diff --git a/build/lib.macosx-10.7-x86_64-2.7/_hotbit.so b/build/lib.macosx-10.7-x86_64-2.7/_hotbit.so deleted file mode 100755 index 0cc9a22..0000000 Binary files a/build/lib.macosx-10.7-x86_64-2.7/_hotbit.so and /dev/null differ diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/__init__.py b/build/lib.macosx-10.7-x86_64-2.7/box/__init__.py deleted file mode 100644 index 264a032..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from box.atoms import Atoms -from box import md -from box import vtk -from box import systems -from box.grids import GridData -from md import NullCalculator diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/atoms.py b/build/lib.macosx-10.7-x86_64-2.7/box/atoms.py deleted file mode 100644 index 20bd2ca..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/atoms.py +++ /dev/null @@ -1,516 +0,0 @@ -# Copyright (C) 2008 NSC Jyvaskyla -# Please see the accompanying LICENSE file for further information. - -import numpy as npy -from box import mix -from box.data import data - -from ase import units -from ase import Atom as ase_Atom -from ase import Atoms as ase_Atoms -from copy import copy -vec=npy.array - - -class Atoms(ase_Atoms): - """A class for cluster structures - to enable simplified manipulation""" - - def __init__(self, *args, **kwargs): - - - if kwargs.get('filename') is not None: - filename = kwargs.pop('filename') - ase_Atoms.__init__(self, *args, **kwargs) - #ase_Atoms.read(self,filename, kwargs.get('filetype')) - #elif isinstance(args[0],ase_Atoms): - #self=args[0] - #print 'dsdsdsdsdgsdgsdgsdg' - #assert False - else: - ase_Atoms.__init__(self, *args, **kwargs) - - self.data={} - self.set_data() - self.analyzed=[] - - def set_calculator(self,calc=None): - ase_Atoms.set_calculator(self,calc) - if calc!=None: - self._update() - - def set_positions(self,r): - """ If calc is set, system should be reasonable for updating. """ - ase_Atoms.set_positions(self,r) - if self.calc!=None: - self._update() - - def set_cell(self,cell,**kwargs): - """ If calc is set, system should be reasonable for updating. """ - ase_Atoms.set_cell(self,cell,**kwargs) - if self.calc!=None: - self._update() - - def set_data(self): - """ Read element data in. """ - symbols=self.get_chemical_symbols() - keys=data[symbols[0]].keys() - for key in keys: - self.data[key]=[data[symbol][key] for symbol in symbols] - - def get_name(self): - """ Get the name of the system, e.g. 'benzene'. Default are symbols, 'H2O' """ - if 'atoms_name' in self.data: - return self.data['atoms_name'] - else: - symbols=self.get_chemical_symbols() - dict={} - for symbol in symbols: - n=symbols.count(symbol) - if n not in dict: - dict.update({symbol:n}) - name='' - for symbol in dict: - if dict[symbol]<2: - name+=symbol - else: - name+=symbol+str(dict[symbol]) - self.data['atoms_name']=name - return name - - def get_N(self): - return len(self.get_positions()) - - def set_name(self,name): - """ Give the system a name, e.g. 'benzene' """ - self.name=name - - def _update(self): - """ After changing cell or atom positions, make checks etc. """ - self._check_cell_orthogonality() - self._reduce_atoms_into_cell() - - def _reduce_atoms_into_cell(self): - """ - Collect all atoms into the 'first' unit cell (0<=xL[a]: - raise ValueError('Atom %i at %f outside box in non-pbc direction %i' %(i,r[i,a],a) ) - ase_Atoms.set_positions(self,r) - - def _check_cell_orthogonality(self): - """ - Non-orthogonality of unit cell is not implemented yet. - """ - for a in range(3): - aux=range(3) - aux.pop(a) - if npy.any(self.cell[a,aux]>1E-9): - raise NotImplementedError('Unit cell not orthogonal.') - return True - - def get_cell_axes(self): - """ - Lengths of the unit cell axes (currently for orthonormal cell). - """ - return self.cell[0,0],self.cell[1,1],self.cell[2,2] - - def vector(self,ri,rj=None,mic=True): - """ - Return the vector ri or rj-ri, normally within the minimum image convention (mic). - - parameters: - ----------- - ri: initial point (atom index or position) - rj: final point (atom index or position) - """ - if not mic: - raise NotImplementedError('Why not use mic?') - R=self.positions - if type(ri)==type(1): - Ri=R[ri].copy() - else: - Ri=ri.copy() - if rj==None: - Rj=None - elif type(rj)==type(1): - Rj=R[rj].copy() - else: - Rj=rj - - if Rj==None: - rij=Ri - else: - rij=Rj-Ri - - L=self.get_cell_axes() - for a in range(3): - if self.pbc[a]: - rij[a]=npy.mod(rij[a]+0.5*L[a],L[a]) - 0.5*L[a] - return vec(rij) - - def distance(self,ri,rj=None,mic=True): - """ - Return the length of |ri| or |rj-ri|, normally within the minimum image convention. - """ - if rj==None: - return mix.norm(self.vector(ri,mic)) - else: - return mix.norm(self.vector(ri,rj,mic)) - - def displace_atoms_randomly(self,dR=0.05): - """ - Displace atoms with random positions up to given radii - with Gaussian profile (sigma=dR/2). - Same for all atoms or list of radii for all atoms. - """ - from numpy.random import normal - sin=npy.sin - cos=npy.cos - R=self.get_positions() - if type(dR)!=type([]): - dR=[dR]*len(R) - for i in range(len(R)): - phi,theta=mix.random_direction() - disp=min(normal(scale=dR[i]/2),dR[i]) - R[i]=R[i]+disp*vec([sin(theta)*cos(phi),sin(theta)*sin(phi),cos(theta)]) - self.set_positions(R) - - def scale_positions(self,x): - """ Scale the whole system by x; also the unit cell. """ - self.set_cell(self.get_cell()*x,scale_atoms=True) - self._reduce_atoms_into_cell() - - - def copy(self): - """ Override ase atoms copy (not to get ase.Atoms type) """ - from copy import copy - return copy(self) - #atoms = Atoms(cell=self.cell, pbc=self.pbc) - #atoms.arrays = {} - #for name, a in self.arrays.items(): - #atoms.arrays[name] = a.copy() - #return atoms - - def spatial_spans(self): - r=self.get_positions() - return vec([max(r[:,a])-min(r[:,a]) for a in range(3)]) - - def get_kinetic_temperature(self,fixed=0,internal=False): - """ Use equipartition to get temp (in K) without 'fixed' number degr. of freedom. """ - if not internal: - return self.get_kinetic_energy()*2 / ((3*self.get_N()-fixed)*units.kB) - elif internal: - assert fixed==0 - raise NotImplementedError('todo: get kinetic energy with removed cm translation and rotation') - - def get_total_energy(self): - """ Return potential+kinetic energy. """ - return self.get_kinetic_energy() + self.get_potential_energy() - - #def __iter__(self): - #""" Initialize iterator. """ - #self.itr=-1 - #return self - - #def next(self): - #""" Iterator over atoms. """ - #self.itr+=1 - #if self.itr==self.N: - #raise StopIteration - #return self.atoms[self.itr] - - def set_cell(self,cell,scale_atoms=False): - """ Override Atoms.set_cell with default atom fixing. """ - ase_Atoms.set_cell(self,cell,scale_atoms=scale_atoms) - - def angular_momentum(self): - assert NotImplementedError() - - def moments_of_inertia(self,rcm=True): - """ Return the moments and principal axes of inertia (wrt. center of mass if rcm is True) """ - r=self.get_positions() - mass=self.get_masses() - N=len(r) - if rcm: - cm=self.get_center_of_mass() - r-=cm - - # make inertia tensor and solve its eigenvalues (principal moments - # of inertia) and eigenvectors (principal axis of inertia) - tensor=npy.zeros((3,3)) - diag=sum([mass[k]*sum(r[k,:]**2) for k in range(N)]) - for i in range(3): - tensor[i,i]=diag - for j in range(3): - tensor[i,j]=tensor[i,j]-sum([mass[k]*r[k,i]*r[k,j] for k in range(N)]) - - eigs,vectors=npy.linalg.eigh(tensor) - return eigs,vectors - - def center_of_mass_to_origin(self): - assert NotImplementedError() - - def remove_rotations(self): - assert NotImplementedError() - - def atom_distribution_wrt_point(self,point=None): - assert NotImplementedError() - #of point==None, point=center_of_mass - - def spatial_extrema(self): - assert NotImplementedError() - #return minx,maxx,miny,maxy,.. - - def radial_distribution_function(self): - assert NotImplementedError() - #within minimum image convention (max of function= minimum box length/2) - - def coordination_numbers(self): - assert NotImplementedError() - - def mean_bond_length(self): - """ Return mean bond length using pair distribution function. """ - pdf = self.pair_distribution_function() - max = False - eps = 1e-6 - # find the first max and following min of pair distr. fct - if self.get_N()==2: - return self.distance(0,1) - else: - for i in xrange(len(pdf)-1): - if pdf[i,1]>pdf[i+1,1]: max=True - if max==True and (pdf[i,1]pdf[i+1,1]: max=True - if max==True and (pdf[i,1]>f, 'VECTORS %s double\n' %property - for value in properties: - print>>f, mix.a2s(value,fmt=fmt) - else: - try: - x=float(properties[0]) - except: - continue - print>>f, 'SCALARS %s double 1\nLOOKUP_TABLE default' %property - for value in properties: - print>>f, '%12.6f' %(value*1.0) - - - # Then data related to bonds - print>>f, 'CELL_DATA %i' %nb - print>>f, 'SCALARS bond_length double 1\nLOOKUP_TABLE default' - for bond in bonds: - f.write( '%f\n' %bond['length'] ) - f.close() - - - - - #def __add__(self, other): - #""" - #Add (one) atom or another molecule. - #Note: completely new molecule constructed. - #""" - #new=copy(self.atoms) - #if type(other)==type(Molecule()): - #for atom in other: - #new.append(atom) - #else: - #new.append(other) - #return Molecule(new) - - - - - - #def get_charge(self): - #def copy to periodic directions (gpaw->hotbit calculations...) - #def get(self,property): - - - - #def sp_occupations(self,excess_el=0): - #energy_as_separated(self,excess_el=0): - #return IE,EA - - - - - #def read_bonds(self,file): - #""" - #Read bond information from given file. - - #* file -- file name of file object where the bonding info is read (for - #file object the "next" data set is read.) - #""" - #self.N_bonds=0 - #f,opened=mix.file_safeopen(file) - #lines=mix.read(file,fmt='string') - #self.bonds=[] - #print file - #for line in lines: - #self.N_bonds +=1 - #i,j,B,r = line.split() - #self.bonds.append( [int(i)-1,int(j)-1,float(B)] ) - - - - - - - - -if __name__=='__main__': - print 'atoms test run' - atoms=Atoms(symbols='H2O',positions=[(1,0,0),(0,1,0),(0,0,0)]) - atoms.set_cell([50,50,50]) - atoms.set_pbc(True) - print 'H2O:\n',atoms.get_positions() - atoms.reduce_atoms_into_cell() - print 'H2O:\n',atoms.get_positions() - print atoms.vector(vec([0,0,0]),vec([0,4.9,0])) - - print 'mean bond length',atoms.mean_bond_length() - print 'number of bonds',atoms.number_of_bonds() - #print 'pair list',atoms.pair_distribution_list() - print atoms.get_name() - atoms.write_vtk('koe.vtk') - - #print 'pdf',atoms.pair_distribution_function() - #pdf=atoms.pair_distribution_function() - #import pylab as p - #p.plot(pdf[:,0],pdf[:,1]) - #p.show() - ##many=Atoms(symbols='H500',positions=[(10,10,10) for x in range(500)],cell=(20,20,20),pbc=True ) - #many.displace_atoms_randomly(dR=7.0) - #from ase import write - #write('shake.xyz',many) - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/barriers.py b/build/lib.macosx-10.7-x86_64-2.7/box/barriers.py deleted file mode 100644 index fec282b..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/barriers.py +++ /dev/null @@ -1,450 +0,0 @@ -import os -from box import Atoms -from box import md -import numpy as np -import ase -from box.interpolation import VectorSplineFunction -#from box.calculators import Calculator -from scipy.linalg import norm -import pylab as pl -vec=np.array - - -class LEPS_Calculator: - """ ase Calculator class """ - - def __init__(self): - """ - Construct calculator for ase.Atoms class using - V_LEPS potential from NEB papers. It looks like this: - - .A...||||||........ - ......||||......... - .......||.......... - ................... - .......|........... - .......||.......... - ......||||......... - .....||||||......B. - ....||||||||....... - - This is designed only for a single atom -Atoms-object. - """ - self.it=0 - - def _V_LEPS(self,rab,rbc): - """ - The complicated part in the function definition. - """ - def Q(r,alpha,r0,d): return d/2.*( 3./2*np.exp(-2*alpha*(r-r0))-np.exp(-alpha*(r-r0)) ) - def J(r,alpha,r0,d): return d/4.*( np.exp(-2*alpha*(r-r0))-6*np.exp(-alpha*(r-r0)) ) - - a=0.05 - b=0.3 - c=0.05 - dab=4.746 - dbc=4.746 - dac=3.445 - r0=0.742 - alpha=1.942 - ai=1.0/(1+a) - bi=1.0/(1+b) - ci=1.0/(1+c) - Qab=Q(rab,alpha,r0,dab) - Qbc=Q(rbc,alpha,r0,dbc) - Qac=Q(rab+rbc,alpha,r0,dac) - Jab=J(rab,alpha,r0,dab) - Jbc=J(rbc,alpha,r0,dbc) - Jac=J(rab+rbc,alpha,r0,dac) - return Qab*ai+Qbc*bi+Qac*ci-np.sqrt(Jab**2*ai**2+Jbc**2*bi**2+Jac**2*ci**2\ - -Jab*Jbc*ai*bi-Jbc*Jac*bi*ci-Jab*Jac*ai*ci) - - def aux(self,rab,xx): - rac=3.742 - kc=0.2025 - c=1.154 - return self._V_LEPS(rab,rac-rab)+2*kc*(rab-(rac/2-xx/c))**2 - - def _function(self,x,y,der=0): - """ LEPS potential written for 'atomic' positions x and y. """ - # use auxiliary function - d=1E-6 - if der==0: - return self.aux(x,y) - elif der==1: - return [(self.aux(x+d,y)-self.aux(x,y))/d,(self.aux(x,y+d)-self.aux(x,y))/d] - - def get_potential_energy(self,atoms): - r=atoms.get_positions() - return self._function(r[0,0],r[0,1]) - - def __call__(self,r): - return self.f(r) - - def set_atoms(self,atoms): - assert len(atoms)==1 - - def get_forces(self,atoms): - """ Forces from LEPS potential for the one atom. """ - r=atoms.get_positions() - der=self._function(r[0,0],r[0,1],der=1) - f0=-vec([der[0],der[1],0.0]) - return vec([f0]) - #if len(r)==1: - #return vec([f0]) - #else: - #return vec([f0,vec([0]*3)*(len(r)-1)]) - - def get_stress(self,atoms): - """ This just has to exist. """ - return None - - def plot(self,scatter=None,screen=True,out=None): - """ Plot the VLEP landscape. """ - X = np.linspace(0.5,3.2,100) - Y = np.linspace(-2,1.4,100) - Z=np.zeros((100,100)) - for i,x in enumerate(X): - for j,y in enumerate(Y): - Z[j,i]=self._function(x,y) - - pl.contourf(X,Y,Z,100) - pl.hot() - - if scatter!=None: - pl.scatter(scatter[0,:],scatter[1,:],color='b') - #if plot!=None: - #pl.plot(plot[0,:],plot[1,:],color='y') - #pl.scatter(plot[0,:],plot[1,:],color='y') - - if screen==True: - pl.show() - else: - assert out!=None - pl.savefig(out) - pl.clf() - self.it+=1 - - - - -class MEP: - def __init__(self,images,calc): - self.images=images - self.N=len(images[0]) - self.M=len(images) - self.dim=self.M*self.N*3 - self.calc=calc - self.it=0 - self.dir='MEP' - if not os.path.isdir(self.dir): - os.system('mkdir %s' %self.dir) - self.lock=False - self.lambdas=None - - - def has(self,key): - return False - - - def __len__(self): - return self.M*self.N - - #def set_optimizer(self,optimizer): - #""" Set the optimizer used to optimize the whole path. """ - #self.optimizer=optimizer - - def interpolate(self): - """ Use linear interpolation for the images. """ - first=self.images[0].get_positions() - last=self.images[-1].get_positions() - for i in range(1,self.M-1): - self.images[i].set_positions(first+i*1.0/(self.M-1.0)*(last-first)) - - - def lock_positions(self): - self.lock=True - - - def release_positions(self): - self.lock=False - - - def set_positions(self,positions): - """ Set positions for images, given positions for M*N 'atoms'. """ - if self.lock: - self.positions2=np.zeros((self.M,self.N,3)) - n1 = 0 - for i in range(len(self.images)): - n2 = n1 + self.N - self.positions2[i] = positions[n1:n2] - n1 = n2 - self.positions2.shape=(self.M,self.N*3) - return - - n1 = 0 - for image in self.images: - n2 = n1 + self.N - image.set_positions(positions[n1:n2]) - n1 = n2 - - def get_lambda_guess(self): - #if self.lambdas==None: - self.it+=1 - R=self.get_positions() - #R.shape=(self.M,self.N,3) - out='%s/landscape_%04i.png' %(self.dir,self.it) - #print R - #R.shape=(self.M,self.N,3) - #print R - #assert False - #print vec([R[:,0],R[:,1]]) - - self.calc.plot(scatter=vec([R[:,0],R[:,1]]),screen=False,out=out) - - if self.lambdas==None: - return [0.]*(self.M-1) - else: - return self.lambdas - - def get_max_constraint_deviation(self): - """ Return max( |R[i]-R[i-1]|-L/(M-1) ) """ - R=self.get_positions() - R.shape=(self.M,self.N*3) - - D=np.zeros(self.M-1) - for i in range(self.M-1): - D[i] = np.linalg.norm(R[i+1]-R[i]) - L1=sum(D)/(self.M-1) - return max( abs(D-L1) )/L1 - - - - def get_constraint_deviations(self): - """ Return how much we deviatie from the M-1 constraints. """ - dev=[] - L=0.0 - try: - R=self.positions2 - except: - R=self.get_positions() - R.shape=(self.M,self.N*3) - for i in range(self.M-1): - Di=np.linalg.norm(R[i+1]-R[i]) - L+=Di - dev.append( Di ) - return np.array(dev) - L/(self.M-1) - - - def get_positions(self): - """ Get path positions, as for M*N 'atoms'. """ - positions = np.empty((self.M*self.N,3)) - n1 = 0 - for image in self.images: - n2 = n1 + self.N - positions[n1:n2] = image.get_positions() - n1 = n2 - return positions - - - def get_potential_energy(self): - """ Return value of the objective function (sum of all energies). """ - return sum( [self.calc.get_potential_energy(image) for image in self.images] ) - - - def _get_potential_forces(self): - """ Return forces only from potential energy. - (first and last images should be optimized already.) - """ - F=[vec([0.0]*3*self.N)] - for image in self.images[1:-1]: - F.append(self.calc.get_forces(image).reshape(3*self.N)) - F.append(vec([0.0]*3*self.N)) - return vec(F) - - - def _get_constraint_forces(self,lambdas): - """ Return the constraint forces for given lambdas (Lagrange multipliers). """ - assert len(lambdas)==self.M-1 - R=self.get_positions() - R.shape=(self.M,self.N*3) - - #M=np.zeros((self.M-1,self.M-1)) - #for i in range(self.M-1): - #for j in range(self.M-1): - #M[i,j]= - - d=[] - for i in range(self.M-1): - D=R[i+1]-R[i] - d.append( D/np.linalg.norm(D) ) - - lambda0=sum(lambdas)/(self.M-1) - F=[vec([0.0]*3*self.N)] - for k in range(1,self.M-1): - F.append( d[k-1]*(lambdas[k-1]-lambda0) - d[k]*(lambdas[k]-lambda0) ) - F.append(vec([0.0]*3*self.N)) - return vec(F) - - def set_lambdas(self,lambdas): - self.lambdas=lambdas - - def get_forces(self): - f0=self._get_potential_forces() - fc=self._get_constraint_forces(self.lambdas) - F = f0 + fc - F.shape=(self.M*self.N,3) - return F - - - - - - - #k=1000 - #for i in range(1,self.M-1): - #tangent=ip.normalized_tangent(t[i]) - #F_homo=-k*np.vdot((R[i]-Rh[i]),tangent)*tangent - #F_tan=np.vdot(tangent,F[i])*tangent - #print 'homo:',norm(F_homo),'tan:',norm(F_tan) - #F[i]=F[i]-F_tan+F_homo - - #F=vec(F) - #F.shape=(self.M*self.N,3) - #self.it+=1 - #rr=ip.homogenize(200) - #Rh.shape=(self.M,self.N*3) - #out='%s/landscape_%04i.png' %(self.dir,self.it) - #self.calc.plot((0.5,3.2,-2.0,1.5),scatter=vec([R[:,0],R[:,1]]),\ - #plot=vec([Rh[:,0],Rh[:,1]]),out=out) - #ip.plot(out='%s/interpol_%04i.png' %(self.dir,self.it)) - - #return vec(F) - - - - - - -class BTI: - def __init__(self,images,calc): - self.images=images - self.N=len(images[0]) - self.M=len(images) - self.dim=self.M*self.N*3 - self.calc=calc - self.it=0 - self.dir='MEP' - if not os.path.isdir(self.dir): - os.system('mkdir %s' %self.dir) - - def __len__(self): - return self.M*self.N - - def get_energy(self,image): - """ Return energy for given image. """ - - def initial_interpolation(self): - first=self.images[0].get_positions() - last=self.images[-1].get_positions() - for i in range(1,self.M-1): - self.images[i].set_positions(first+i*1.0/(self.M-1.0)*(last-first)) - - - def get_forces(self): - R=self.get_positions() - R.shape=(self.M,self.N*3) - ip=VectorSplineFunction(R,k=3,s=0) - Rh=ip.homogenize() - t=ip.closest_parameters(Rh) - - # draw tangents - #if False: - tangents=vec(ip.tangents()) - tangents.shape=(self.M,self.N,3) - for image,i in zip(self.images,range(self.M)): - image.set('tangent',tangents[i,:,:]) - image.write_vtk('%s/image_%04i_%04i.vtk' %(self.dir,self.it,i)) - - F=[vec([0.0]*3*self.N)] - for image in self.images[1:-1]: - image.set_calculator(self.calc) - F.append(image.get_forces().reshape(3*self.N)) - F.append(vec([0.0]*3*self.N)) - - k=1000 - for i in range(1,self.M-1): - tangent=ip.normalized_tangent(t[i]) - F_homo=-k*np.vdot((R[i]-Rh[i]),tangent)*tangent - F_tan=np.vdot(tangent,F[i])*tangent - print 'homo:',norm(F_homo),'tan:',norm(F_tan) - F[i]=F[i]-F_tan+F_homo - - F=vec(F) - F.shape=(self.M*self.N,3) - self.it+=1 - rr=ip.homogenize(200) - Rh.shape=(self.M,self.N*3) - out='%s/landscape_%04i.png' %(self.dir,self.it) - self.calc.plot((0.5,3.2,-2.0,1.5),scatter=vec([R[:,0],R[:,1]]),\ - plot=vec([Rh[:,0],Rh[:,1]]),out=out) - ip.plot(out='%s/interpol_%04i.png' %(self.dir,self.it)) - - return vec(F) - - - def get_potential_energy(self): - E=[] - for image in self.images: - image.set_calculator(self.calc) - E.append(image.get_potential_energy()) - return max(E) - - def set_positions(self,positions): - n1 = 0 - for image in self.images: - n2 = n1 + self.N - image.set_positions(positions[n1:n2]) - n1 = n2 - - def get_positions(self): - positions = np.empty((self.M*self.N,3)) - n1 = 0 - for image in self.images: - n2 = n1 + self.N - positions[n1:n2] = image.get_positions() - n1 = n2 - return positions - - - -if __name__=='__main__': - fmax=1E-4 - calc=Hotbit(potential='neb_model_1') - first=Atoms(symbols='H',positions=[(3.0,-1.3,0.0)]) #,(0,0,0)]) - first.set_calculator(calc) - md.quench_atoms(first,fmax=fmax) - print 'first minimum:',first.get_positions()[0] - - - - last=Atoms('H',[(0.77,1.31,0.0)]) #,(0,0,0)]) - last.set_calculator(calc) - md.quench_atoms(last,fmax=fmax) - print 'last minimum:',last.get_positions()[0] - - - images=[first.copy() for x in range(10)] - images.append(last) - - - bti=BTI(images,calc) - bti.initial_interpolation() - qn=ase.MDMin(bti,dt=0.05) - writer=md.TrajectoryWriter(images,name='test') - qn.attach(writer) - qn.run(fmax=fmax) - - - - \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/brillouin_zone.py b/build/lib.macosx-10.7-x86_64-2.7/box/brillouin_zone.py deleted file mode 100644 index 3e6aaa2..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/brillouin_zone.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Contains data for high symmetry points in different structures. -""" - -import numpy as np - -import ase.dft.kpoints as kpoints - -_Gamma = [ 0.00, 0.00, 0.00 ] -_X = [ 1.00, 0.00, 0.00 ] -_W = [ 1.00, 0.50, 0.00 ] -_K = [ 0.75, 0.75, 0.00 ] -_L = [ 0.50, 0.50, 0.50 ] - -_fcc_a1 = [ 0., 1./2, 1./2 ] -_fcc_a2 = [ 1./2, 0., 1./2 ] -_fcc_a3 = [ 1./2, 1./2, 0. ] -_fcc_A = np.array( [ _fcc_a1, _fcc_a2, _fcc_a3 ] ) - -symmetry_points = { - 'fcc': { - 'Gamma': np.dot(_fcc_A, _Gamma), - 'X': np.dot(_fcc_A, _X), - 'W': np.dot(_fcc_A, _W), - 'K': np.dot(_fcc_A, _K), - 'L': np.dot(_fcc_A, _L) - } - } - -band_structures = { - 'fcc': [ 'Gamma', 'X', 'W', 'K', 'Gamma', 'L', 'W' ] - } - - -def get_bandpath(crystal, cell, npoints=50): - """ - Return a list of k-points sampling the band-structure for the respective - crystal. - """ - bs = band_structures[crystal] - symp = symmetry_points[crystal] - - points = reduce( - lambda y1, y2: y1+y2, - [ [ symp[x1], symp[x2] ] for x1, x2 in zip(bs[:-1], bs[1:]) ] - ) - - return kpoints.get_bandpath(points, cell, npoints) diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/broaden.py b/build/lib.macosx-10.7-x86_64-2.7/box/broaden.py deleted file mode 100644 index 7fa5a50..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/broaden.py +++ /dev/null @@ -1,42 +0,0 @@ -import numpy as np - - -def gaussian_peak(grid, x0, FWHM): - """ Return a normalized gaussian peak with FWHM=width - in the given grid. """ - a = np.sqrt(4*np.log(2)/np.pi)/FWHM - b = 4*np.log(2)/FWHM**2 - return a*np.exp( - b*(grid-x0)**2 ) - - -def broaden(grid, values, width, weights=None): - """ Broaden given values with Gaussian distributions over - given grid. Width is the FWHM of the peak, and values - can be provided with different weights (default value - is that the weights are 1 for all values). Each peak - integrates to the corresponding weight.""" - if weights == None: - weights = np.ones_like(values) - ret = np.zeros_like(grid) - for val, weight in zip(values, weights): - ret += weight * gaussian_peak(grid, val, width) - return ret - - -def make_cumulative_plot(grid, values, width, weights_list, labels=None, colors=None): - """ Make a cumulative plot from the values that are broadened with - gaussian distributions of FWHM=width. The weights_list is an - array of the shape [:,len(values)]. """ - import pylab - if labels == None: - labels = ['_nolegend_' for i in range(len(weights_list))] - if colors == None: - colors = np.random.random((len(values), 4)) - colors[:,3] = 1 - low = np.zeros_like(grid) - for weights, color, label in zip(weights_list, colors, labels): - up = low + broaden(grid, values, width, weights) - x, y = pylab.poly_between(grid, low, up) - pylab.fill(x, y, facecolor=color, edgecolor='none', label=label) - low = up - diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/buildmixer.py b/build/lib.macosx-10.7-x86_64-2.7/box/buildmixer.py deleted file mode 100644 index 4a1a7d3..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/buildmixer.py +++ /dev/null @@ -1,19 +0,0 @@ -from box.misc import AndersonMixer -from box.pulay import PulayMixer - -mixers = {'pulay':PulayMixer, 'anderson':AndersonMixer} - -def BuildMixer(params): - if params == None: - return mixers['anderson']() - elif type(params) == str: - name = params - return mixers[name.lower()]() - elif type(params) == dict and 'name' in params: - p = params.copy() - name = p['name'].lower() - p.pop('name') - return mixers[name](**p) - else: - raise Exception('You must provide the name of the mixer.') - diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/calculators.py b/build/lib.macosx-10.7-x86_64-2.7/box/calculators.py deleted file mode 100644 index e345716..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/calculators.py +++ /dev/null @@ -1,2 +0,0 @@ -# nothing here - \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/convergence_plotter.py b/build/lib.macosx-10.7-x86_64-2.7/box/convergence_plotter.py deleted file mode 100644 index fca9515..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/convergence_plotter.py +++ /dev/null @@ -1,62 +0,0 @@ -import numpy as np - -class ConvergencePlotter: - """ Show Mulliken excess charges generated during the iterative - solving cycle. """ - - def __init__(self, calc): - M = 10 # how many steps to show - N = len(calc.el) - self.maxiter = min(calc.st.solver.maxiter, M) - self.title = calc.el.get_name() + ", %i last excess Mulliken populations, (red=latest, green=oldest)" % self.maxiter - self.N1 = self.maxiter/2 - if self.maxiter % 2 == 0: - self.N2 = self.maxiter/2 - else: - self.N2 = self.maxiter/2+1 - # colors from green to yellow - colors1 = [(n,1,0) for n in np.linspace(0,1,self.N1)] - # colors from yellow to red - colors2 = [(1,1-n,0) for n in np.linspace(0,1,self.N2)] - self.colors = colors1 + colors2 - self.it = 0 - self.iters_saved = 0 - self.points = np.zeros((self.maxiter,N)) - self.points2 = [] - - def color(self): - """ Return next color. """ - ret = self.colors[self.it] - self.it += 1 - return tuple(ret) - - def draw(self, dq): - """ Add points to be shown later. """ - self.iters_saved += 1 - self.points2.append(dq) - self.points[1:self.maxiter] = self.points[0:self.maxiter-1] - self.points[0] = dq - - def show(self): - """ Show the last M points that are still in the memory. """ - try: - import pylab - except ImportError: - print "Could not import pylab, cannot print the Mulliken excess charges." - return - for p in self.points[:self.iters_saved][::-1]: - c = self.color() - pylab.scatter(range(len(p)), p, color=c) - pylab.title(self.title) - pylab.xlabel('atom index') - pylab.ylabel('Mulliken excess population') - pylab.savefig('mulliken_charge_fluctuations_%i.eps' % self.maxiter) - pylab.figure() - pylab.title('Mulliken excess charges evolution') - pylab.xlabel('iteration') - pylab.ylabel('excess population') - P=np.array(self.points2) - for p in P.transpose(): - pylab.plot(range(len(p)), p) - pylab.savefig('Mulligen_population_evolution.eps') - pylab.show() diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/data.py b/build/lib.macosx-10.7-x86_64-2.7/box/data.py deleted file mode 100644 index 24cd83d..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/data.py +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright (C) 2008 NSC Jyvaskyla -# Please see the accompanying LICENSE file for further information. -# -# Experimental data * mass, R_cov (2008 data), R_vdw, EA from www.webelements.com -# * IE from gElemental 1.2.0 -# -# UNITS: -# * mass in amu -# * all radii in Angstrom -# * all energies in eV -# -from numpy import nan - -data={} - -data['H'] ={'Z':1, 'symbol':'H', 'name':'hydrogen', 'mass': 1.0079, 'R_cov':0.31,'R_vdw':1.20,'IE':0.0135,'EA':72.27 } -data['He']={'Z':2, 'symbol':'He'} -data['Li']={'Z':3, 'symbol':'Li', 'R_cov':1.28} -data['Be']={'Z':4, 'symbol':'Be'} -data['B'] ={'Z':5, 'symbol':'B'} -data['C'] ={'Z':6, 'symbol':'C', 'name':'carbon', 'mass':12.0107, 'R_cov':0.76,'R_vdw':1.70,'IE':11.256,'EA':1.594} -data['N'] ={'Z':7, 'symbol':'N', 'name':'nitrogen', 'mass':14.0067, 'R_cov':0.71,'R_vdw':1.55,'IE':14.527,'EA':0.072} -data['O'] ={'Z':8, 'symbol':'O', 'name':'oxygen', 'mass':15.9994, 'R_cov':0.66,'R_vdw':1.52,'IE':13.612,'EA':1.460} -data['F'] ={'Z':9, 'symbol':'F'} -data['Ne']={'Z':10,'symbol':'Ne'} -data['Na']={'Z':11,'symbol':'Na','name':'sodium', 'mass':22.9898, 'R_cov':1.66,'R_vdw':2.27,'IE':5.136, 'EA':0.547} -data['Mg']={'Z':12,'symbol':'Mg','name':'magnesium','mass':24.3050, 'R_cov':1.41,'R_vdw':1.73,'IE':7.642, 'EA':0.000} -data['Si']={'Z':14,'symbol':'Si','name':'silicon', 'mass':28.0855} -data['S'] ={'Z':16, 'symbol':'S', 'name':'sulfur', 'mass':32.065, 'R_cov':1.02,'R_vdw':1.80,'IE':999.6, 'EA':200} #FIXME these are kJ/mol, what are the others? -data['Cl']={'Z':17,'symbol':'Cl','name':'chlorine', 'mass':35.4530, 'R_cov':1.02,'R_vdw':1.75,'IE':12.962,'EA':3.615} -data['Ar']={'Z':18,'symbol':'Ar'} -data['K'] ={'Z':19,'symbol':'K', 'name':'potassium','mass':39.0983, 'R_cov':2.03,'R_vdw':2.75,'IE':4.338, 'EA':0.501} -data['Ti']={'Z':22,'symbol':'Ti','name':'titanium', 'mass':47.8760, 'R_cov':1.60,'R_vdw':2.15,'IE':6.825, 'EA':0.078} -data['Kr']={'Z':36,'symbol':'Kr'} -data['Sr']={'Z':38,'symbol':'Sr','name':'strontium','mass':87.62, 'R_cov':1.95,'R_vdw':2.49, 'IE':5.69,'EA':0.052} -data['Pd']={'Z':46,'symbol':'Pd'} -data['Sn']={'Z':50, 'symbol':'Sn', 'R_cov':1.39} -data['Xe']={'Z':54,'symbol':'Xe'} -data['Pt']={'Z':78,'symbol':'Pt','name':'platinum', 'mass':195.084, 'R_cov':1.36,'R_vdw':1.75,'IE':9.013, 'EA':2.127} -data['Au']={'Z':79,'symbol':'Au','name':'gold', 'mass':196.9666, 'R_cov':1.36,'R_vdw':1.66,'IE':9.221, 'EA':2.308} - -# update with valence orbital data -valence_orbitals={} -valence_orbitals['H'] =['1s'] -valence_orbitals['He']=['1s'] -valence_orbitals['Li']=['2s','2p'] -valence_orbitals['Be']=['2s','2p'] -valence_orbitals['B'] =['2s','2p'] -valence_orbitals['C'] =['2s','2p'] -valence_orbitals['N'] =['2s','2p'] -valence_orbitals['O'] =['2s','2p'] -valence_orbitals['F'] =['2s','2p'] -valence_orbitals['Ne']=['2s','2p'] -valence_orbitals['Na']=['3s','3p'] -valence_orbitals['Mg']=['3s','3p'] -valence_orbitals['Si']=['3s','3p'] -valence_orbitals['S'] =['3s','3p'] -valence_orbitals['Cl']=['3s','3p'] -valence_orbitals['Ar']=[] -valence_orbitals['K']=['4s','4p'] -valence_orbitals['Ti']=['3d','4s','4p'] -valence_orbitals['Kr']=[] -valence_orbitals['Sr']=['5s','5p','4d'] -valence_orbitals['Pd']=['5s','5p','4d'] -valence_orbitals['Sn']=['5s','5p'] -valence_orbitals['Xe']=[] -valence_orbitals['Pt']=['6s','6p','5d'] -valence_orbitals['Au']=['6s','6p','5d'] - -for key in valence_orbitals: - data[key]['valence_orbitals']=valence_orbitals[key] - - - -# Set electronic configurations (orbital occupations) -aux=[ ['H', '',{'1s':1}],\ - ['He','',{'1s':2}],\ - # second row - ['Li','He',{'2s':1,'2p':0}],\ - ['Be','He',{'2s':2,'2p':0}],\ - ['B', 'He',{'2s':2,'2p':1}],\ - ['C', 'He',{'2s':2,'2p':2}],\ - ['N', 'He',{'2s':2,'2p':3}],\ - ['O', 'He',{'2s':2,'2p':4}],\ - ['F', 'He',{'2s':2,'2p':5}],\ - ['Ne','He',{'2s':2,'2p':6}],\ - # third row - ['Na','Ne',{'3s':1,'3p':0}],\ - ['Mg','Ne',{'3s':2,'3p':0}],\ - ['Si','Ne',{'3s':2,'3p':2}],\ - ['S', 'Ne',{'3s':2,'3p':4}],\ - ['Cl','Ne',{'3s':2,'3p':5}],\ - ['Ar','Ne',{'3s':2,'3p':6}],\ - # fourth row - ['K', 'Ar',{'4s':1,'4p':0}],\ - ['Ti','Ar',{'3d':2,'4s':2,'4p':0}],\ - ['Kr','Ar',{'3d':10,'4s':2,'4p':6}],\ - # fifth row - ['Sr','Kr',{'5s':2,'4d':0,'5p':0}], - ['Sn','Kr',{'4d':10,'5s':2,'5p':2}], - ['Pd','Kr',{'4d':10,'5s':0,'5p':0}], - ['Xe','Kr',{'4d':10,'5s':2,'5p':6}], - # sixth row - ['Pt','Xe',{'4f':14,'5d':9,'6s':1,'6p':0}], - ['Au','Xe',{'4f':14,'5d':10,'6s':1,'6p':0}] ] - -configurations={} -for item in aux: - el, core, occu=item - if core!='': - configurations[el]=configurations[core].copy() - else: - configurations[el]={} - configurations[el].update(occu) -for key in configurations: - config=configurations[key] - data[key]['configuration']=config - data[key]['valence_number']=sum( [config[orbital] for orbital in data[key]['valence_orbitals']] ) - -if __name__=='__main__': - for symbol in data: - print 'X'*40 - for d in data[symbol]: - print d,data[symbol][d] - - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/distort.py b/build/lib.macosx-10.7-x86_64-2.7/box/distort.py deleted file mode 100644 index fc509a9..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/distort.py +++ /dev/null @@ -1,49 +0,0 @@ -# -# Auxiliary functions for distorting nanomaterials -# -import numpy as np -from hotbit import Atoms - - -def setup_bending(atoms,angle,radius,rotation=0.0,physical=True): - """ - Prepare a bending setup for a tube or slab. - - Tube should be originally periodic in z-direction with - the correct cell, and optionally periodic in y-direction. - - Then atoms are set up for bending with hotbit.Wedge class - with bending wrt. z-axis, and optionally periodic along - z-axis. - - Atoms are first rotated pi/2 around -x-axis, then - rotated an angle 'rotation' around y-axis, then - transformed the distance 'radius' towards x-axis. - The atoms are further adjusted for the wedge angle 'angle'. - 'physical' tells if the angle should be 2*pi/integer. - """ - a = atoms.copy() - a.rotate('-x',np.pi/2) - L = a.get_cell().diagonal() - if abs(L.prod()-a.get_volume())>1E-10: - raise AssertionError('Cell should be orthorhombic.') - pbc = a.get_pbc() - if not pbc[2] or pbc[0]: - raise AssertionError('Should be periodic in z-direction and not periodic in x-direction') - r = a.get_positions() - if np.any( r[:,1]<0 ): # index 1 is correct here - raise AssertionError('For bending, all atoms should be above xy-plane') - - # move and adjust - a.rotate('y',rotation) - for i in range(len(a)): - x,y = r[i,0:2] - R = x + radius - phi = y*angle/L[2] - r[i,0] = R*np.cos(phi) - r[i,1] = R*np.sin(phi) - a.set_positions(r) - a = Atoms(a,container='Wedge') - a.set_container(angle=angle,height=L[1],pbcz=pbc[1],physical=physical) - return a - diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/dummymixer.py b/build/lib.macosx-10.7-x86_64-2.7/box/dummymixer.py deleted file mode 100644 index 89729b4..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/dummymixer.py +++ /dev/null @@ -1,41 +0,0 @@ -class DummyMixer: - """ A dummy mixer that all mixer class should inherit. """ - - - def __init__(self, beta, convergence): - self.name = 'DummyMixer' - self.beta = beta - self.convergence = convergence - self.reset() - - - def reset(self): - self.fmax = [] - self.it = 0 - - - def __call__(self, xi, yi): - return False, yi - - - def get(self, key): - return self.__dict__[key] - - - def echo(self, out): - """ Say something about the progress of iteration. """ - print >> out, "%s: iter %i fmax %0.12f" % (self.name, self.it, self.fmax[-1]) - out.flush() - - - def final_echo(self, out): - print >> out, self.it - - - def out_of_iterations(self, out): - """ Print out-of-iterations info. """ - print>>out, '%s mixer out of iterations!' % self.name - print>>out, 'History of maximum residuals:' - for it,fmax in enumerate(self.fmax): - print>>out, it,fmax - diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/fd_forces.py b/build/lib.macosx-10.7-x86_64-2.7/box/fd_forces.py deleted file mode 100644 index 7d94b53..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/fd_forces.py +++ /dev/null @@ -1,126 +0,0 @@ -""" -Finite-differences computation of forces and the virial. Required by the -test-suite to check consistency of forces, the virial and energy. -""" - -import numpy as np - -import ase - -def check_forces(atoms, dx=1e-6): - """ - Compute forces and compare to forces computed numerically from a - finite differences approach. - """ - - f0 = atoms.get_forces().copy() - ffd = f0.copy() - - for a in atoms: - r0 = a.position.copy() - - a.x = r0[0]-dx - ex1 = atoms.get_potential_energy() - a.x = r0[0]+dx - ex2 = atoms.get_potential_energy() - a.x = r0[0] - - a.y = r0[1]-dx - ey1 = atoms.get_potential_energy() - a.y = r0[1]+dx - ey2 = atoms.get_potential_energy() - a.y = r0[1] - - a.z = r0[2]-dx - ez1 = atoms.get_potential_energy() - a.z = r0[2]+dx - ez2 = atoms.get_potential_energy() - a.z = r0[2] - - ffd[a.index, 0] = -(ex2-ex1)/(2*dx) - ffd[a.index, 1] = -(ey2-ey1)/(2*dx) - ffd[a.index, 2] = -(ez2-ez1)/(2*dx) - - df = ffd-f0 - - return ( ffd, f0, np.max(np.abs(df)) ) - - -def check_field(atoms, calc, dx=1e-6): - """ - Compute electostatic field and compare to electrostatic field computed - numerically from a finite differences approach from the electrostatic - potential. - """ - - E0 = calc.get_field(atoms).copy() - Efd = E0.copy() - - for a in atoms: - r0 = a.position.copy() - - a.set_x(r0[0]-dx) - px1 = calc.get_potential(atoms)[a.index] - a.set_x(r0[0]+dx) - px2 = calc.get_potential(atoms)[a.index] - a.set_x(r0[0]) - - a.set_y(r0[1]-dx) - py1 = calc.get_potential(atoms)[a.index] - a.set_y(r0[1]+dx) - py2 = calc.get_potential(atoms)[a.index] - a.set_y(r0[1]) - - a.set_z(r0[2]-dx) - pz1 = calc.get_potential(atoms)[a.index] - a.set_z(r0[2]+dx) - pz2 = calc.get_potential(atoms)[a.index] - a.set_z(r0[2]) - - Efd[a.index, 0] = -(px2-px1)/(2*dx) - Efd[a.index, 1] = -(py2-py1)/(2*dx) - Efd[a.index, 2] = -(pz2-pz1)/(2*dx) - - dE = Efd-E0 - - return ( Efd, E0, np.max(np.abs(dE)) ) - - -def check_virial(atoms, de=1e-6): - """ - Compute virial and compare to virial computed numerically from a - finite differences approach. - """ - - s0 = atoms.get_stress().copy() - V0 = atoms.get_volume() - sfd = np.zeros([ 3, 3 ]) - c0 = atoms.get_cell().copy() - - un = np.zeros([3,3]) - un[0,0] = 1.0 - un[1,1] = 1.0 - un[2,2] = 1.0 - - - for i in range(3): - for j in range(3): - c = c0.copy() - eps = un.copy() - - eps[i, j] = un[i, j]-de - c = np.dot(c0, eps) - atoms.set_cell(c, scale_atoms=True) - e1 = atoms.get_potential_energy() - - eps[i, j] = un[i, j]+de - c = np.dot(c0, eps) - atoms.set_cell(c, scale_atoms=True) - e2 = atoms.get_potential_energy() - - sfd[i, j] = (e2-e1)/(2*de) - - sfd = np.array( [ sfd[0,0], sfd[1,1], sfd[2,2], (sfd[1,2]+sfd[2,1])/2, (sfd[0,2]+sfd[2,0])/2, (sfd[0,1]+sfd[1,0])/2 ] )/V0 - - return ( sfd, s0, np.max(np.abs(sfd-s0)) ) - diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/grids.py b/build/lib.macosx-10.7-x86_64-2.7/box/grids.py deleted file mode 100644 index 26445bb..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/grids.py +++ /dev/null @@ -1,187 +0,0 @@ -import ase -import numpy as np -from box import mix -from box.interpolation import TrilinearInterpolation -from ase.io.cube import read_cube_data -vec=np.array - -class GridData: - def __init__(self, atoms, data): - """ - - Paramaters: - =========== - atoms: ase Atoms instance - data: grid data (in the cell of atoms, 3-dimensional array) or - cube file containing the data - """ - if type(data)==type(''): - self.data, aux=read_cube_data(data) - else: - self.data=data - self.atoms=atoms - self.cell = atoms.get_cell() - assert not self.cell[2, :2].any() and not self.cell[:2, 2].any() - self.ldos = None - self.heights = None - self.axes=vec([self.cell[i,i] for i in range(3)]) - self.dg=None - self.ng=self.data.shape - self.grids=[np.linspace(0,self.axes[i],self.ng[i]) for i in range(3)] - self.ztol=0.001 - self.dataip=TrilinearInterpolation(self.data,grids=self.grids) - - def __call__(self,r): - """ - Return the value of the data at r - """ - return self.dataip(vec([r[0],r[1],r[2]])) - - def get_grids(self): - """ Return the grids points in x-,y-, and z-directions. """ - from copy import copy - return copy(self.grids) - - - def get_data(self): - """ Return the data as 3-dimensional array. """ - return self.data - - - def get_z_averaged_data(self, z): - """ Get averaged data for given z.""" - sum=0 - for x in self.grids[0]: - for y in self.grids[1]: - sum+=self.dataip(vec([x,y,z])) - c=sum/(self.ng[0]*self.ng[1]) - return c - - - def get_max_over_xy(self, z): - """ Get maximum data value in the xy-plane at height z.""" - mx=0. - for x in self.grids[0]: - for y in self.grids[1]: - mx=max(mx,self.dataip(vec([x,y,z]))) - return mx - - - def scan(self,threshold,bottom=0.0): - """ - Scan the data height profile in constant contour mode with given threshold. - - Construct the profile into the same existing x-y grid. - """ - heights=np.empty((self.ng[0],self.ng[1])) - nz=len(self.grids[2]) - for i,x in enumerate(self.grids[0]): - for j,y in enumerate(self.grids[1]): - # approach from top... - for k in range(nz-1,-1,-1): - if k==0: - heights[i,j]=bottom #no crossing of threshold - else: - if self.data[i,j,k]<=threshold<=self.data[i,j,k-1]: - heights[i,j]=self.find_height(threshold,x,y,self.grids[2][k-1],self.grids[2][k]) - break - self.heights=heights - return heights - - - def find_height(self,threshold,x,y,zmin,zmax): - """ - Let us approach from zmax towards zmin. Return z where the threshold value - for LDOS is obtained. Search is done recursively. Return NaN - if threshold not found. - """ - zmid=0.5*(zmax+zmin) - if zmax-zmin=threshold: - return self.find_height(threshold,x,y,zmid,zmax) - else: - return self.find_height(threshold,x,y,zmin,zmid) - - - def linescan(self, start, end, threshold, points=200, bottom=0.0): - """ Make data linescan between start and end points. - - Note: only x- and y-coordinates of the start and end points matter. - - Parameters: - ----------- - start: position array - end: position array - threshold: constant-data contour line threshold - points: linear interpolation in output using this many points. - """ - r1=vec(start) - r2=vec(end) - L=np.linalg.linalg.norm(r2-r1) - nz=len(self.grids[2]) - l=[] - h=[] - for i,r in enumerate([r1+i/(points-1.0)*(r2-r1) for i in range(points)]): - l.append(1.0*i*L/(points-1.0)) - dataz=[ self.dataip(vec([r[0],r[1],self.grids[2][k]])) for k in range(self.ng[2]) ] - for k in range(nz-1,-1,-1): - if k==0: - h.append(bottom) #no crossing of threshold; use 'bottom' value - else: - if dataz[k]<=threshold<=dataz[k-1]: - h.append( self.find_height(threshold,r[0],r[1],self.grids[2][k-1],self.grids[2][k]) ) - break - return l,h - - def broadened_linescan(self, start, end, width, threshold, points=100, nwidth=10, bottom=0.0, getlines=False): - """ Make data linescan between start and end points with effective 'width' for data scanner. - - Not: only x- and y-coordinates of the start and end points matter. - Line scan between start and end, but with such a way that you perform - 'nwidth' parallel line scans from width/2 distance from both sides of the original line. - The result with given distance from the start is the maximum over all parallel values. - - Parameters: - ----------- - start: position array - end: position array - width: width (in Angstrom) for data scanning - threshold: constant-data contour line threshold - nwidth: how many parallel line scans are performed - points: linear interpolation in output using this many points. - getlines: if True, return ase.Atoms object where atoms are 'X's with - starting and end-points of the line scans - - Return: distance array and heights on that distance array - (if getlines, return also the ase.Atoms object) - """ - start, end = vec(start), vec(end) - n=np.cross( end-start,vec([0,0,1]) ) - n/=np.linalg.norm(n) - start0, end0 = start - (width/2)*n, end - (width/2)*n - atoms=ase.Atoms() - - # perform nwidth parallel scans - hlist=[] - for shift in np.linspace(0,width,nwidth): - l,h = self.linescan(start0+shift*n, end0+shift*n, threshold, points=points, bottom=bottom) - atoms.append( ase.Atom('X',start0+shift*n) ) - atoms.append( ase.Atom('X',end0+shift*n) ) - hlist.append(h) - hlist=np.array(hlist) - - # take maxima from these scans - h=[] - for i in range(len(l)): - h.append( max(hlist[:,i]) ) - if getlines: - return l,h,atoms - else: - return l,h - - - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/interpolation.py b/build/lib.macosx-10.7-x86_64-2.7/box/interpolation.py deleted file mode 100644 index 6c029e7..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/interpolation.py +++ /dev/null @@ -1,905 +0,0 @@ -import numpy as np -from box import mix -from scipy.linalg import norm -from scipy.optimize import fminbound -from scipy.optimize import brentq -from scipy.interpolate import splprep -from scipy.interpolate import splrep -from scipy.interpolate import splev -from scipy.interpolate import splint -try: - import pylab as pl -except: - pass -vec=np.array -linspace=np.linspace - -class MultipleSplineFunction: - """ Class for interpolating many functions at the same time on the same grid. - - cubic natural spline. - """ - def __init__(self,x): - """ Setup x-grid. - - parameters: - ----------- - x: the *linear* x-grid - """ - self.x=x - self.a=x[0] - self.b=x[-1] - self.n=len(x) - self.xmin, self.xmax=x[0], x[-1] - self.h=x[1]-x[0] - self.labels=[] - self.indices=[] - self.y=[] - self.initialized=False - self.m=0 - - def add_function(self,y,label='',index=0): - """ Add function on the same x-grid. - - label: characterizes the function and - index: some additional number to characterize function (used for speed-up) - """ - assert not self.initialized - self.y.append(y) - self.labels.append(label) - self.indices.append(index) - self.m+=1 - - - def get_number_of_functions(self): - return self.m - - - def get_labels(self): - return self.labels - - - def get_indices(self): - return self.indices - - - def _initialize(self): - """ Calculate second derivatives for all the functions. """ - assert not self.initialized - self.initialized=True - - self.d2=[] - n=self.n - for i in range(self.m): - u=np.zeros_like(self.x) - d2=np.zeros_like(self.x) - y=self.y[i] - x=self.x - qn = 0.0 - un = 0.0 - - if len(x) != len(y): - raise RuntimeError('x- and y-tables need to have identical ' - 'numbers of entries. Here x: %i, y: %i.' % \ - ( len(x), len(y) )) - - # Solve the second derivatives - for i in range(1,n-1): - sig = (x[i]-x[i-1])/(x[i+1]-x[i-1]) - p = sig*d2[i-1]+2 - d2[i]= (sig-1)/p - u[i] = ( 6*((y[i+1]-y[i])/(x[i+1]-x[i])-(y[i]-y[i-1])/(x[i]-x[i-1]))/(x[i+1]-x[i-1])-sig*u[i-1] )/p - - d2[n-1]=(un-qn*u[n-2])/(qn*d2[n-2]+1) - for i in range(n-1)[::-1]: - d2[i]=d2[i]*d2[i+1]+u[i] - self.d2.append(d2) - self.d2=np.array(self.d2) - self.y=np.array(self.y) - - - def get_range(self): - return self.x[0],self.x[-1] - - -# def _find_bin_fast(self,x): -# """ For given x, return i such that x_i<=x1: -# k=(hi+lo)/2 -# if x=self.x[-1]: - # if der==None: - # return np.zeros((self.m,)),np.zeros((self.m)) - # else: - # return np.zeros((self.m,)) - - hi = np.searchsorted(self.x, x) - lo = hi-1 - #assert xlo<=x<=xhi - - # If x > cutoff, descrease hi. In this case hi == lo and all - # returned values will be zero. - if isinstance(x, np.ndarray): - hi = np.where(hi == len(self.x), hi-1, hi) - else: - if hi == len(self.x): - hi -= 1 - - xlo, xhi = self.x[lo], self.x[hi] - - h=self.h - a, b=(xhi-x)/h, (x-xlo)/h - ylo, yhi=self.y[:,lo], self.y[:,hi] - dlo, dhi=self.d2[:,lo], self.d2[:,hi] - - y=a*ylo + b*yhi + ((a**3-a)*dlo+(b**3-b)*dhi)*(h**2)/6 - dy=(yhi-ylo)/h - (3*a**2-1)/6*h*dlo + (3*b**2-1)/6*h*dhi - - if der==None: - return y,dy - elif der==0: - return y - elif der==1: - return dy - elif der==2: - return a*self.d2[:,lo] + b*self.d2[:,hi] - - -class FastSplineFunction: - def __init__(self,x,y,grid,**kwargs): - """ Initialize second derivatives. - - Parameters: - ----------- - x: x-grid - y: y-values on given x-grid - grid: type of grid - 'linear': x[i]=xmin + i/(N-1)*(xmax-xmin) (i~(N-1)*(x-xmin)/(xmax-xmin)) - 'power': x[i]=xmin + (i/(N-1))**p*(xmax-xmin) - **kwargs: parameters for grid (can vary) (xmin,xmax,p,...) - (N comes from length of x) - """ - - - self.x=x - self.y=y - self.a=x[0] - self.b=x[-1] - d2=np.zeros_like(y) - u=np.zeros_like(y) - n=len(x) - qn = 0.0 - un = 0.0 - - # Solve the second derivatives - for i in range(1,n-1): - sig = (x[i]-x[i-1])/(x[i+1]-x[i-1]) - p = sig*d2[i-1]+2 - d2[i]= (sig-1)/p - u[i] = ( 6*((y[i+1]-y[i])/(x[i+1]-x[i])-(y[i]-y[i-1])/(x[i]-x[i-1]))/(x[i+1]-x[i-1])-sig*u[i-1] )/p - - d2[n-1]=(un-qn*u[n-2])/(qn*d2[n-2]+1) - for i in range(n-1)[::-1]: - d2[i]=d2[i]*d2[i+1]+u[i] - self.n=n - self.d2=d2 - self.grid=grid - self.xmin, self.xmax=x[0], x[-1] - if grid=='linear': - #self.xmin,self.xmax=kwargs['xmin'],kwargs['xmax'] - self.find_lower_index=self.find_lower_index_linear - if grid=='power': - self.p=kwargs['p'] - self.find_lower_index=self.find_lower_index_power - - def get_range(self): - return self.x[0],self.x[-1] - - def find_lower_index_linear(self,x): - """ For given x, return i such that x_i<=x=self.x[-1]: - return 0.0 - - lo=self.find_lower_index(x) - hi=lo+1 - - h=self.x[hi]-self.x[lo] - assert self.x[lo]<=x self.x[-1], - np.zeros(len(x)), - splev(x, self.tck, der=der) - ) - ) - else: - if x < self.x[0] or x > self.x[-1]: - return 0.0 - else: - return splev(x, self.tck, der=der) - - def get_name(self): - """ Return the name of the function. """ - return self.name - - def get_range(self): - return (self.x[0],self.x[-1]) - - def limits(self): - return self.get_range() - - def solve(self,y,a=None,b=None): - """ Solve x for f(x)=y, where x in [a,b]. """ - if a==None: a=self.x[0] - if b==None: b=self.x[-1] - assert a points r given exactly) - u = node points (for internal u-parameter) - force = force field at the nodes of r (forces evaluated at each M point) - - Usage: - fr=VectorSplineFunction(r) (now r=fr(t) with t [0,1]) - tan=fr.normalized_tangent(0.2) - ... - - - The trajectory is parametrized with variable 't' ([0,1]) where - t=l/L (L is the total length of the trajectory and l length so far). - Internally for technical reasons the path is internally parametrized - by 'u' ([0,1]), where the path is taken to be _linear_ between - the points. Thus, for k=1, u is equal to t. - - r=r(t) and r=r(u); r(t=0)=r(u=0) and r(t=1)=r(u=1) - The length along the path l(u) and l(t). t has the property - dl(t)/dr=L/1=L = constant (l(t=0)=0 and l(t=1)=L). - - dl dl(t) dt dt l'(u) - -- = -----*--=L*-- --> dt=-----du --> t(u)=l(u)/L (with correct bound.cond.) - du dt du du L - - /b /b - l(a,b)= | ds = | |dr(u)/du|du (for a,b=u) - /u=a /u=a - - /b /b - l(a,b)= | ds = | |dr(u)/du*du/dt|dt (for a,b=t) - /t=a /t=a - - where |...| is the Eucledian norm. - - - Energy slope E'(t)=F(t)*r'(t) - - """ - self.k=k - self.s=s - self.r=r.copy() - self.u=u - self.N=len(r[0,:]) - self.M=len(r[:,0]) - self.M2=self.M*10 #finer grid (used for plotting etc) - self.M3=self.M*50 #finest grid (used in integration etc) - self.w=[1]*self.M - self.w[0]=1E6 - self.w[-1]=1E6 - - if self.s==None: - self.s=self.M-np.sqrt(2.0*self.M) - if self.u!=None: - self.u=u.copy() - - self.tck,self.u=splprep(self.r.transpose(),u=self.u,k=self.k,s=self.s,w=self.w) - - u,l=self.line_integral(a=0,b=1,parameter='u',full_out=True) - self.length=l[-1] - t=l/self.length - self.u_of_t=SplineFunction(t,u,k=3,s=0) - self.t_of_u=SplineFunction(u,t,k=3,s=0) - self.t=[self.t_of_u(u) for u in self.u] - - if self.k!=1: - self.linear=VectorSplineFunction(self.r,k=1,s=0,u=self.u) - if force!=None: - self.force=VectorSplineFunction(r=force,k=self.k,s=self.s,u=self.u) - - - def get_length(self): - return self.length - - - - - def plot(self,out='screen'): - selected=range(self.N) #from maximum deviation? - n=len(selected) - ny=n+2 - nx=1 - - rhomo=self.homogenize() - thomo=grid(self.M) - tsmooth=grid(self.M2) - rsmooth=vec([self(t=t) for t in tsmooth]) - - - fig=1 - if self.N==2: - pl.figure(fig) - pl.scatter(self.r[:,0],self.r[:,1],color='r',label='trajectory') - pl.scatter(rhomo[:,0],rhomo[:,1],s=[50]*self.M,color='y') - pl.plot(rsmooth[:,0],rsmooth[:,1]) - fig+=1 - - # plot u(t) - pl.figure(fig) - pl.subplot(ny,nx,1) - usmooth=[self.u_of_t(x) for x in tsmooth] - pl.plot(tsmooth,usmooth) - pl.plot(tsmooth,tsmooth) - pl.title('u(t)') - pl.axis(xmin=0,xmax=1.0,ymin=0,ymax=1) - - pl.subplot(ny,nx,2) - pl.plot(tsmooth,self.curvature(t=tsmooth),label='curvature') - - sub=3 - for i in selected: - pl.subplot(ny,nx,sub) - pl.plot(tsmooth,rsmooth[:,i]) - pl.scatter(thomo,rhomo[:,i],s=[100]*self.M,label='homog',color='y',marker='d') - pl.scatter( self.t,self.r[:,i],color='r',label='%i' %i) - pl.axis(xmin=0,xmax=1.0) - sub+=1 - #p.legend() - - if out=='screen': - pl.show() - else: - pl.savefig(out) - pl.close() - - - - def __call__(self,t=None,u=None,der=0): - """ - Return the interpolated r(t) or r(u). If you evaluate t-derivatives - then chain rule is used: dr(t)/dt=dr(u)/du*(du/dt). This because - spline routine is always called using internal u-parameter. Take special - care to return initial or end-points if parameter==0 or 1. - """ - assert t!=None and u==None or t==None and u!=None - if t!=None: - u=self.u_of_t(t) - elif u!=None: - pass - - if der==1 and t!=None: - return vec( splev(u,self.tck,der=1) )*self.u_of_t(t,der=1) - elif der==2 and t!=None: - return vec(splev(u,self.tck,der=2))*self.u_of_t(t,der=1)**2 + \ - vec(splev(u,self.tck,der=1))*self.u_of_t(t,der=2) - else: - if abs(u)<1E-4 and der==0: - return self.r[0,:] - elif abs(u-1)<1E-4 and der==0: - return self.r[-1,:] - else: - return vec(splev(u,self.tck,der=der)) - - - def line_integral(self,a=None,b=None,parameter=None,full_out=False): - """ - Return line integral in N-dimensional space along splined function. - Paramater is 'u' or 't' [a,b]. If b2 # at least cubic required - if type(t)==type(1.0) or type(t)==type(1): - return norm(self(t=t,der=2)) - else: - return [norm(self(t=tx,der=2)) for tx in t] - - -class BilinearInterpolation: - """ - Perform bilinear interpolation for 2D (xy)-data - - For bilinear interpolation, see e.g. Wikipedia. - """ - def __init__(self,a,xgrid=None,ygrid=None): - self.a=a - self.nx=a.shape[0] - self.ny=a.shape[1] - self.xgrid=xgrid - self.ygrid=ygrid - if self.xgrid==None: - self.xgrid=np.arange(self.nx) - if self.ygrid==None: - self.ygrid=np.arange(self.ny) - self.dx=self.xgrid[1]-self.xgrid[0] - self.dy=self.ygrid[1]-self.ygrid[0] - - def __call__(self,x,y): - """ Return the interpolated value at x,y. """ - assert self.xgrid[0]<=x<=self.xgrid[-1] - assert self.ygrid[0]<=y<=self.ygrid[-1] - - i,j=(np.floor(x/self.dx),np.floor(y/self.dx)) - i,j=(min(i,self.nx-2),min(j,self.ny-2)) - dx,dy=((x%self.dx)/self.dx,(y%self.dy)/self.dy) - raise NotImplementedError('Check that dx=0...1 and not something else.') - - a=self.a - return a[i,j] *(1-dx)*(1-dy)+a[i+1,j]*dx*(1-dy)+\ - a[i,j+1]*(1-dx)*dy +a[i+1,j+1]*dx*dy - - def plot(self,nx=100,ny=100,out='screen'): - """ Make 2D contour-color plot of the data. """ - b=np.empty((nx,ny)) - X=np.linspace(self.xgrid[0],self.xgrid[1],nx) - Y=np.linspace(self.ygrid[0],self.ygrid[1],ny) - for i,x in enumerate(X): - for j,y in enumerate(Y): - b[i,j]=self(x,y) - pl.contourf(b,100) - pl.hot() - pl.colorbar() - if out=='screen': - pl.show() - else: - pl.savefig('linter.png') - -class TrilinearInterpolation: - """ - Perform trilinear interpolation for 3D (xyz)-data - - For trilinear interpolation, see e.g. Wikipedia. - """ - def __init__(self,a,grids=None): - self.a=a - self.n=a.shape - self.grids=grids - if self.grids==None: - self.grids=vec([np.arange(self.n[i]) for i in range(3)])*1.0 - self.dg=vec([self.grids[i][1]-self.grids[i][0] for i in range(3)])*1.0 - - def __call__(self,r): - """ Return the interpolated value at r. """ - for i in range(3): - assert self.grids[i][0]<=r[i]<=self.grids[i][-1] - - ind0=np.floor((r/self.dg)) - dx0,dy0,dz0=[self.grids[i][1]-self.grids[i][0] for i in range(3)] - # i,j,k grid point can never be a point at 'larger' side - i,j,k=[int(min(ind0[i],self.n[i]-2)) for i in range(3)] - dx,dy,dz=[r[p]-self.grids[p][ind] for p,ind in zip(range(3),(i,j,k))] - dx,dy,dz=(dx/dx0, dy/dy0, dz/dz0) - - a=self.a - i1=a[i,j,k] *(1-dz)+a[i,j,k+1]*dz - i2=a[i,j+1,k] *(1-dz)+a[i,j+1,k+1]*dz - j1=a[i+1,j,k] *(1-dz)+a[i+1,j,k+1]*dz - j2=a[i+1,j+1,k]*(1-dz)+a[i+1,j+1,k+1]*dz - w1=i1*(1-dy)+i2*dy - w2=j1*(1-dy)+j2*dy - return w1*(1-dx)+w2*dx - - - def write_vtk(self,name='trilinear',gpts=None): - """ - Write data into vtk file with given number of grid points. - - Parameters: - gpts - number of grid points to all directions. Default - is the number of DFT grid points. - """ - if gpts==None: - gpts=self.n - R=[np.linspace(0,self.grids[i][-1],gpts[i]) for i in range(3)] - nx,ny,nz=(gpts[0],gpts[1],gpts[2]) - - - of=open('%s.vtk' %name,'w') - print>>of,"# vtk DataFile Version 2.0" - print>>of,"Trilinear interpolation" - print>>of,"ASCII" - print>>of,"DATASET RECTILINEAR_GRID" - print>>of,"DIMENSIONS %i %i %i" %(nx,ny,nz) - print>>of,"X_COORDINATES %i double" %nx - print>>of,mix.a2s(R[0]) - print>>of,"Y_COORDINATES %i double" %ny - print>>of,mix.a2s(R[1]) - print>>of,"Z_COORDINATES %i double" %nz - print>>of,mix.a2s(R[2]) - print>>of,"POINT_DATA %i" %(nx*ny*nz) - print>>of,"SCALARS data double" - print>>of,"LOOKUP_TABLE default" - - for k in range(nz): - for j in range(ny): - for i in range(nx): - r=vec([R[0][i],R[1][j],R[2][k]]) - print>>of, self(r) - of.close() - - -def interpolate_path(points, N): - """ - Make a path between defined points 3D-points. Returns - - the interpolated path, which contains the original points - - distance of each point along the path starting from the first point - - the distances of the original points on the path (for naming purposes) - - Parameters: - points - the points that the path connects. - N - The preferred number of points on the path (the number may be slightly larger than given number) - """ - points = np.array(points) - path = [] - path.append(points[0]) # start from the first point - lengths = [norm(kf-ki) for kf, ki in zip(points[1:], points[:-1])] # lengths of the subpaths - label_points = np.zeros(len(points)) # the distances where the fixed points are on the path - for i in range(1, len(label_points)): - label_points[i] = np.sum(lengths[:i]) - dk = np.sum(lengths)/(N-1.0) # maximum distance between points - N_i = [] # the number of points on each subpath - for i in range(len(lengths)): - n_i = round(lengths[i] / dk) + 1 - if n_i*dk < lengths[i]: - n_i += 1 - N_i.append(n_i) - for i in range(len(points)-1): - A = points[i] - B = points[i+1] - X = np.linspace(A[0], B[0], N_i[i]) - Y = np.linspace(A[1], B[1], N_i[i]) - Z = np.linspace(A[2], B[2], N_i[i]) - for x,y,z in zip(X[1:], Y[1:], Z[1:]): - path.append((x,y,z)) - distances = np.zeros(len(path)) - for i in range(len(path[1:])): - distances[i+1] = distances[i] + norm(np.array(path[i+1])-np.array(path[i])) - return np.array(path), distances, label_points - - -if __name__=='__main__': - #sp=SplineFunction([0,1,2,3],[0,1,2,10]) - #print sp.solve(4.56) - #sp.plot() - #assert False - if False: - r=vec([vec([1,0]),vec([0.5,1.0]),vec([0,2]),vec([0,2.1]),vec([0.2,2.2]),vec([0.2,2.3]),vec([0.21,2.2]),vec([0.2,2.3]),vec([-0.3,2.5])]) - #r=vec([[0,0],[1,1],[2,10],[3,8]]) - f=VectorSplineFunction(r,k=3,s=0) - #for t in np.linspace(0,1,10): - #print t,f(t,der=0) #,f(t,der=1),f(t,der=-1) - #print t, f.line_integral(b=t) #,np.sqrt(5.0) - f.max_deviation_from_linear() - f.plot() - #print 'length',f.get_length() - - if False: - a=vec([[10,1],[2,5]]) - inte=BilinearInterpolation(a) - inte.plot() - - a=np.empty((2,2,2)) - a[0,0,0]=0.1 - a[0,0,1]=1 - a[0,1,0]=2 - a[0,1,1]=3 - a[1,0,0]=4 - a[1,0,1]=4 - a[1,1,0]=3 - a[1,1,1]=4 - inte=TrilinearInterpolation(a) - print inte(vec([0.999,0.999,0.999])) - print inte(vec([1.0,1.0,1.0])) - inte.write_vtk(gpts=[20,20,20]) diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/md.py b/build/lib.macosx-10.7-x86_64-2.7/box/md.py deleted file mode 100644 index 6b1f8d0..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/md.py +++ /dev/null @@ -1,374 +0,0 @@ -import ase -import numpy as np -from box import mix -from box.data import data -from ase.md import VelocityVerlet -from ase.io import PickleTrajectory -from ase.units import fs, Hartree - - -class NullCalculator: - def __init__(self): - pass - - def calculation_required(self,atoms,quantities): - return False - - def get_forces(self,atoms): - return np.zeros_like(atoms.get_positions()) - - def get_stress(self,atoms): - return None - - def get_potential_energy(self,atoms=None): - return 0.0 - - - -class TrajectoryRecording: - def __init__(self,atoms,verbose=False): - self.atoms=atoms - self.properties={'epot':self.atoms.get_potential_energy,\ - 'etot':self.atoms.get_total_energy } - self.data={} - for key in self.properties: - self.data[key]=[] - self.i=0 - self.verbose=verbose - - def __call__(self): - for key in self.properties: - self.data[key].append( self.properties[key]() ) - self.i+=1 - if self.verbose: - print 'record',self.i,self.data['epot'][-1] - - def get(self,key): - return self.data[key] - - def plot_energies(self): - pl.plot( self.get('epot'),label='potential') - pl.plot( self.get('etot'),label='total') - pl.show() - pl.close() - - -def dimer_curve(atoms,r1=None,r2=None,N=100): - """ Calculate dimer curve """ - rc=[] - for s in atoms.get_chemical_symbols(): - rc.append(data[s]['R_cov']) - if r1==None: - r1=(rc[0]+rc[1])*0.5 - if r2==None: - r2=(rc[0]+rc[1])*2.5 - e=[] - rl=np.linspace(r1,r2,N) - for r in rl: - atoms.set_positions([(0,0,0),(r,0,0)]) - e.append( atoms.get_potential_energy() ) - return rl,np.array(e) - - - -def canonical(atoms,dt=1.0,steps=1000,output=10,name=None,verbose=False): - """ Perform little canonical simulation. - - parameters: - ----------- - atoms: atoms with calculator attached - dt: time step in fs - steps: how many md steps - output: output frequency - name: TrajectoryRecording name - verbose: increase verbosity - """ - if name==None: - try: - name=atoms.get_chemical_formula(mode="hill") - except: - name='microcanonical' - name+='.trj' - traj=PickleTrajectory(name,'w',atoms) - rec=TrajectoryRecording(atoms,verbose) - md=VelocityVerlet(atoms,dt*fs) - md.attach(rec,interval=output) - md.attach(traj.write,interval=output) - md.run(steps) - return rec - - -def microcanonical(atoms,dt=1.0,steps=100,output=1,name=None,verbose=False): - """ Perform little microcanonical simulation. - - parameters: - ----------- - atoms: - dt: time step in fs - steps: how many md steps - output: output frequency - name: TrajectoryRecording name - verbose: increase verbosity - - Return TrajectoryRecording object for further analysis. - """ - if name==None: - try: - name=atoms.get_chemical_formula(mode="hill") - except: - name='microcanonical' - name+='.trj' - traj=PickleTrajectory(name,'w',atoms) - rec=TrajectoryRecording(atoms,verbose) - md=VelocityVerlet(atoms,dt*fs) - md.attach(rec,interval=output) - md.attach(traj.write,interval=output) - md.run(steps) - return rec - - -def check_energy_conservation(atoms,dt=1.0*fs,steps=200,tol=0.01,plot=False): - """ - For given initial atoms, check the energy conservation with NVE simulation. - - @param atoms: ase atoms instance - @param dt: time step - @param steps: number of time steps used in the check - @param plot: use maplotlib to plot the etot,epot -graph - - Energy is conserved if fluctuation of total energy is tolerance times - the fluctuation of potential energy. - """ - dyn = VelocityVerlet(atoms,dt=dt) - epot = [] - ekin = [] - for i in range(steps): - dyn.run(1) - epot.append( atoms.get_potential_energy() ) - ekin.append( atoms.get_kinetic_energy() ) - epot = np.array(epot) - ekin = np.array(ekin) - etot = epot + ekin - depot = np.sqrt( np.var(epot) ) - detot = np.sqrt( np.var(etot) ) - if plot: - import pylab as pl - pl.plot(epot,label='epot') - pl.plot(etot,label='etot') - pl.legend() - pl.xlabel('time step') - pl.ylabel('energy (eV)') - pl.show() - if detot < tol*depot: - return True - else: - return False - - -def energy_conservation(atoms,dt=1.0,steps=100,name=None,verbose=False): - """ Make microcanonical simulation, check energy conservation. - - parameters: - ----------- - atoms: atoms object with calculator attached (and initial geometry) - dt: time step to perform md (fs) - steps: how many md steps are taken - name: name for the TrajectoryRecording object - verbose: increase verbosity - - Return TrajectoryRecording instance and deviations in etot and epot. - """ - rec=microcanonical(atoms,dt,steps=steps,output=1,name=name,verbose=verbose) - etot, epot=rec.get('etot'), rec.get('epot') - de=np.sqrt( np.var(etot) ) - du=np.sqrt( np.var(epot) ) - return rec, de, du - - -def energy_conservation_plot(atoms,dts,total_time=100): - """ Make set of NVE simulations with different time steps and plot errors. - - parameters: - ----------- - atoms: atoms object with calculator attached (and initial geometry) - perform all simulations from same initial point - dts: list of time steps to try (fs) - total_time: total simulation time (in fs) for all simulations - (smaller time stepping makes more calculations) - """ - import pylab as pl - R0=atoms.get_positions() - dE=[] - dU=[] - for dt in dts: - steps=int(total_time/dt) - print 'time step %.2f fs, steps %i' %(dt,steps) - atoms.set_positions(R0) - rec, de, du=energy_conservation(atoms,dt,steps=steps) - dE.append(de) - dU.append(du) - atoms.set_positions(R0) - frac=np.array(dE)/np.array(dU) - rec.plot_energies() - - pl.plot(dts,frac*100) - pl.title('Total energy deviation/potential energy deviation') - pl.xlabel('time step (fs)') - pl.ylabel('dev(e)/dev(u) (%)') - pl.plot() - pl.show() - - -class TrajectoryWriter: - """ - Trajectory writer for transition paths. - Write each path into its own file. - """ - def __init__(self,images,name=None): - """ images is the list of Atoms objects; you can supply also the name. """ - - if name==None: - self.name='path' - else: - self.name=name - self.images=images - self.i=0 - - def __call__(self): - """ Writes trajectory file for current atoms list. """ - from ase import PickleTrajectory - traj = PickleTrajectory('%s_it%i.trj' %(self.name,self.i), 'w') - for image in self.images: - traj.write(image) - self.i+=1 - - -def quench(atoms,name=None,fmax=0.05,method='QN'): - """ Quench given Atoms object with given attached calculator. """ - if name==None: - try: - name=atoms.get_chemical_formula(mode="hill") - except: - raise ValueError('name not specified') - traj=ase.PickleTrajectory(name+'_quenching.trj','w',atoms) - - if method=='QN': - qn=ase.QuasiNewton(atoms) - elif method=='FIRE': - qn=ase.FIRE(atoms) - qn.attach(traj.write) - qn.run(fmax=fmax) - e=atoms.get_potential_energy() - ase.write(name+'_quenched.xyz',atoms) - return e - - -def transition_barrier(calc,quench,guess,cell=None,pbc=None,constraints=None,\ - M=None,name=None,fmax=0.05,steps=1000000): - import ase - method=ase.NEB - - if type(guess)!=type([]) and type(guess)!=type(''): - # all Atoms properties should be set for Atoms-type guess - images=guess - path=method(images) - else: - if type(guess)==type(''): - assert guess.split('.')[-1]=='trj' and M==None - # for some reason copying has to be done... - images=[] - for image in ase.PickleTrajectory(guess): - images.append(image.copy()) - path=method(images) - else: - assert type(guess)==type([]) and M!=None - images=[] - first=ase.read(guess[0]) - images.append(first) - for i in range(M-2): - images.append(first.copy()) - last=ase.read(guess[1]) - images.append(last) - path=method(images) - path.interpolate() - - # now coordinates are set; set other properties - assert cell!=None and pbc!=None - for image in images: - image.set_pbc(pbc) - image.set_cell(cell,fix=True) - if constraints!=None: - image.set_constraint(constraints) - - # attach calculators - if type(calc)==type([]): - for image,clc in zip(images,calc): - image.set_calculator(clc) - else: - for image in images: - image.set_calculator(calc.copy()) - - for image in images: - image.center() - - if quench: - e1=quench_atoms(images[0],'initial') - print 'First image quenched. Energy=',e1 - eM=quench_atoms(images[-1],'final') - print 'Last image quenched. Energy=',eM - - # solve the transition path - writer=TrajectoryWriter(images) - minimizer=ase.QuasiNewton(path) - minimizer.attach(writer) - minimizer.run(fmax=fmax,steps=steps) - - # output of the final path - traj = ase.PickleTrajectory('%s_converged.trj' %name, 'w') - path.write(traj) - return images - -def merge_atoms(atoms1,atoms2,box_from=None,R=0.3): - """ - Merge two sets of atoms without atom duplication. - (atoms1 and atoms2 may share same atoms within radius R) - """ - from box import Atoms - - atoms=atoms1.copy() - print type(atoms) - - # set box from the first atoms or box_from - if box_from!=None: - bx=box_from - else: - bx=atoms1 - atoms.set_cell(bx.get_cell(),fix=True) - atoms.set_pbc(bx.get_pbc()) - - # add atoms from atoms2 if not close - for a2,r2 in zip(atoms2,atoms2.get_positions()): - close=False - for r1 in atoms1.get_positions(): - if atoms.distance(r1,r2)1: - A=np.zeros((M,M)) - b=np.zeros((M,)) - # prepare for solving solve A*z=b (eq.(4.3) in Eyert) - for i in range(M): - b[i]=np.dot(self.F[0,:]-self.F[i+1,:],self.F[0,:]) - for j in range(M): - A[i,j]=np.dot(self.F[0,:]-self.F[i+1,:],self.F[0,:]-self.F[j+1,:]) - try: - # c is the optimum linear combination - c=solve(A,b) - simple=False - except: - # if A singular, use simple mixing - simple=True - - if simple: - xb=(1-self.beta)*xi+self.beta*yi - else: - # xb is the best (calculated) estimate; go that direction - xb=xi.copy() - Fb=self.F[0,:].copy() - for j in range(M): - xb+=c[j]*(self.x[j+1,:]-xi) - Fb+=c[j]*(self.F[j+1,:]-self.F[0,:]) - xb=xb+self.beta*Fb - - - # The input must not change more than chop for all - maxdev=max(abs(xb-xi)) - if self.chop!=None and maxdev>self.chop: - xb = xi + self.chop/maxdev*(xb-xi) - - # shift history - self.F[1:self.memory+1,:] = self.F[0:self.memory,:] - self.x[1:self.memory+1,:] = self.x[0:self.memory,:] - - fmax=abs(self.F[0,:]).max() - self.fmax.append(fmax) - if fmax>out, 'Anderson mixer out of iterations!' - print>>out, 'History of maximum residuals:' - for it,fmax in enumerate(self.fmax): - print>>out, it,fmax - - print>>out, "Recent history: (number=i'th last iteration)" - for i in range(1,self.memory+1): - print>>out, i-1, self.x[i,:5] - -if __name__=='__main__': - def testf(x): - return -np.array([3.0,2.0,1.5,1.0,0.5])*x-0.01*x**3 - - mix=AndersonMixer(0.2,3,1E-40) - xi=np.array([1.,1.,1.,1.,1.]) - for i in range(50): - out=testf(xi) - #print xi,out - done,xi=mix(xi,out) - mix.echo() - - if done: - break diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/mix.py b/build/lib.macosx-10.7-x86_64-2.7/box/mix.py deleted file mode 100644 index 7708f32..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/mix.py +++ /dev/null @@ -1,1050 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2008 NSC Jyvaskyla -# Please see the accompanying LICENSE file for further information. -''' - A module containing miscellaneous utility functions. - - Author: P. Koskinen 11.9 2006- - - -''' -import numpy as np -import time -from math import atan,cos,sin -from numpy import sqrt,pi,exp -import warnings - -def even_cpu_load(N,ncpu,power=3,indices=False): - """ - For a given list of system sizes N, divide load evenly to cpus. - - This is for dummy (ideal) parallellization. - - parameters: - =========== - N: list of system sizes, e.g. [5,6,7] - ncpu: number of cpus - power: scaling with system size. For systems with N=[5,6,7] - the scaling goes as 5**power etc. - indices:instead of returning N for given cpu, return indices - (i such that N equals N[i]) - - output: cpuN[:] - * where cpuN[cpu] gives the list of Ns appointed to given cpu. - * if indices==True, return indices only - (cpuN[cpu] gives the list of indices such that 'cpu' is given - system sizes N[cpuN[cpu]]) - """ - size = ncpu - N2 = np.array(N[::-1],int) - times = N2**power - n = len(N2) - if ntime_per_cpu: - break - j = i+1 - if j==n: - break - - if any(cput==0): - m = sum(cput==0) - warnings.warn('Trying to divide load evenly to %i cpus left %i cpus idle.' %(size,m)) - return cpuN - - - -class _FitFunction: - def __init__(self,f,p): - self.p=p - self.f=f - def __call__(self,x,der=0): - if der==0: - return self.f(x,self.p) - else: - return self.f(x,self.p,der) - - - -def fit(f,p,xlist,ylist,fct=False): - ''' - Fit function f(x) with parameters p to given data. - - parameters: - =========== - f: function to fit; usage f(x,p) - p: initial guesses for parameters - xlist: x-data to fit - ylist: y-data to fit - fct: additionally return the function with fitted parameters - ''' - from scipy.optimize import fmin - def chi2(p,x,y): - err = y-f(x,p) - return sum(err**2) - res = fmin(chi2,p,args=(np.array(xlist),np.array(ylist)),disp=False) - if fct: - return res,_FitFunction(f,res) - else: - return res - - -def fit1(p,xlist,ylist,fct=False): - ''' - Fit y=a+b*x to given data. - - parameters: - =========== - p: initial guesses for a and b - xlist: x-data to fit - ylist: y-data to fit - fct: additionally return the function with fitted parameters - ''' - assert len(p)==2 - def f(x,p,der=0): - if der==0: - return p[0]+p[1]*x - elif der==1: - return p[1] - else: - return 0.0 - res = fit(f,p,np.array(xlist),np.array(ylist)) - if fct: - return res,_FitFunction(f,res) - else: - return res - - -def fit2(p,xlist,ylist,fct=False): - ''' - Fit y=a+0.5*b*(x-c)**2 to given data. - - parameters: - =========== - p: initial guesses for a,b and c. - Use None for reasonable initial guesses (with upward curvature!) - xlist: x-data to fit - ylist: y-data to fit - fct: additionally return the function with fitted parameters - ''' - if p==None: - imin = np.argmin(ylist) - p = [min(ylist),5*(max(ylist)-min(ylist))/(xlist[-1]-xlist[0])**2,xlist[imin]] - assert len(p)==3 - def f(x,p,der=0): - if der==0: - return p[0]+0.5*p[1]*(x-p[2])**2 - elif der==1: - return p[1]*(x-p[2]) - elif der==2: - return p[1] - - res = fit(f,p,np.array(xlist),np.array(ylist)) - if fct: - return res,_FitFunction(f,res) - else: - return res - - -def get_peak_positions(x,y,fact=0.01): - """ - Return the peaks of y(x) - - parameters: - =========== - x: x-grid (equally spaced) - y: y-grid, same length as x - fact: find peaks that are higher than fact times - the highest y-peak - - return: - ======= - peaks [x1,x2,...], [y1,y2,...] - """ - ymax = max(y) - N=len(x) - X, Y = [], [] - if y[1]fact*ymax: - X.append(x[0]) - Y.append(y[0]) - if y[-2]fact*ymax: - X.append(x[-1]) - Y.append(y[-1]) - - aux = xrange(1,N) - d = y[1:]-y[:-1] - peaks = np.extract( (d[:-1]>0)*(d[1:]<0),aux ) - for i in peaks: - a,b,c = fit2(None,x[i-1:i+2],-np.array(y[i-1:i+2])) - assert b>0 - if -a>fact*ymax: - X.append(c) - Y.append(-a) - - return np.array(X),np.array(Y) - - -def divisors(x): - ''' - Return all divisors of x. - - @param x: integer - ''' - assert isinstance(x,int) - lst=[x] - for i in range(x/2,0,-1): - if np.mod(x,i)==0: lst.append(i) - return np.array(lst) - -def gcd(a,b): - """ Return greatest common divisor of a and b.""" - while b!=0: - rem = a%b - a,b = b,rem - return a - - -def rotation_matrix(axis,angle): - """ Return the active rotation matrix with given axis and rotation angle. """ - n1, n2, n3 = axis/np.linalg.norm(axis) - c, s = cos(angle), sin(angle) - cc = 1-c - R = [[n1**2*cc + c, n1*n2*cc - n3*s, n1*n3*cc + n2*s], - [n1*n2*cc + n3*s, n2**2*cc + c, n2*n3*cc - n1*s], - [n1*n3*cc - n2*s, n2*n3*cc + n1*s, n3**2*cc + c ]] - return np.array(R) - - -def phival(x,y): - """ Return azimuthal angle for ALL x,y. """ - e=1E-16 - if x>e and y>e: - return atan(y/x) - elif x<-e and y>e: - return atan(y/x) + pi - elif x<-e and y<-e: - return atan(y/x) + pi - elif x>e and y<-e: - return atan(y/x)+2*pi - elif abs(x)<=e and abs(y)<=e: - return 0.0 - elif x>e and abs(y)<=e: - return 0.0 - elif y>e and abs(x)<=e: - return pi/2 - elif x<-e and abs(y)<=e: - return pi - elif y<-e and abs(x)<=e: - return 3*pi/2 - else: - #print x,y - raise RuntimeError('Strange things in phival') - - -def kronecker(i,j): - if i==j: - return 1 - else: - return 0 - -def matrix_pprint(m,fmt='%.4f'): - """ pretty-pring matrix. """ - assert len(m.shape)==2 - for i in range(len(m[:,0])): - print a2s(m[i,:],fmt=fmt) - -class Timer: - def __init__(self): - self.t0=time.time() - self.t=time.time() - - def __call__(self): - t=time.time() - dt=t-self.t - self.t=t - print 'dt',dt - - def __del__(self): - t=time.time() - print 'total time',t-self.t0 - - -def print_timing(func): - def wrapper(*arg): - t1 = time.time() - res = func(*arg) - t2 = time.time() - print '%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0) - return res - return wrapper - -def random_direction(vector=False): - """ Return random direction from 4*pi (phi,theta) or unit vector. """ - phi=np.random.random()*2*np.pi - theta=np.arccos(1-2*np.random.random()) - if not vector: - return phi,theta - else: - return np.array([np.sin(theta)*np.cos(phi),np.sin(theta)*np.sin(phi),np.cos(theta)]) - -def spherical_to_cartesian(theta,phi,r=1.0): - """ Transform spherical coordinates to cartesian ones. """ - return np.array([r*np.sin(theta)*np.cos(phi),r*np.sin(theta)*np.sin(phi),r*np.cos(theta)]) - -def cosd(x): - return cos(x*2*pi/360.0) - -def sind(x): - return sin(x*2*pi/360.0) - -def base_and_extension(filename): - """ Separate the basename and extension from given file name. """ - i=filename.rfind('.') - return filename[:i],filename[i+1:] - -def sec_to_time(secs): - """ - return days,hours,minutes and seconds from seconds. - - return list [dd,hh,mm,ss] - parameters: - ----------- - secs: seconds (int or float) - """ - d = int(secs // 86400) - s = secs % 86400 - h = int(s // 3600) - s = secs % 3600 - m = int(s // 60) - s = secs % 60 - s = int(s+.5) - return [d,h,m,s] - -def clean_indentation(st): - """ - Return multiple-line string into lowest indentation equal to zero. - Remove initial and trailing empty line. - """ - lines=st.splitlines() - mn=100 - for line in lines: - ns=0 - if len(line)<=1: - continue - else: - for c in line: - if c==" ": ns+=1 - else: break - mn=min(ns,mn) - new='' - for line in lines: - new+=line[mn:]+'\n' - first=False - for c in new: - if c=='\n' and not first: - new=new[1:] - else: - first=True - return new[:-1] - - -def max_norm(vecs): - """ Return the maximum norm of given list of vectors. """ - mx=0.0 - assert type(vecs)==type([]) - for vec in vecs: - mx=max( mx,norm(vec) ) - return mx - -def select_vector_mode(vec,mode): - """ Change given vector into given mode (default or global) - If mode is the same as vector, do nothing. - """ - from numpy import array as vector - from numpy import mod - listvec=( type(vec)==type([]) ) - if listvec and mode=='default': - return vec - elif not listvec and mode=='global': - return vec - elif listvec and mode=='global': - x=list(vec[0]) - for vec in vec[1:]: - x=x+list(vec) - return vector(x) - elif not listvec and mode=='default': - if mod(len(vec),3)!=0: - raise AssertionError - N=len(vec)/3 - x=[] - for i in range(N): - x.append( vector(vec[i*3:i*3+3]) ) - return x - - -def eof(file,tol=3): - """ Test enf of file within given byte tolerance. """ - from os import lseek - now=file.tell() - end=lseek(file.fileno(),0,2) - file.seek(now) - if end-now<=tol: - return True - else: - return False - -def a2s(a,fmt='%.14g',end=''): - """ Transforms vector array into a string with given format.""" - st='' - for i in range( len(a) ): - st=st+str(fmt%a[i]+'\t' ) - return st+end - - -def norm(a): - """ - Return the norm of the vector a. - """ - from numpy import dot - return sqrt( dot(a,a) ) - - -def gauss_fct(x,mean=0.,sigma=1.): - """ - Returns 1/sqrt(2*pi*sigma**2)*exp(-(x-mean)**2/(2*sigma**2) - mean=0 and sigma=1 on default - """ - return 1./sqrt(2*pi*sigma**2)*exp(-(x-mean)**2/(2*sigma**2) ) - - -def lorentzian(x,mean,width): - """ Return normalized Lorentzian with given mean and broadening. """ - return (width/np.pi)/((x-mean)**2+width**2) - - -def broaden(x,y=None,width=0.05,function='gaussian',extend=False,N=200,a=None,b=None,xgrid=None): - """ - Broaden a peaked distribution (DOS,optical spectra,...). - - parameters: - ----------- - x: data points (~energy axis) - y: heights of the peaks given with x. Default is one for all. - width: width parameter specific for given broadening function. - function: 'gaussian' or 'lorentzian' - extend: if True, extend xrange bit beyond min(x) and max(x) (unless [a,b] given) - N: number of points in output - a: if defined, is used as the lower limit for output - b: if defined, is used as the upper limit for output - xgrid: directly given x-grid - - return: xgrid, broadened distribution - """ - if y==None: - y=np.ones_like(x) - dx=[0.0,4*width][extend] - if a==None: - mn=min(x)-dx - else: - mn=a - if b==None: - mx=max(x)+dx - else: - mx=b - - if xgrid!=None: - pass - else: - xgrid = np.linspace(mn,mx,N) - - ybroad= np.zeros_like(xgrid) - for xi,yi in zip(x,y): - if function=='lorentzian': - w = (width/np.pi)/((xgrid-xi)**2+width**2) - elif function=='gaussian': - w = np.exp( -(xgrid-xi)**2/(2*width**2) ) / (np.sqrt(2*np.pi)*width) - ybroad = ybroad + yi*w - return xgrid, ybroad - - -def grid(min,max,N): - """ - Returns a grid with min and max as end-points and (N-1) divisions. - """ - from numpy import arange - return min+arange(N)/(N-1.0)*(max-min) - -def true_false(s): - """ - Interpret string s as boolean ans return True or False. - """ - s2=s.lower().strip() - if( s2=='true' or s2=='t' or s2=='yes' or s2=='y' ): - return True - elif( s2=='false' or s2=='f' or s2=='no' or s2=='n' ): - return False - else: - raise RuntimeError - - -def execute(cmd,echo=True): - from os import system - from sys import exit - if echo: - s=cmd - if len(s)>80: - s=s.split() - s1=' '.join(s[:-1]) - print 'Executing:',s1,'...' - print ' ...',s[-1],'...' - else: print 'Executing:',s,'...' - system(cmd) - - -def find_value(inp,key,fmt='default',default=None,position='start'): - ''' - Find value for key from file. - - Usage: value_string=find_key(f,key) - value_string_list=find_key(f,key,fmt='default') - - Parameters: - ----------- - inp - file object or file name - key - key string (corresponding to 'key=value') - fmt - the format of the value: - 'default' = return first value as string from the same line - 'all' = return the whole line from the same line - 'onestr' = return the whole line from the same line as one string - 'matrix' = return a matrix coming after key as float - 'strings' = return the non-empty lines coming after the key as str - 'bool' = interpret the line as boolean - 'test' = return True if key found, otherwise False - default - returned value if key not found - position - position to start searching - 'start' = beginning of the file object - 'current' = current position - Example: f=open('data.txt') - mass=float( find_value(f,'mass') ) - mat = find_value(f,'m','matrix') - ''' - f,opened=file_safeopen(inp) - if position=='start': - f.seek(0) - else: - pass - empty=0 - ret=None - while 1: - line=f.readline() - if(len(line)==0): empty+=1 - if(empty>1000): break - i=line.find('=') - hlp=line.split('=') - if hlp[0].strip()==key.strip() and i>=0: - if fmt=='test': ret=True - if fmt=='bool': ret=true_false(hlp[1]) - if fmt=='matrix': ret=read(f) - if fmt=='strings': ret=read(f,fmt='string') - if len(hlp)>1: value=hlp[1].split() - if fmt=='default': ret=value[0] - if fmt=='onestr': ret=hlp[1][:-1] - elif fmt=='all': ret=value[0:] - break - if opened: f.close() - if fmt=='test' and ret==None: - return False - elif ret!=None: - if fmt=='strings' and type(ret)!=type([]): - ret=[ret] - return ret - elif default!=None: - return default - else: - raise RuntimeError('key '+key+' not found from file '+f.name) - - -def read_file(file,mode='all',commentchar='#'): - """ - Read the lines in file into list of strings. - mode: all - read the whole file - comments - read only comments - nocomments - everything but comments - """ - from os.path import isfile - - opened=False - if isinstance(file,str): - if isfile(file): - f=open(file,'r') - opened=True - else: - raise RuntimeError('\n File '+file+' does not exist!') - else: - f=file - f.seek(0) - lines=f.readlines() - if mode=='all': - return lines - else: - ret=[] - for line in lines: - line=line.lstrip() - if len(line)==0: continue - if line[0]==commentchar and mode=='comments': ret.append(line) - if line[0]!=commentchar and mode=='nocomments': ret.append(line) - return ret - if opened: f.close() - -def file_safeopen(file,action='r'): - """ - Return file if file is a file-object, otherwise return the opened file - object and True/False if the file was opened or not. Action 'r','w','rw'. - """ - from os.path import isfile - opened=False - if isinstance(file,str): - if isfile(file): - f=open(file,action) - opened=True - else: - raise RuntimeError('\n File '+file+' does not exist!') - else: - f=file - return (f,opened) - - -def identify_column(col,file,commentchar='#'): - """ - Return the column index (starting from 0), identified by col. - The first row identifies the columns, and starts with commentchar. - Example: i=mix.identify_column('energy','stuff.out') -> i=2 with - stuff.out begining e.g. # time temperature energy distance ... - """ - from string import maketrans - f,opened = file_safeopen(file) - f.seek(0) - columns=f.readline() - i = columns.find(col) - if i<0: - raise RuntimeError('[identify_column] column '+col+' not found in '+file) - columns=columns.translate( maketrans('#.,;:|',' ') ).split() - if opened: f.close() - - return columns.index(col) - - -def read_column(col,file,commentchar='#'): - """ - Load a column with name col into one-dimensional NumPy array. - The first row identifies the columns, and starts with commentchar. - Example: energies=mix.read_column('energy','stuff.out') - (stuff.out begins e.g. # time temperature energy distance ...) - """ - from numpy import array - import sys - f,opened = file_safeopen(file) - dat = read(f) - if opened: f.close() - return dat[:,identify_column(col,file)] - - -def read(file,commentchar='#',fmt='array'): - """ - Read a data set from given file. - - * file -- file name of file object (for object the "next" set is read) - * commentchar -- character for comments, which are not read - * fmt -- format for output: - - - 'array' -- return two-dimensional numpy array - - 'string' -- return the set as a list of strings - - 'lines' -- return following non-empty lines as one string - """ - from os.path import isfile - if fmt=='array': from numpy import array - f,opened = file_safeopen(file) - r=[] - col=-1 - start=True - while 1: - line = f.readline() - if not line: break #end of file - line = line.lstrip().strip() - if line.isspace() or len(line)==0: - if start==True: continue # initial blank line - elif start==False: break # next blank line stops the data set - if line[0]=="#": continue # ignore comment line - cl = len(line.split()) - #if col!=-1 and cl!=col: - #break # different amount of columns->stop - if fmt=='array': - r.append([float(x) for x in line.split()]) - elif fmt=='string': - if line[-1]=='\n': line=line[:-1] - r.append(line) - else: - raise AssertionError('[mix.read] Invalid format.') - col = cl - start=False - if opened: f.close() - if r==[]: return None - if fmt=='array': - return array(r) - elif fmt=='lines': - return '\n'.join(r) - else: - return r - - -def write(file,a,fmt='%g'): - """ - Write a two-dimensional NumPy array a in a tabular form. - file can be file name or file object. - fmt is the format of output (Default: fmt='%g') - Example: - write('data.out',array,'%14.2f') - write(f,r) - - """ - try: - f=open(file,'w') - except: - f=file - for i in range(a.shape[0]): - for j in range(a.shape[1]): - f.write(fmt %a[i,j]+'\t') - f.write('\n') - f.flush() - -def abs_sum(a): - """ Return the sum of all elements (absolute values) in array. """ - return abs(a).sum() - - -def gplot(string,file=None,delete=False,view=False): - """Make a gnuplot file and call gnuplot to make an image from string. - If delete=True, remove the intermediate .gp -files - """ - from os import system - from os import environ - - if file==None: - for line in string.splitlines(): - if line.find('set output')>=0: - psfile=line.split("'")[1] - file=psfile.split('.')[0]+'.gp' - f=open(file,'w') - for line in string.splitlines(): - f.write(line.lstrip()+'\n') - f.close() - execute('gnuplot %s' %file, echo=False) - if delete: system('rm %s' %file) - psviewer=environ.get('PSVIEWER') - if psviewer=='': psviewer='gs' - i = file.rfind('.') - if i<0: - psfile=file+'.ps' - else: - psfile=file[:i]+'.ps' - if view: execute('%s %s&' %(psviewer,psfile) ) - - -def add_to_file(s,file): - """Add string to a file.""" - f=open(file,'r') - lines=f.readlines() - f.close() - f=open(file,'w') - lines.append(s+'\n') - f.writelines(lines) - f.close() - - -def add_file_appendix(file,app): - """ - Adds appendix to file name, preserving the file type. - Examples: - 'result.out' + '1' --> 'result_1.out' - 'result' '1' --> 'result_1' - 'result.out.xyz' '1' --> 'result.out_1.xyz' - """ - i = file.rfind('.') - if i<0: - return file+'_'+app - else: - return file[:i]+'_'+app+file[i:] - - -def parse_name_for_atoms(atoms): - """ - Returns a name for the atoms based on the symbols. - """ - symbols = atoms.get_chemical_symbols() - dict = {} - for symbol in symbols: - n = symbols.count(symbol) - if n not in dict: - dict.update({symbol:n}) - name = '' - for symbol in dict: - if dict[symbol] < 2: - name += symbol - else: - name += symbol+str(dict[symbol]) - return name - - -class AnalyticFunction: - """ Class for defining analytic functions with strings.""" - - def __init__(self,expr,variable='x',**kwargs): - """ e.g. f=AnalyticFunction('a*x**2+b*x',a=1,b=2). free=independent variable """ - self.f=expr - self.args=kwargs - self.args['variable']=variable - - def __call__(self,variable,**kwargs): - """ variable is the independent variable """ - self.args.update(kwargs) - self.args.update({self.args['variable']:variable}) - f=eval(self.f,globals(),self.args) - return f - - def set(self,**kwargs): - self.args.update(kwargs) - - def info(self): - print 'function:',self.f - print 'current arguments:',self.args - - def plot(self,a=None,b=None,N=200,out='screen'): - import pylab as pl - if a==b==None: - a,b=(-10,10) - - x=np.linspace(a,b,N) - f=[self(tx) for tx in x] - pl.plot(x,f) - if out=='screen': - pl.show() - else: - pl.savefig(out) - - -class IFunction: - """Simple class for interpolating functions on a grid.""" - def __init__(self,x,y,s=0): - """ x is the grid and y the corresponding values. - s is the "smoothness", default s=0 (f(x_i)=y_i exactly) - """ - from scipy.interpolate import splrep - from scipy.interpolate import splev - from scipy.interpolate import splint - self.splrep = splrep - self.splev = splev - self.splint = splint - self.tck = self.splrep(x,y,s=s) - - def __call__(self,x,der=0): - """Evaluate function or its derivatives (der=1,2) at x.""" - return self.splev(x,self.tck,der=der) - - def integrate(self,x1,x2): - """Integrate the function from x1 to x2.""" - return self.splint(x1,x2,self.tck) - - -class Const: - """ Simple class for constants. - - Example: - const=Const() - E=const.kB*T - const.list_constants() -> list of available constants - const.search('Boltzmann') - """ - def __init__(self,lst): - self.constants=[] - const=lst.splitlines() - for c in const: - self.add_const(c) - - def add_const(self,st): - """ Add constant (given as string) to list. """ - div=st.split(';') - if len(div)<4: return - for i in range(len(div)): div[i]=div[i].strip() - div[2]=float(div[2]) - self.constants.append(div) - exec('self.%s=%20.15g' %(div[1],div[2]) ) - - def list_constants(self): - """ List all the constants in this object. """ - for c in self.constants: print c - - def info(self,const): - """ Print info for the given constant. """ - for c in self.constants: - if c[1]==const.strip(): - print c - return - print 'Constant',const,'was not found.' - - def search(self,st): - """ Search a part of string from the constant database. """ - for c in self.constants: - hlp=[c[0],c[1],c[3]] - for part in hlp: - if part.find(st.strip())>=0: - print c - exit - - -SI_const=""" -speed of light in a vacuum; c; 2.99792458E+08; m/s -elementary charge (of proton); e; 1.60217733E-19; C -gravitational constant; G; 6.67259E-11; m^3/(kg*s^2) -gravitational acceleration; g; 9.80665; m/s^2 -unified atomic mass constant; u; 1.6605402E-27; kg -rest mass of electron; me; 9.1093897E-31; kg -rest mass of proton; mp; 1.6726231E-27; kg -rest mass of neutron; mn; 1.6749286E-27; kg -Planck constant; h; 6.6260755E-34; J*s -Planck constant/2pi; hbar; 1.05457266E-34; J*s -Hartree energy; Ha; 4.3597482E-18; J -Bohr radius; a_B; 5.29177249E-11; m -Avogadro constant; Na; 6.0221367E+23; 1/mol -Faraday constant (Na*e); F; 9.6485309E+04; C/mol -Boltzmann constant (R*Na); kB; 1.380658E-23; J/K -Stefan-Boltzman constant; sigma; 5.67051E-08; J/(s*m^2*K^4) -Bohr magneton (e*hbar/(2*me)); mu_B; 9.2740154E-24; J/T -nuclear magneton (e*hbar/(2*mp)); mu_N; 5.0507866E-27; J/T -electric constant (1/(4*pi*epsilon_0)); Cc; 8987551787.37; V*m/(A*s) -molar gas constant; Rc; 8.314510; J/(mol*K) -permeability of a vacuum (4*pi*10E-7); mu0; 1.25663706144E-7; V*s/(A*m) -permittivity of a vacuum; epsilon_0; 8.85418781762E-12; A*s/(V*m) -fine structure constant (e^2/(2*epsilon_0*h*c)); alpha; 7.29735308E-3; 1 """ - - -AU_const=""" -time unit; t_0;1.03274989966e-15; s -speed of light in a vacuum; c; 5850.79255585; L/T -elementary charge (of proton); e; 1; Q -gravitational constant; G; 7.97499949791e-37; L^3/(M*T^2) -gravitational acceleration; g; 1.97655923555e-19; L/T^2 -unified atomic mass constant; u; 1; M -rest mass of electron; me; 0.000548579895868; M -rest mass of proton; mp; 1.00727648749; M -rest mass of neutron; mn; 11.0086648911; M -Planck constant; h; 0.14716340209; E*T -Planck constant/2pi; hbar; 0.0234217826822; E*T -Hartree energy; Ha; 1; E -Bohr radius; a_B; 1; L -Avogadro constant; Na; 6.0221367E+23; 1/mol -Faraday constant (Na*e); F; 9.6485309E+04; Q/mol -Boltzmann constant (R*Na); kB; 3.1668297361e-06; E/K -Stefan-Boltzman constant; sigma; 3.76147527217e-26; E/(T*L^2*K^4) -Bohr magneton (e*hbar/(2*me)); mu_B; 2.12719063966e-06; E/Tesla -nuclear magneton (e*hbar/(2*mp)); mu_N; 1.15850422013e-09; E/Tesla -permeability of a vacuum (4*pi*10E-7); mu0; 3.67096691757e-08; V*s/(A*m) -permittivity of a vacuum; epsilon_0; 0.0795774702667; A*s/(V*m) -fine structure constant (e^2/(2*epsilon_0*h*c)); alpha; 7.29735308E-3; 1 """ - - -SI=Const(SI_const) -AU=Const(AU_const) - - -if __name__=='__main__': - pass - # - # testing class Const - # - #SI.list_constants() - #SI.info('e') - #SI.search('J') - #SI.add_const('kk;test;3.4;XX') - #SI.list_constants() - m=1/SI.a_B - C=1/SI.e - kg=1/SI.u - J=1/( SI.me*SI.e**4/(8*SI.h**2*SI.epsilon_0**2)*2 ) - s=sqrt( kg*m**2/J ) - A=C/s - - print 'Basic quantities' - print 'm',m - print 'C',C - print 'kg',kg - print 'J',J - print 's',s - print 'A',A - - t_0 =1/s - c =SI.c*m/s - G =SI.G*m**3/(kg*s**2) - g =SI.g*m/s**2 - me =SI.me*kg - mp =SI.mp*kg - mn =SI.mn*kg - h =SI.h*J*s - hbar =SI.hbar*J*s - Ha =SI.Ha*J - a_B =SI.a_B*m - F =SI.F*C - kB =SI.kB*J - sigma =SI.sigma *J/(s*m**2) - mu_B =SI.mu_B*J - mu_N =SI.mu_N*J - Cc =SI.Cc *J*m/(C*A*s) - mu0 =SI.mu0 *J*s/(A*m*C) - epsilon_0=SI.epsilon_0 *A*s*C/(m*J) - # C*V=J => V=J/C - - print '\nConstants' - print 't_0',t_0 - print 'c',c - print 'G',G - print 'g',g - print 'me',me - print 'mp',mp - print 'mn',mn - print 'h',h - print 'hbar',hbar - print 'Ha',Ha - print 'a_B',a_B - print 'F',F - print 'kB',kB - print 'sigma',sigma - print 'mu_B',mu_B - print 'mu_N',mu_N - print 'Cc',Cc - print 'mu0',mu0 - print 'epsilon_0',epsilon_0 - - a=[1.0,2.0,3.22] - print a2s(a) - - - f=AnalyticFunction('x**2+a',a=2,b=5) - f.info() - print f(5,n=3,a=1) - - - - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/pulay.py b/build/lib.macosx-10.7-x86_64-2.7/box/pulay.py deleted file mode 100644 index 3fd8c02..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/pulay.py +++ /dev/null @@ -1,67 +0,0 @@ -import numpy as np -from box.dummymixer import DummyMixer - -class PulayMixer(DummyMixer): - """ A class for Pulay mixing, as described in - https://wiki.fysik.dtu.dk/gpaw/documentation/densitymix/densitymix.html#densitymix """ - - - def __init__(self, mixing_constant=0.3, memory=8, convergence=1e-3, chop=None): - DummyMixer.__init__(self, mixing_constant, convergence) - self.name = 'Pulay' - self.memory = memory - self.initialized = False - self.A = np.zeros((self.memory, self.memory)) - self.alfa = np.zeros(self.memory) - self.chop = chop - - - def _initialize(self, xi): - """ Allocate fixed-sized arrays. """ - self.R = np.zeros((self.memory, len(xi))) - self.rho = np.zeros((self.memory, len(xi))) - self.initialized = True - - - def __call__(self, xi, yi): - simple = False - if self.it == 0: - self._initialize(xi) - self.it += 1 - lim = min(self.it, self.memory) - self.rho[1:lim] = self.rho[0:lim-1] - self.rho[0] = xi - self.R[1:lim] = self.R[0:lim-1] - self.R[0] = yi - xi - for i in range(lim): - for j in range(lim): - self.A[i,j] = np.dot(self.R[j], self.R[i]) - try: - inv_A = np.linalg.inv(self.A[:lim,:lim]) - except: - # problem in taking the inverse of the matrix A, - # use simple mixing in this step. - simple = True - if simple: - xb = (1-self.beta)*xi + self.beta*yi - else: - for i in range(lim): - up = np.sum(inv_A[:lim, i]) - down = np.sum(inv_A[:lim,:lim]) - self.alfa[i] = up/down - xb = np.zeros_like(xi) - for i in range(lim): - xb += self.alfa[i]*(self.rho[i] + self.beta*self.R[i]) - - # The input must not change more than chop for all - maxdev=max(abs(xb-xi)) - if self.chop!=None and maxdev>self.chop: - xb = xi + self.chop/maxdev*(xb-xi) - - fmax = max(abs(self.R[0])) - self.fmax.append(fmax) - if self.it > 3 and np.all(np.array(self.fmax[-3:]) < self.convergence): - return True, xb - else: - return False, xb - diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/random.py b/build/lib.macosx-10.7-x86_64-2.7/box/random.py deleted file mode 100644 index cc830fd..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/random.py +++ /dev/null @@ -1,55 +0,0 @@ -from box.interpolation import SplineFunction -import numpy as np - -class ArbitraryDistribution: - """ Class for generating random numbers form given distribution. """ - - def __init__(self,distr=None,xgrid=None): - """ - Initialize either with given probability distribution 'distr(x)', - or give the distribution on grid (given grid or 0,1,2,... by default) - """ - try: - distr(0.0) - self.f=distr - except: - self.x=xgrid - if self.x is None: - self.x=range(len(distr)) - self.distr=distr - self.f=SplineFunction(self.x,self.distr,k=1) - - # put the probability distribution f(x) on grid - self.N=1000 - self.lim=self.f.limits() - self.xgrid=np.linspace(self.lim[0],self.lim[1],self.N) - self.fvals=[self.f(z) for z in self.xgrid] - - # construct the distribution function F(x) - cum=[0.0] - for i in range(self.N-1): - cum.append(cum[-1]+self.fvals[i]+self.fvals[i+1]) - cum=np.array(cum)/2*(self.lim[1]-self.lim[0])/self.N - self.norm=cum[-1] - cum=cum/self.norm - self.F=SplineFunction(self.xgrid,cum,k=1) - - def __call__(self): - """ Generate random number from given distribution. """ - rnd=np.random.uniform(0.0,1.0) - return self.F.solve(rnd) - - def verify(self,nr=10000): - """ Plot and compare given distribution and simulated one. """ - c=np.array([self() for rnd in range(nr)]) - - import pylab as pl - pl.hist(c,len(self.xgrid),normed=True) - distr=[self.f(x)/self.norm for x in self.xgrid] - pl.plot(self.xgrid,distr,c='r') - pl.show() - -if __name__=='__main__': - y=[0,1,2,3,0.1,0.1,0.1,5] - f=ArbitraryDistribution(distr=y) - f.verify() \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/systems.py b/build/lib.macosx-10.7-x86_64-2.7/box/systems.py deleted file mode 100644 index a1acd35..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/systems.py +++ /dev/null @@ -1,425 +0,0 @@ -#!/usr/bin/env python -""" - Make various atomic structures into xyz-files. - - P. Koskinen 31.1 2008 -""" -from ase import Atoms as ase_Atoms -from ase import Atom -import numpy as np -from math import sqrt, atan, cos, sin -from box.mix import gcd -vec=np.array -dot=np.dot -pi = np.pi - - - -def graphene(n1,n2,R,height=5.0): - """ - Construct graphene lattice, multiply the primitive cell - n1 x n2 times in corresponding directions. - - .-----. - / / - / X / a2 - / / - X-----> - a1 - """ - from hotbit import Atoms - - if not isinstance(R,float): R=R[0] - a1=vec([R*np.cos(pi/6)*2,0.,0.]) - a2=0.5*a1 + vec([0.,1.5*R,0.]) - #assert n2%2==0 - - r=[] - for i1 in range(n1): - for i2 in range(n2): - corner = i1*a1+i2*a2 - r.append(corner) - r.append(corner+a1+vec([0.0,R,0.0])) - - cell=[[n1*a1[0], 0, 0],[n2*a2[0],n2*a2[1],0],[0,0,10]] - atoms=Atoms('C'*len(r),positions=r,cell=cell) - atoms.center(vacuum=height/2,axis=2) - atoms.set_pbc((True,True,False)) - return atoms - -def ZGNR(n,units=1,pbc='z',R=1.42): - """ - Make an n-zigzag graphene nanoribbon. - - parameters: - =========== - n: ribbon width (atomic rows) - length: ribbon length (unit cells) - pbc: periodic direction, 'x' or 'z' - R: bond length - """ - from hotbit import Atoms - a0 = R*np.sqrt(3) - atoms = ase_Atoms() - for i in range(n): - x = 1 - if np.mod(i,2)==1: - x=-1 - atoms += Atom('C',(0,3*R*i/2+3*R/4-x*R/4,0)) - atoms += Atom('C',(a0/2,3*R*i/2+3*R/4+x*R/4,0)) - - a = atoms.copy() - for i in range(units-1): - b = a.copy() - b.translate(((i+1)*a0,0,0)) - atoms += b - if pbc=='x': - atoms.set_pbc((True,False,False)) - atoms.set_cell((units*a0,1,1)) - atoms.center(vacuum=6,axis=1) - atoms.center(vacuum=6,axis=2) - elif pbc=='z': - atoms.set_pbc((False,False,True)) - atoms.rotate('z',np.pi/2) - atoms.rotate('x',np.pi/2) - atoms.set_cell((n*3*R/2*1.2/2,1,units*a0)) - atoms.translate( -atoms.get_center_of_mass() ) - atoms.center(axis=2) - return atoms - - - -def AGNR(n,units=1,pbc='z',R=1.42): - """ - Make an n-armchair graphene nanoribbon. - - parameters: - =========== - n: ribbon width (atomic rows) - length: ribbon length (unit cells) - pbc: periodic direction, 'x' or 'z' - R: bond length - """ - from hotbit import Atoms - a = R*np.sqrt(3) - atoms = ase_Atoms() - for i in range(n): - x0 = 0.0 - if np.mod(i,2)==1: - x0 = 1.5*R - atoms += Atom('C',(x0+0,i*a/2,0)) - atoms += Atom('C',(x0+R,i*a/2,0)) - - a = atoms.copy() - for i in range(units-1): - b = a.copy() - b.translate(((i+1)*3*R,0,0)) - atoms += b - if pbc=='x': - atoms.set_pbc((True,False,False)) - atoms.set_cell((units*3*R,1,1)) - atoms.center(vacuum=6,axis=1) - atoms.center(vacuum=6,axis=2) - elif pbc=='z': - atoms.set_pbc((False,False,True)) - atoms.rotate('z',np.pi/2) - atoms.rotate('x',np.pi/2) - atoms.set_cell((1,1,units*3*R)) - atoms.translate( -atoms.get_center_of_mass() ) - return atoms - -def armchair_ribbon(n1,n2,R,pbc='z'): - """ - Make ribbon out of graphene with armchair edges: n1 armchair periods in x-direction - and n2 stacked armchairs. - - parameters: - =========== - n1: length (units in periodic direction) - n2: width - R: bond distance - pbc: periodic direction ('z' or 'x') - """ - from hotbit import Atoms - a1=vec([3*R,0,0]) - a2=vec([0,2*R*np.cos(pi/6),0]) - atoms=ase_Atoms() - r=[] - for i1 in range(n1): - for i2 in range(n2): - corner=i1*a1+i2*a2 - atoms += Atom('C',corner) - atoms += Atom('C',corner+vec([R,0,0])) - atoms += Atom('C',corner+vec([1.5*R,R*np.cos(pi/6),0])) - atoms += Atom('C',corner+vec([2.5*R,R*np.cos(pi/6),0])) - - if pbc=='x': - atoms.set_cell( [n1*3*R,n2*2*R*np.cos(pi/6),1] ) - atoms.center(vacuum=5,axis=2) - atoms.center(vacuum=5,axis=1) - atoms.set_pbc((True,False,False)) - return atoms - elif pbc=='z': - atoms.translate( -atoms.get_center_of_mass() ) - atoms.rotate('z',np.pi/2) - atoms.rotate('x',np.pi/2) - atoms.center(vacuum=5,axis=1) - atoms.translate( -atoms.get_center_of_mass() ) - zmin = atoms.get_positions()[:,2].min() - atoms.translate( (0,0,-zmin) ) - atoms.set_cell( [n2*2*R*np.cos(pi/6),1,n1*3*R] ) - atoms.set_pbc((False,False,True)) - return atoms - else: - raise NotImplementedError('pbc only along x or z') - - - - - - -def zigzag_ribbon(n1,n2,R,pbc='z'): - """ - Make ribbon out of graphene with zigzag edges. - """ - from hotbit import Atoms - a1=vec([2*R*np.cos(pi/6),0,0]) - a2=vec([0,3*R,0]) - r=[] - for i1 in range(n1): - for i2 in range(n2): - corner=i1*a1+i2*a2 - r.append(corner+vec([R*np.cos(pi/6),R/2,0])) - r.append(corner+vec([0,R,0])) - r.append(corner+vec([0,2*R,0])) - r.append(corner+vec([R*np.cos(pi/6),2.5*R,0])) - cell=[n1*2*R*np.cos(pi/6),n2*3*R,1] - elements=['C']*len(r) - atoms = ase_Atoms(elements,r,cell=cell) - if pbc=='x': - atoms.set_cell( [2*R*np.cos(pi/6),n1*3*R,1] ) - atoms.center(vacuum=5,axis=2) - atoms.center(vacuum=5,axis=1) - atoms.set_pbc((True,False,False)) - return atoms - elif pbc=='z': - atoms.translate( -atoms.get_center_of_mass() ) - atoms.rotate('z',np.pi/2) - atoms.rotate('x',np.pi/2) - atoms.center(vacuum=5,axis=1) - atoms.translate( -atoms.get_center_of_mass() ) - zmin = atoms.get_positions()[:,2].min() - atoms.translate( (0,0,-zmin) ) - atoms.set_cell( [n2*2*R*np.cos(pi/6),1,n1*3*R] ) - atoms.set_pbc((False,False,True)) - return atoms - else: - raise NotImplementedError('pbc only along x or z') - - - -def nanotube_data(n,m,R=1.42): - """ - Return a dictionary if miscellaneous nanotube data - """ - from hotbit import Atoms - a=sqrt(3.0)*R - data={} - data['a'] = a - data['diameter'] = a/pi*sqrt(n**2+m**2+n*m) - data['radius'] = data['diameter']/2 - data['C'] = data['diameter']*pi - if n==m: - d = n - dR = 3*n - else: - d = gcd(n,m) - if np.mod(n-m,3*d)==0: - dR = 3*d - else: - dR = d - - data['T'] = 3*R*sqrt(n**2+m**2+n*m)/dR - data['metallic'] = (np.mod(n-m,3)==0) - data['semiconducting'] = not data['metallic'] - data['angle'] = atan( sqrt(3)*m/(m+2*n) ) - data['hexagons_per_cell'] = int(round(2*(m**2+n**2+m*n)/dR,0)) - if n==m: - data['type'] = 'armchair' - elif n==0 or m==0: - data['type'] = 'zigzag' - else: - data['type'] = 'chiral' - return data - - - - -def chiral_nanotube(n,m,R=1.42,element='C'): - """ - Construct a nanotube with a chiral container. - - parameters: - =========== - n,m: chiral indices - R: bond length - element: element type - """ - from hotbit import Atoms - a = np.sqrt(3)*R - a1 = np.array([a,0,0]) - a2 = np.array([0.5*a,-1.5*R,0]) - - rl = [] - shift = (a/2,-0.5*R,0) - for i in range(n): - origin = i*a1 - rl.append( origin ) - rl.append( origin+shift ) - - for j in range(m): - origin = (n-1)*a1 + (j+1)*a1 - rl.append( origin ) - rl.append( origin + shift ) - - atoms = Atoms() - C = n*a1 + m*a2 - Cn = np.linalg.norm(C) - T = np.array([C[1],-C[0],0]) - t = T/np.linalg.norm(T) - radius = Cn/(2*pi) - - atoms = Atoms() - for r in rl: - phi = np.dot(r,C)/Cn**2 * 2*pi - atoms += Atom( element,(radius*np.cos(phi),radius*np.sin(phi),np.dot(r,t)) ) - - atoms = Atoms(atoms,container='Chiral') - height = np.abs( np.dot(a1-a2,t) ) - angle = -np.dot(a1-a2,C)/Cn**2 * 2*pi - atoms.set_container(angle=angle,height=height) - - data = nanotube_data(n,m,R) - T, Ntot = data['T'],2*data['hexagons_per_cell'] - data['height']=height - data['twist']=angle - atoms.data = data - return atoms - - - -def nanotube(n,m,R=1.42,length=1,element='C'): - ''' - Create a nanotube around z-axis. - - parameters: - ----------- - n,m: chiral indices - R: nearest neighbor distance - length: number of unit cells - element: element symbol - ''' - from hotbit import Atoms - at = Atoms( pbc = ( False, False, True ) ) - - sq3 = sqrt(3.0) - a0 = R - gcn = gcd(n, m) - - a1 = np.array( [ sq3/2, 0.5 ] ) * a0 * sq3 - a2 = np.array( [ sq3/2, -0.5 ] ) * a0 * sq3 - - h = float(float(n)-float(m))/float(3*gcn) - - if h-int(h) == 0.0: - RR = 3 - else: - RR = 1 - - c = n*a1 + m*a2 - abs_c = sqrt(dot(c, c)) - - a = ( -(2*m+n)*a1 + (2*n+m)*a2 )/(gcn*RR) - abs_a = sqrt(dot(a, a)) - - eps = 0.01 - b = [ [ 1./3-eps, 1./3-eps ], [ 2./3-eps, 2./3-eps ] ] - - nxy = max(n, m)+100 - eps = 0.00001 - - for x in xrange(-nxy, nxy): - for y in xrange(-nxy, nxy): - for b1, b2 in b: - p = (x+b1)*a1 + (y+b2)*a2 - abs_p = sqrt(dot(p, p)) - - sa = dot(p, a)/(abs_a**2) - sc = dot(p, c)/(abs_c**2) - - if sa >= 0 and sa < 1-eps and sc >= 0 and sc < 1-eps: - r = ( cos(2*pi*sc)*abs_c/(2*pi), sin(2*pi*sc)*abs_c/(2*pi), sa*abs_a ) - at += Atom( element, r ) - at.set_cell( ( 2*abs_c/(2*pi), 2*abs_c/(2*pi), length*abs_a ) ) - b = at.copy() - - for i in range(length-1): - b.translate( ( 0.0, 0.0, abs_a ) ) - for j in b: - at += j - at.center(axis=2) - rcm = at.get_center_of_mass() - at.translate( (-rcm[0],-rcm[1],0) ) - at.set_pbc((False,False,True)) - at.data = nanotube_data(n,m) - return at - - - -def CNT_list(i=None): - """ - Select a carbon nanotube from a list. - - Order all CNTs according to the number of atoms in the - unit cell, with diameters larger than 2.0 Angstrom, - assuming 1.42 Angstrom bond length. - - - parameters: - ----------- - i: return the (n,m) tuple of i'th CNT in the list. - If i==None, return the whole list of - (N,d,L,n,m) -tuples (N=atom count, d=diameter, - L=unit cell length, n,m=chiral indices) - """ - R = 1.42 - dmin = 2.0 - - data = [] - for n in range(1,20): - for m in range(n+1): - cnt = nanotube_data(n,m,R=R) - N = cnt['hexagons_per_cell']*2 - d = cnt['diameter'] - L = cnt['T'] - if d>self.txt, '\nTiming:' - print>>self.txt, ' label time calls %sub %covered %tot' - print>>self.txt, '-'*79 - print>>self.txt, txt, - print>>self.txt, '-'*79 - print>>self.txt, 'total time %12.3f seconds %s' % (total, self.human_readable_time(total)) - print>>self.txt, asctime() - self.smry=True - self.txt.flush() - - - def human_readable_time(self, seconds): - seconds = int(round(seconds)) - hours = seconds/3600 - seconds -= hours*3600 - mins = seconds/60 - seconds -= mins*60 - return "%i h %i min %i sec" % (hours, mins, seconds) - - -class OneTimer: - def __init__(self,key): - self.key=key - self.t0=time.time() - self.durations=[] - self.running=False - - def start(self): - self.t1=time.time() - self.running=True - - def stop(self): - assert self.running - self.t2=time.time() - self.durations.append( self.t2-self.t1 ) - self.running=False - - def is_running(self): - return self.running - - def get_time(self): - if self.running==True: - self.stop() - return sum(self.durations) - - def get_calls(self): - return len(self.durations) - - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/box/vtk.py b/build/lib.macosx-10.7-x86_64-2.7/box/vtk.py deleted file mode 100644 index d2872cb..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/box/vtk.py +++ /dev/null @@ -1,69 +0,0 @@ -import box.mix as mix - -def rectilinear_vtk(grid,data,fname): - """ Write data in rectilinear grid into .vtk file. - - parameters: - ----------- - grid: grid[:,{0,1,2}] x-, y-, and z-grids - data: data on this regular grid. - fname: output file name - """ - f=open(fname,'w') - nx, ny, nz=len(grid[0][:]), len(grid[1][:]), len(grid[2][:]) - print>>f,"# vtk DataFile Version 2.0" - print>>f,"...some rectilinear grid data." - print>>f,"ASCII" - print>>f,"DATASET RECTILINEAR_GRID" - print>>f,"DIMENSIONS %i %i %i" %(nx,ny,nz) - print>>f,"X_COORDINATES %i double" %nx - print>>f,mix.a2s(grid[0][:]) - print>>f,"Y_COORDINATES %i double" %ny - print>>f,mix.a2s(grid[1][:]) - print>>f,"Z_COORDINATES %i double" %nz - print>>f,mix.a2s(grid[2][:]) - print>>f,"POINT_DATA %i" %(nx*ny*nz) - print>>f,"SCALARS some_data double" - print>>f,"LOOKUP_TABLE default" - for k in range(nz): - for j in range(ny): - for i in range(nx): - print>>f, data[i,j,k] - print 'min ... max=',min(data.flatten()),'...',max(data.flatten()) - f.close() - - - -def atoms_vtk(atoms,scalars={},vectors={},filename=None): - ''' - vtk output of atoms - - @param filename: vtk output file name - @param atoms: atoms object - @param scalars: dictionary of atoms' scalar properties - @param vectors: dictionary of atoms' vector properties - ''' - if filename==None: - filename=atoms.get_name()+'.vtk' - N=len(atoms) - f=open(filename,'w') - f.write('# vtk DataFile Version 2.0 \nAtoms %s\n' %atoms.get_name()) - f.write('ASCII \nDATASET UNSTRUCTURED_GRID\n') - f.write('POINTS %i double \n ' %N) - fmt='%20.14f' #output format for floats - - # Point data (atom coordinates) and cell data (bonds) - for r in atoms.get_positions(): - f.write('%s\n' %mix.a2s(r,fmt=fmt)) - - # First the data related to atoms - f.write('POINT_DATA %i\n' %N) - for scalar in scalars: - print>>f, 'SCALARS %s double 1\nLOOKUP_TABLE default' %scalar - for value in scalars[scalar]: - print>>f, '%12.6f' %(value*1.0) - for vector in vectors: - print>>f, 'VECTORS %s double\n' %vector - for value in properties: - print>>f, mix.a2s(value,fmt=fmt) - f.close() \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/__init__.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/__init__.py deleted file mode 100644 index ba65747..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/__init__.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (C) 2008 NSC Jyvaskyla -# Please see the accompanying LICENSE file for further information. - -from atoms import Atoms -from aseinterface import Hotbit, database_from_path -from atoms import ExtendedTrajectory -from electrostatics import Electrostatics -from element import Element -from elements import Elements -from environment import Environment -from environment import LinearlyPolarizedLaser -from grids import Grids -from interactions import Interactions -from occupations import Occupations -from output import Output -from repulsion import RepulsivePotential -from repulsion import Repulsion -from solver import Solver -from states import States -from wfpropagation import WFPropagation - -from hotbit.analysis import LinearResponse -from hotbit.analysis import MullikenAnalysis -from hotbit.analysis import MullikenBondAnalysis -from hotbit.analysis import DensityOfStates - -from hotbit.containers import DoubleChiral -from hotbit.containers import Bravais -from hotbit.containers import Chiral -from hotbit.containers import Wedge -from hotbit.containers import Sphere -from hotbit.containers import Saddle -from hotbit.containers import Gaussian -from hotbit.containers import Slab -from hotbit.containers import ContainerTest1 - -from hotbit.parametrization import SlaterKosterTable -from hotbit.parametrization import KSAllElectron -from hotbit.parametrization import RepulsiveFitting -from hotbit.parametrization import ParametrizationTest - -from os import environ, path - -import atexit -import _hotbit - -hbpar = environ.get('HOTBIT_PARAMETERS') -fixpar = path.join(environ.get('HOTBIT_PARAMETERS'),'fixed_parameters') -testpar = path.join(environ.get('HOTBIT_PARAMETERS'),'inofficial') - - -# -# Free eigenvalue solver workspace on exit -# -atexit.register(_hotbit.free_geig_workspace) -from hotbit.version import hotbit_version - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/__init__.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/__init__.py deleted file mode 100644 index 68d7950..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from lr import LinearResponse -from mulliken import MullikenAnalysis, MullikenBondAnalysis, DensityOfStates diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/lr.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/lr.py deleted file mode 100644 index 755aac2..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/lr.py +++ /dev/null @@ -1,273 +0,0 @@ -import numpy as np -from numpy.linalg.linalg import eigh -from box import mix -from ase.units import Hartree -dot=np.dot -sqrt=np.sqrt -import sys -from box.timing import Timer - -class LinearResponse: - """ - - """ - def __init__(self,calc,energy_cut=10.0,timing=False,txt=None): - """ - Calculate linear optical response (LR-TD-DFTB). - For details, see Niehaus et.al. Phys. Rev. B 63, 085108 (2001) - - parameters: - =========== - calc: calculator object - energy_cut: max energy (in eV) for particle-hole excitations - Used to select all particle-hole excitations in the - construction of the matrix, that have excitation energy - less than this value. This implies, that if we are - interested in optical response up to some energy, - energy_cut should be slightly larger. - timing: output timing summary after calculation - out: output object (file name or object) - """ - self.calc=calc - self.st=calc.st - self.el=calc.el - self.es=calc.st.es - self.energy_cut=energy_cut/Hartree - #self.noc=self.st.get_hoc()+1 #number of occupied states (not index) - # do not use HOC - self.nel=self.el.get_number_of_electrons() - self.norb=self.el.get_nr_orbitals() - self.e=self.st.get_eigenvalues()[0,:] - self.f=self.st.get_occupations()[0,:] - if np.any( abs(self.st.wf.flatten().imag)>1E-10 ): - raise ValueError('Wave functions should not be complex.') - self.wf = self.st.wf[0].real - self.S = self.st.S[0].real - self.N=len(self.el) - self.SCC = self.calc.get('SCC') - atoms=calc.get_atoms() - if atoms.pbc.any(): - raise AssertionError('No linear response for extended, periodic systems!') - - #if abs(np.mod(self.nel,2))>1E-2: - #raise RuntimeError('Linear response only for closed shell systems! (even number of electrons)') - #if abs(self.nel-2*self.noc)>1E-2: - #print 'Number of electrons:',self.nel - #print '2*Number of occupied states:',2*self.noc - #raise RuntimeError('Number of electrons!=2*number of occupied orbitals. Decrease electronic temperature?') - if txt is None: - self.txt=sys.stdout - else: - self.txt=open(txt,'a') - self.timer=Timer('Linear Response',txt=self.txt) - self.timing=timing - self.done=False - self.allowed_cut = 1E-2 #if osc.strength is smaller, transition is not allowed - self._initialize() - - def _initialize(self): - """ - Perform some initialization calculations. - """ - self.timer.start('init') - self.Swf = np.dot(self.S,self.wf.transpose()) #try to avoind the transpose - self.timer.stop('init') - - - def get_linear_response(self): - """ Get linear response spectrum in eV. """ - return self.omega*Hartree, self.F - - - def mulliken_transfer(self,k,l): - """ Return Mulliken transfer charges between states k and l. """ - q=[] - for i,o1,no in self.el.get_property_lists(['i','o1','no']): - #qi=sum( [self.wf[a,k]*self.Swf[a,l]+self.wf[a,l]*self.Swf[a,k] for a in range(o1,o1+no)] ) - qi=sum( [self.wf[k,a]*self.Swf[a,l]+self.wf[l,a]*self.Swf[a,k] for a in range(o1,o1+no)] ) - q.append(qi/2) - return np.array(q) - - def run(self): - """ Run the calculation. """ - if self.done==True: - raise AssertionError('Run LR calculation only once.') - - print>>self.txt, '\nLR for %s (charge %.2f). ' %(self.el.get_name(),self.calc.get_charge()), - - # - # select electron-hole excitations (i occupied, j not occupied) - # de = excitation energy ej-ei (ej>ei) - # df = occupation difference fi-fj (ej>ei so that fi>fj) - # - de=[] - df=[] - particle_holes=[] - self.timer.start('setup ph pairs') - for i in range(self.norb): - for j in range(i+1,self.norb): - energy=self.e[j]-self.e[i] - occup=(self.f[i]-self.f[j])/2 #normalize the double occupations (...is this rigorously right?) - if energy1E-6: - assert energy>0 and occup>0 - particle_holes.append([i,j]) - de.append(energy) - df.append(occup) - self.timer.stop('setup ph pairs') - de=np.array(de) - df=np.array(df) - - # - # setup the matrix (gamma-approximation) and diagonalize - # - self.timer.start('setup matrix') - dim=len(de) - print>>self.txt, 'Dimension %i. ' %dim, - if not 0>self.txt, 'coupling matrix constructed. ', - self.txt.flush() - self.timer.start('diagonalize') - omega2,eigv=eigh(matrix) - self.timer.stop('diagonalize') - print>>self.txt, 'Matrix diagonalized.', - self.txt.flush() -# assert np.all(omega2>1E-16) - print omega2 - omega=sqrt(omega2) - - # calculate oscillator strengths - F=[] - collectivity=[] - self.timer.start('oscillator strengths') - for ex in range(dim): - v=[] - for i in range(3): - v.append( sum( rv[:,i]*sqrt(df[:]*de[:])*eigv[:,ex])/sqrt(omega[ex])*2 ) - F.append( omega[ex]*dot(v,v)*2.0/3 ) - collectivity.append( 1/sum(eigv[:,ex]**4) ) - self.omega=omega - self.F=F - self.eigv=eigv - self.collectivity=collectivity - self.dim=dim - self.particle_holes=particle_holes - self.timer.stop('oscillator strengths') - if self.timing: - self.timer.summary() - self.done=True - self.emax=max(omega) - self.particle_holes=particle_holes - - - def info(self): - """ Some info about excitations (energy, main p-h excitations,...) """ - print '\n#e(eV), f, collectivity, transitions ...' - for ex in range(self.dim): - if self.F[ex]=self.allowed_cut: p+=1 - if p==i: - return self.omega[k]*Hartree, self.F[k] - - - def write_spectrum(self,filename=None): - """ Write the linear response spectrum into file. """ - if filename==None: - filename='linear_spectrum.out' - o=open(filename,'w') - print>>o, '#e(eV), f' - for ex in range(self.dim): - print>>o, '%10.5f %10.5f %10.5f' %(self.omega[ex]*Hartree,self.F[ex],self.collectivity[ex]) - o.close() - - def read_spectrum(self,filename): - """ Read the linear response from given file. - - Format: energy & oscillator strength. - """ - o=open(filename,'r') - data=mix.read(filename) - self.omega, self.F, self.collectivity=data[:,0], data[:,1], data[:,2] - - - def plot_spectrum(self,filename,width=0.2,xlim=None): - """ Make pretty plot of the linear response. - - Parameters: - =========== - filename: output file name (&format, supported by matplotlib) - width: width of Lorenzian broadening - xlim: energy range for plotting tuple (emin,emax) - """ - import pylab as pl - if not self.done: - self.run() - - e,f=mix.broaden(self.omega*Hartree,self.F,width=width,N=1000,extend=True) - f=f/max(abs(f)) - - pl.plot(e,f,lw=2) - xs, ys = pl.poly_between(e, 0, f) - pl.fill(xs,ys,fc='b',ec='b',alpha=0.5) - pl.ylim(0,1.2) - - if xlim==None: - pl.xlim(0,self.emax*Hartree*1.2) - else: - pl.xlim(xlim) - pl.xlabel('energy (eV)') - pl.ylabel('linear optical response') - pl.title('Optical response') - pl.savefig(filename) - #pl.show() - pl.close() - - - - - - - - - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/mulliken.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/mulliken.py deleted file mode 100644 index 9bfb085..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/mulliken.py +++ /dev/null @@ -1,552 +0,0 @@ -from ase.units import Hartree -import numpy as np -from weakref import proxy -from box import mix - -def get_angular_momenta(l): - ret = [] - if 's' in l: ret.append(0) - if 'p' in l: ret.append(1) - if 'd' in l: ret.append(2) - return ret - - -class MullikenAnalysis: - def __init__(self, calc): - """ - Class for Mulliken charge analysis. - - q_I = sum_k w_k Trace_I Re[ rho(k)*S(k) ] - = sum_(i in I) Re [ sum_k w_k sum_j rho(k)_ij*S(k)_ji ] - = sum_(i in I) Re [ sum_k w_k sum_j rho(k)_ij*S(k)^T_ij ] - = sum_(i in I) [ sum_k w_k diag(k)_i ], - = sum_(i in I) diag_i - - where diag(k)_i = Re [sum_j rho(k)_ij * S(k)^T_ij] - and diag_i = sum_k w_k diag(k)_i - - Charge in pieces: - - q_(k,a,mu) = wk * f(k,a) * Re [sum_nu wf(k,a,mu)^*wf[k,a,nu]*S(k,mu,nu)] - = wk * f(k,a) * aux(k,a,mu) - - where aux(k,a,mu) = Re [wf(k,a,mu)*sum_nu wf(k,a,nu)*S(k,mu,nu)] - - All the units are, also inside the class, in eV and Angstroms. - """ - self.calc = proxy(calc) - st = self.calc.st - self.st = st - self.N = self.calc.el.N - self.nk = self.calc.st.nk - self.wk = self.calc.st.wk.copy() - norb = self.calc.st.norb - self.norb = norb - - self.diag = np.zeros((norb)) - for k in xrange(self.nk): - diag_k = ( st.rho[k]*st.S[k].transpose() ).sum(axis=1).real - self.diag += self.wk[k]*diag_k - - self.aux = np.zeros((self.nk,norb,norb)) - wf = st.wf.copy() - wfc = st.wf.copy().conjugate() - for k in xrange(self.nk): - for a in range(norb): - self.aux[k,a] = ( wfc[k,a] * np.dot(wf[k,a],st.S[k].transpose()) ).real - - - def trace_I(self,I,matrix): - """ Return partial trace over atom I's orbitals. """ - ret = 0.0 - I = self.calc.el.orbitals(I,indices=True) - for i in I: - ret += matrix[i,i] - return ret - - - def get_atoms_mulliken(self): - """ Return Mulliken populations. """ - q = [] - for o1, no in self.calc.el.get_property_lists(['o1','no']): - q.append( self.diag[o1:o1+no].sum() ) - return np.array(q)-self.calc.el.get_valences() - - - def get_atom_mulliken(self, I): - """ - Return Mulliken population for atom I. - - parameters: - =========== - I: atom index - """ - orbs = self.calc.el.orbitals(I,indices=True) - return sum( self.diag[orbs] ) - - - def get_basis_mulliken(self, mu): - """ - Return Mulliken population of given basis state. - - parameters: - =========== - mu: orbital index (see Elements' methods for indices) - """ - return self.diag[mu] - - - def get_atom_all_angmom_mulliken(self,I): - """ Return the Mulliken population of atom I from eigenstate a, for all angmom.""" - - orbs = self.calc.el.orbitals(I,indices=True) - all = self.diag[orbs] - pop = np.zeros((3,)) - pop[0] = all[0] - if len(all)>1: pop[1] = all[1:4].sum() - if len(all)>4: pop[2] = all[4:].sum() - return pop - - - def get_atom_wf_mulliken(self,I,k,a,wk=True): - """ - Return Mulliken population for given atom and wavefunction. - - parameters: - =========== - I: atom index - k: k-vector index - a: eigenstate index - wk: embed k-point weight in population - """ - w = 1.0 - if wk: w = self.wk[k] - orbs = self.calc.el.orbitals(I,indices=True) - return w*self.aux[k,a,orbs].sum() - - - def get_atom_wf_all_orbital_mulliken(self,I,k,a,wk=True): - """ - Return orbitals' Mulliken populations for given atom and wavefunction. - - parameters: - =========== - I: atom index (returned array size = number of orbitals on I) - k: k-vector index - a: eigenstate index - wk: embed k-point weight in population - """ - w = 1.0 - if wk: w = self.wk[k] - orbs = self.calc.el.orbitals(I,indices=True) - q = [] - for mu in orbs: - q.append( w*self.aux[k,a,mu] ) - return np.array(q) - - - def get_atom_wf_all_angmom_mulliken(self,I,k,a,wk=True): - """ - Return atom's Mulliken populations for all angmom for given wavefunction. - - parameters: - =========== - I: atom index - k: k-vector index - a: eigenstate index - wk: embed k-point weight into population - - return: array (length 3) containing s,p and d-populations - """ - all = self.get_atom_wf_all_orbital_mulliken(I,k,a,wk) - pop = np.zeros((3,)) - pop[0] = all[0] - if len(all)>1: pop[1] = all[1:4].sum() - if len(all)>4: pop[2] = all[4:].sum() - return pop - - - -class DensityOfStates(MullikenAnalysis): - def __init__(self, calc): - """ - A class that calculates different kinds of local and projected - density of states using the Mulliken charges. - - Units also inside this class are in eV - """ - MullikenAnalysis.__init__(self, calc) - - self.e = self.calc.st.get_eigenvalues()*Hartree - self.e -= self.calc.get_fermi_level() - self.eflat = self.e.flatten() - self.emin, self.emax = self.eflat.min(), self.eflat.max() - - - - def get_density_of_states(self,broaden=False,projected=False,occu=False,width=0.05,window=None,npts=501): - """ - Return the full density of states. - - Sum of states over k-points. Zero is the Fermi-level. - Spin-degeneracy is NOT counted. - - parameters: - =========== - broaden: * If True, return broadened DOS in regular grid - in given energy window. - * If False, return energies of all states, followed - by their k-point weights. - projected: project DOS for angular momenta - occu: for not broadened case, return also state occupations - width: Gaussian broadening (eV) - window: energy window around Fermi-energy; 2-tuple (eV) - npts: number of data points in output - - return: * if projected: e[:],dos[:],pdos[l,:] (angmom l=0,1,2) - * if not projected: e[:],dos[:] - * if broaden: e[:] is on regular grid, otherwise e[:] are - eigenvalues and dos[...] corresponding weights - * if occu: e[:],dos[:],occu[:] - - """ - if broaden and occu or projected and occu: - raise AssertionError('Occupation numbers cannot be returned with broadened DOS.') - if projected: - e,dos,pdos = self.get_local_density_of_states(True,width,window,npts) - return e,dos.sum(axis=0),pdos.sum(axis=0) - - mn, mx = self.emin, self.emax - if window is not None: - mn, mx = window - - x, y, f = [],[],[] - for a in range(self.calc.el.norb): - x = np.concatenate( (x,self.e[:,a]) ) - y = np.concatenate( (y,self.calc.st.wk) ) - f = np.concatenate( (f,self.calc.st.f[:,a]) ) - x=np.array(x) - y=np.array(y) - f=np.array(f) - if broaden: - e,dos = mix.broaden(x, y, width=width, N=npts, a=mn, b=mx) - else: - e,dos = x,y - if occu: - return e,dos,f - else: - return e,dos - - - def get_local_density_of_states(self,projected=False,width=0.05,window=None,npts=501): - """ - Return state density for all atoms as a function of energy. - - parameters: - =========== - projected: return local density of states projected for - angular momenta 0,1 and 2 (s,p and d) - ( sum of pldos over angular momenta = ldos ) - width: energy broadening (in eV) - window: energy window around Fermi-energy; 2-tuple (eV) - npts: number of grid points for energy - - return: projected==False: - energy grid, ldos[atom,grid] - projected==True: - energy grid, - ldos[atom, grid], - pldos[atom, angmom, grid] - """ - mn, mx = self.emin, self.emax - if window is not None: - mn, mx = window - - # only states within window - kl,al,el = [],[],[] - for k in range(self.nk): - for a in range(self.norb): - if mn<=self.e[k,a]<=mx: - kl.append(k) - al.append(a) - el.append(self.e[k,a]) - - ldos = np.zeros((self.N,npts)) - if projected: - pldos = np.zeros((self.N,3,npts)) - for i in range(self.N): - q = [ self.get_atom_wf_mulliken(i,k,a,wk=True) for k,a in zip(kl,al) ] - egrid, ldos[i,:] = mix.broaden( el,q,width=width,N=npts,a=mn,b=mx ) - if projected: - q = np.array( [self.get_atom_wf_all_angmom_mulliken(i,k,a,wk=True) for k,a in zip(kl,al)] ) - for l in range(3): - egrid, pldos[i,l] = mix.broaden( el,q[:,l],width=width,N=npts,a=mn,b=mx ) - - if projected: - assert np.all( abs(ldos-pldos.sum(axis=1))<1E-6 ) - return egrid, ldos, pldos - else: - return egrid, ldos - - - - -class MullikenBondAnalysis(MullikenAnalysis): - - def __init__(self, calc): - """ - Class for bonding analysis using Mulliken charges. - """ - MullikenAnalysis.__init__(self, calc) - rhoSk = [] - HS = [] - rhoM = [] - n=self.st.norb - epsilon = [] - for mu in xrange(self.norb): - epsilon.append( self.calc.el.orbitals(mu,basis=True)['energy'] ) - epsilon = np.array(epsilon) - #epsilon-bar matrix of Bornsen et al J.Phys.:Cond.mat 11, L287 (1999) - aux = epsilon.repeat(n).reshape(n,n) - eps = 0.5*(aux+aux.transpose()) - for k in range(self.nk): - rhoSk.append( np.dot(self.st.rho[k],self.st.S[k]) ) - HS.append( self.st.H0[k] - self.st.S[k]*eps ) - rhoM.append( self.st.rho[k]*((self.st.H0[k]-self.st.S[k]*eps).transpose()) ) - self.rhoSk = np.array(rhoSk) - self.rhoM = np.array(rhoM) - self.HS = np.array(HS) - self.epsilon = np.array(epsilon) - self.SCC = self.calc.get('SCC') - - - def get_mayer_bond_order(self,i,j): - """ - Return Mayer bond-order between two atoms. - - Warning: appears to work only with periodic systems - where orbitals have no overlap with own images. - - parameters: - =========== - I: first atom index - J: second atom index - """ - assert type(i)==int and type(j)==int - orbi = self.calc.el.orbitals(i, indices=True) - orbj = self.calc.el.orbitals(j, indices=True) - - M = 0.0 - for k in xrange(self.nk): - for mu in orbi: - for nu in orbj: - M += self.wk[k] * self.rhoSk[k,mu,nu]*self.rhoSk[k,nu,mu] - assert abs(M.imag)<1E-12 - return M.real - - - def get_atom_energy(self, I=None): - """ - Return the absolute atom energy (in eV). - - Warning: bonding & atom energy analysis less clear for - systems where orbitals overlap with own periodic images. - - parameters: - =========== - I: atom index. If None, return all atoms' energies - as an array. - """ - if I==None: - return np.array( [self.get_atom_energy(i) for i in range(self.N)] ) - - if self.SCC: - coul = 0.5*self.calc.st.es.G[I,I]*self.st.dq[I]**2 - else: - coul = 0.0 - - elm = self.calc.el.elements[self.calc.el.symbols[I]] - o1, no = self.calc.el.get_property_lists(['o1','no'])[I] - - eorb = 0.0 - for k,wk in enumerate(self.wk): - eorb += wk*np.sum( self.rhoM[k,o1:o1+no,o1:o1+no] ) - - erep = self.calc.rep.get_pair_repulsive_energy(I,I) #self-repulsion for pbc - epp = self.calc.pp.get_pair_energy(I,I) #self-energy from pair potentials - A = (coul + erep + epp + eorb )*Hartree + self.get_promotion_energy(I) - assert abs(A.imag)<1E-12 - return A.real - - - def get_promotion_energy(self, I=None): - """ - Return atom's promotion energy (in eV). - - Defined as: - E_prom,I = sum_(mu in I) [q_(mu) - q_(mu)^0] epsilon_mu - - parameters: - =========== - I: atom index. If None, return all atoms' energies - as an array. - """ - if I==None: - return np.array( [self.get_promotion_energy(i) for i in range(self.N)] ) - - e = 0.0 - for mu in self.calc.el.orbitals(I, indices=True): - q = self.get_basis_mulliken(mu) - q0 = self.calc.el.get_free_population(mu) - emu = self.calc.el.orbitals(mu,basis=True)['energy'] - e += (q-q0)*emu - - assert abs(e.imag)<1E-12 - return e.real * Hartree - - - def get_bond_energy(self,i,j): - """ - Return the absolute bond energy between atoms (in eV). - - Warning: bonding & atom energy analysis less clear for - systems where orbitals overlap with own periodic images. - - parameters: - =========== - i,j: atom indices - """ - rep = self.calc.rep.get_pair_repulsive_energy(i,j) - epp = self.calc.pp.get_pair_energy(i,j) - - if self.SCC: - coul = self.st.es.G[i,j]*self.st.dq[i]*self.st.dq[j] - else: - coul = 0.0 - - o1i, noi = self.calc.el.get_property_lists(['o1','no'])[i] - o1j, noj = self.calc.el.get_property_lists(['o1','no'])[j] - ebs = 0.0 - for k,wk in enumerate(self.wk): - ebs += 2*wk*np.sum( self.rhoM[k,o1i:o1i+noi,o1j:o1j+noj].real ) - return (rep + epp + coul + ebs) * Hartree - - - def get_atom_and_bond_energy(self, i): - """ - Return given atom's contribution to cohesion (in eV). - - Warning: bonding & atom energy analysis less clear for - systems where orbitals overlap with own periodic images. - - parameters: - =========== - i: atom index. If None, return all atoms' energies - as an array. - """ - if i==None: - return np.array( [self.get_atom_and_bond_energy(j) for j in range(self.N)] ) - - ea = self.get_atom_energy(i) - eb = 0.0 - for j in range(self.N): - if j==i: continue - eb += 0.5 * self.get_bond_energy(i,j) - return ea + eb - - - def get_covalent_energy(self,mode='default',i=None,j=None,width=None,window=None,npts=501): - """ - Return covalent bond energies in different modes. (eV) - - ecov is described in - Bornsen, Meyer, Grotheer, Fahnle, J. Phys.:Condens. Matter 11, L287 (1999) and - Koskinen, Makinen Comput. Mat. Sci. 47, 237 (2009) - - parameters: - =========== - mode: 'default' total covalent energy - 'orbitals' covalent energy for orbital pairs - 'atoms' covalent energy for atom pairs - 'angmom' covalent energy for angular momentum components - i,j: atom or orbital indices, or angular momentum pairs - width: * energy broadening (in eV) for ecov - * if None, return energy eigenvalues and corresponding - covalent energies in arrays, directly - window: energy window (in eV wrt Fermi-level) for broadened ecov - npts: number of points in energy grid (only with broadening) - - return: - ======= - x,y: * if width==None, x is list of energy eigenvalues (including k-points) - and y covalent energies of those eigenstates - * if width!=None, x is energy grid for ecov. - * energies (both energy grid and ecov) are in eV. - - Note: energies are always shifted so that Fermi-level is at zero. - Occupations are not otherwise take into account (while k-point weights are) - """ - eps = 1E-6 - x, y = [], [] - wf = self.st.wf - energy = self.st.e - self.st.occu.get_mu() - if window==None: - mn,mx = energy.flatten().min()-eps, energy.flatten().max()+eps - else: - mn,mx = window[0]/Hartree, window[1]/Hartree - - if mode=='angmom': - lorbs = [[],[],[]] - for m,orb in enumerate(self.calc.el.orbitals()): - lorbs[orb['angmom']].append(m) - oi, oj = np.array(lorbs[i]), np.array(lorbs[j]) - elif mode=='atoms': - o1i, noi = self.calc.el.get_property_lists(['o1','no'])[i] - o1j, noj = self.calc.el.get_property_lists(['o1','no'])[j] - - for k,wk in enumerate(self.wk): - for a in range(self.norb): - if not mn<=energy[k,a]<=mx: - continue - x.append( energy[k,a] ) - if mode == 'default': - e = 0.0 - for m in range(self.norb): - e += wk*np.sum( (wf[k,a,m]*wf[k,a,:].conj()*self.HS[k,:,m]) ) - y.append(e) - elif mode == 'orbitals': - if i!=j: - y.append( wk*2*(wf[k,a,i]*wf[k,a,j].conj()*self.HS[k,j,i]).real ) - else: - y.append( wk*wf[k,a,i]*wf[k,a,j].conj()*self.HS[k,j,i]) - elif mode == 'atoms': - e = 0.0 - if i!=j: - for m in range(o1i,o1i+noi): - for n in range(o1j,o1j+noj): - e += wk*2*(wf[k,a,m]*wf[k,a,n].conj()*self.HS[k,n,m]).real - else: - for m in range(o1i,o1i+noi): - for n in range(o1j,o1j+noj): - e += wk*(wf[k,a,m]*wf[k,a,n].conj()*self.HS[k,n,m]) - y.append(e) - elif mode == 'angmom': - e = 0.0 - for m in lorbs[i]: - e += wk*np.sum( wf[k,a,m]*wf[k,a,oj].conj()*self.HS[k,oj,m] ) - if i!=j: - e += e.conj() - y.append(e) - else: - raise NotImplementedError('Unknown covalent energy mode "%s".' %mode) - - x,y = np.array(x), np.array(y) - assert np.all( abs(y.imag)<1E-12 ) - y=y.real - if width==None: - return x * Hartree, y * Hartree - else: - e,ecov = mix.broaden(x, y, width=width/Hartree, N=npts, a=mn, b=mx) - return e * Hartree, ecov * Hartree - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/wavefunctions.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/wavefunctions.py deleted file mode 100644 index cbee757..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/analysis/wavefunctions.py +++ /dev/null @@ -1,613 +0,0 @@ -import box -import numpy as np -import math -import os, pickle -from box import mix -import time -from ase import * -from box.broaden import * -from box.mix import phival -acos=math.acos -cos=math.cos -sin=math.sin -atan=math.atan -sqrt=math.sqrt -pi=math.pi -exp=np.exp - - - - -def to_spherical_coordinates(vec): - """ Transforms the given cartesien vector to spherical - coordinates. """ - x, y, z = vec - r = float(np.linalg.norm(vec)) - if r < 1e-6: - r = 0.0 - theta = 0.0 - phi = 0.0 - else: - theta = float(acos(z/r)) - phi = float(phival(x,y)) - assert 0 <= theta <= np.pi - assert 0 <= phi <= 2*np.pi - return (r, theta, phi) - - -def factorial(n): - if n == 0: - return 1 - else: - return n*factorial(n-1) - - -def Ylm(l, m): - """ Return the spherical harmonic function. """ - if l == 0: - if m == 0: - def ret((theta, phi)): - return 0.5*sqrt(1/np.pi) - if l == 1: - if m == -1: - def ret((theta, phi)): - return 0.5*sqrt(3./(2*pi))*exp(-1j*phi)*sin(theta) - if m == 0: - def ret((theta, phi)): - return 0.5*sqrt(3/pi)*cos(theta) - if m == 1: - def ret((theta, phi)): - return -0.5*sqrt(3./(2*pi))*exp(1j*phi)*sin(theta) - if l == 2: - if m == -2: - def ret((theta, phi)): - return 0.25*sqrt(15/(2*pi))*exp(-2j*phi)*sin(theta)**2 - if m == -1: - def ret((theta, phi)): - return 0.5*sqrt(15/(2*pi))*exp(-1j*phi)*sin(theta)*cos(theta) - if m == 0: - def ret((theta, phi)): - return 0.25*sqrt(5/pi)*(3*cos(theta)**2 - 1) - if m == 1: - def ret((theta, phi)): - return -0.5*sqrt(15/(2*pi))*exp(1j*phi)*sin(theta)*cos(theta) - if m == 2: - def ret((theta, phi)): - return 0.25*sqrt(15/(2*pi))*exp(2j*phi)*sin(theta)**2 - if l == 3: - if m == -3: - def ret((theta, phi)): - return 0.125*sqrt(35/pi)*exp(-3j*phi)*sin(theta)**3 - if m == -2: - def ret((theta, phi)): - return 0.25*sqrt(105/(2*pi))*exp(-2j*phi)*sin(theta)**2 * cos(theta) - if m == -1: - def ret((theta, phi)): - return 0.125*sqrt(21/pi)*exp(-1j*phi)*sin(theta)*(5*cos(theta)**2 - 1) - if m == 0: - def ret((theta, phi)): - return 0.25*sqrt(7/pi)*(5*cos(theta)**3 - 3*cos(theta)) - if m == 1: - def ret((theta, phi)): - return -0.125*sqrt(21/pi)*exp(1j*phi)*sin(theta)*(5*cos(theta)**2 - 1) - if m == 2: - def ret((theta, phi)): - return 0.25*sqrt(105/(2*pi))*exp(2j*phi)*sin(theta)**2 * cos(theta) - if m == 3: - def ret((theta, phi)): - return -0.125*sqrt(35/pi)*exp(3j*phi)*sin(theta)**3 - if l == 4: - if abs(m) == 4: - def ret((theta, phi)): - return (3./16)*sqrt(35/(2*pi))*exp(m*1j*phi)*sin(theta)**4 - if abs(m) == 3: - def ret((theta, phi)): - return np.sign(-m)*(3./8)*sqrt(35/pi)*exp(m*1j*phi)*sin(theta)**3 * cos(theta) - if abs(m) == 2: - def ret((theta, phi)): - return (3./8)*sqrt(5/(2*pi))*exp(m*1j*phi)*sin(theta)**2 * (7*cos(theta)**2 - 1) - if abs(m) == 1: - def ret((theta, phi)): - return np.sign(-m)*(3./8)*sqrt(5/pi)*exp(m*1j*phi)*sin(theta)*(7*cos(theta)**3 - 3*cos(theta)) - if m == 0: - def ret((theta, phi)): - return (3./16)*sqrt(1/pi)*(35*cos(theta)**4 - 30*cos(theta)**2 + 3) - - if l == 5: - if abs(m) == 5: - def ret((theta, phi)): - return np.sign(-m)*(3./32)*sqrt(77/pi)*exp(m*1j*phi)*sin(theta)**5 - if abs(m) == 4: - def ret((theta, phi)): - return (3./16)*sqrt(385/(2*pi))*exp(m*1j*phi)*sin(theta)**4 * cos(theta) - if abs(m) == 3: - def ret((theta, phi)): - return np.sign(-m)*(1./32)*sqrt(385/pi)*exp(m*1j*phi)*sin(theta)**3 * (9*cos(theta)**2 - 1) - if abs(m) == 2: - def ret((theta, phi)): - return 0.125*sqrt(1155/(2*pi))*exp(m*1j*phi)*sin(theta)**2 * (3*cos(theta)**3 - cos(theta)) - if abs(m) == 1: - def ret((theta, phi)): - return np.sign(-m)*(1./16)*sqrt(165/(2*pi))*exp(m*1j*phi)*sin(theta) * (21*cos(theta)**4 - 14*cos(theta)**2 + 1) - if m == 0: - def ret((theta, phi)): - return (1./16)*sqrt(11/pi) * (63*cos(theta)**5 - 70*cos(theta)**3 + 15*cos(theta)) - if l == 6: - if abs(m) == 6: - def ret((theta, phi)): - return (1./64)*sqrt(3003/pi)*exp(m*1j*phi)*sin(theta)**6 - if abs(m) == 5: - def ret((theta, phi)): - return np.sign(-m)*(3./32)*sqrt(1001/pi)*exp(m*1j*phi)*sin(theta)**5 * cos(theta) - if abs(m) == 4: - def ret((theta, phi)): - return (3./32)*sqrt(91/(2*pi))*exp(m*1j*phi)*sin(theta)**4 * (11*cos(theta)**2 - 1) - if abs(m) == 3: - def ret((theta, phi)): - return np.sign(-m)*(1./32)*sqrt(1365/pi)*exp(m*1j*phi)*sin(theta)**3 * (11*cos(theta)**3 - 3*cos(theta)) - if abs(m) == 2: - def ret((theta, phi)): - return (1./64)*sqrt(1365/pi)*exp(m*1j*phi)*sin(theta)**2 * (33*cos(theta)**4 - 18*cos(theta)**2 + 1) - if abs(m) == 1: - def ret((theta, phi)): - return np.sign(-m)*(1./16)*sqrt(273/(2*pi))*exp(m*1j*phi)*sin(theta) * (33*cos(theta)**5 - 30*cos(theta)**3 + 5*cos(theta)) - if m == 0: - def ret((theta, phi)): - return (1./32)*sqrt(13/pi)*(231*cos(theta)**6 - 315*cos(theta)**4 + 105*cos(theta)**2 - 5) - return ret - - -states=['s','px','py','pz','dxy','dyz','dzx','dx2-y2','d3z2-r2'] -def angular(r,wf): - """ Return angular part of wave function. - - The real combinations of Y_lm's - - parameters: - ----------- - r: (not normalized) position vector - wf: index or symbol for state (look below) - """ - R=sqrt(sum(r**2)) - if R<1E-14: - return 0.0 - theta=acos(r[2]/R) - phi=phival(r[0],r[1]) - - if type(wf)!=type(1): - wf=states.index(wf) - - if wf==0: return 1/sqrt(4*pi) - elif wf==1: return sqrt(3/(4*pi))*sin(theta)*cos(phi) - elif wf==2: return sqrt(3/(4*pi))*sin(theta)*sin(phi) - elif wf==3: return sqrt(3/(4*pi))*cos(theta) - elif wf==4: return sqrt(15/(4*pi))*sin(theta)**2*cos(phi)*sin(phi) - elif wf==5: return sqrt(15/(4*pi))*sin(theta)*cos(theta)*sin(phi) - elif wf==6: return sqrt(15/(4*pi))*sin(theta)*cos(theta)*cos(phi) - elif wf==7: return 0.5*sqrt(15/(4*pi))*sin(theta)**2*cos(2*phi) - elif wf==8: return 0.5*sqrt(5/(4*pi))*(3*cos(theta)**2-1) - - - - - # def write_vtk(self,i,fname=None): ---------------------------------------- - # """ Write .vtk file of wave function with *index* i. """ ------------- - # wf=self.st.wf[i,:].copy() -------------------------------------------- - # orbs=self.el.orbitals() ---------------------------------------------- - # wfg=np.zeros(self.N) ------------------------------------------------- - # grid=[] -------------------------------------------------------------- - # for i in range(3): --------------------------------------------------- - # grid.append( np.linspace(0,self.L[i],self.N[i]) ) ---------------- - # for orb,c in zip(orbs,wf): ------------------------------------------- - # symb, orbtype, Rnl=orb['symbol'], orb['orbital'], orb['Rnl'] ----- - # for i,x in enumerate(grid[0]): ----------------------------------- - # for j,y in enumerate(grid[1]): ------------------------------- - # for k,z in enumerate(grid[2]): --------------------------- - # r0=np.array([x,y,z]) --------------------------------- - # r=self.el.vector(orb['atom'],rj=r0) ------------------ - # wfg[i,j,k]+=c*Rnl(mix.norm(r))*angular(r,orbtype) ---- - # box.vtk.rectilinear_vtk(grid,wfg,fname) ------------------------------ - - -class JelliumAnalysis: - - - def __init__(self, atoms, origin=None, maxl=3, R_0=3, a=0.2, file='ylm_expansion.hb'): - """ - A class to analyse the wave functions of the system by projecting - them onto the spherical harmonics. - - atoms: The ase atoms object with a ground state calculated - of the expansion data file calculated before. - origin: The center of the expansion (Ang). If None, the center of - the mass will be used. - maxl: The largest angular momentum the expansion is performed. - R_0: The radius of the expansion (Ang) - a: The approximate length of the side of cubic grid box (Ang) - N: Number of grid points in expansion sphere in one dimension - (the total number is then N^3). - file: The filename where the ylm-expansion data is saved. - """ - # values that are saved/loaded - self.data = ['R_0', - 'origin', - 'N', - 'a', - 'dV', - 'grid_points', - 'maxl', - 'l_array', - 'e', - 'occ', - 'fermi_level', - 'finished', - 'c_nl', - 'weights', - 'dim', - 'norb', - 'analyzed_states', - 'needed_orbitals', - 'norb_needed', - 'file', - 'letters'] - self.letters = "spdfghi"[0:maxl+1] - self.loaded = False - if os.path.isfile(file): - self.load(file) - else: - atoms.get_potential_energy() - calc = atoms.get_calculator() - self.R_0 = R_0 / Bohr - self.finished = False - if origin == None: - self.origin = calc.el.get_center_of_mass() - else: - self.origin = np.array(origin)/Bohr - self.create_uniform_cubic_grid(a) - self.maxl = maxl - self.l_array = range(min(7, maxl+1)) - self.norb = calc.st.norb - self.fermi_level = calc.st.occu.get_mu() - self.e = calc.st.get_eigenvalues() - self.occ = calc.st.get_occupations() - self.file = file - self.c_nl = np.zeros((self.norb, len(self.l_array))) - self.weights = np.zeros(self.norb) - self.analyzed_states = np.zeros(self.norb, dtype=bool) - - self.atoms = atoms - self.calc = atoms.get_calculator() - - self.basis_functions = {} - - self.mark_grids() - self.mark_needed_basis_functions() - - self.log = open('jellium_analysis.log','a') - self.greetings() - - - def load(self, file): - """ Load expansion data to file. """ - f = open(file) - while True: - try: - name, data = pickle.load(f) - self.__dict__[name] = data - except EOFError: - break - self.loaded = True - f.close() - - - def write(self): - """ Write expansion data to file. """ - f = open(self.file, 'w') - for name in self.data: - pickle.dump([name, self.__dict__[name]], f) - f.close() - - - def create_uniform_cubic_grid(self, a): - """ - Creates a grid of N x N x N cubes. The grid is built so that - the origin of the expansion is between the grid points. - """ - a = a / Bohr # the requested grid spacing - self.N = np.ceil(2*self.R_0 / a) - # we want an odd number of grid points per side, so that the - # center of the expansion is one grid point. - if self.N % 2 == 0: - self.N += 1 - self.a = 2*self.R_0/self.N # the actual grid spacing - assert abs(self.N*self.a - 2*self.R_0) < 1e-3 - self.dV = self.a**3 - self.grid_points = [] - for d in range(3): - R = self.origin[d] - g = np.linspace(R - self.R_0 + self.a/2, R + self.R_0 - self.a/2, self.N) - self.grid_points.append(g) - self.dim = np.array([len(axis) for axis in self.grid_points]) - - - def estimate_memory_consumption(self, human_readable=False): - """ Give an approximation on how much the arrays need memory. """ - # grid points for one state - N = np.prod(self.dim) - mem = 0.0 - # the spherical harmonics - mem += (self.maxl+1)**2 * np.array([1], np.complex).itemsize * N - # the basis functions - mem += self.norb_needed * np.array([1], np.float).itemsize * N - # working arrays - mem += 4 * np.array([1], np.float).itemsize * N - f = 'byte' - if mem / 1024.0 > 1.0: - memm = mem / 1024.0 - f = 'kb' - if memm / 1024.0 > 1.0: - memm = memm / 1024.0 - f = 'Mb' - if memm / 1024.0 > 1.0: - memm = memm / 1024.0 - f = 'Gb' - if human_readable: - return "%0.3f %s" % (memm, f) - else: - return mem - - - def mark_grids(self): - """ Create a grid that contains indices that tell to which - shell the grid belongs to. - Index = 0: outside the expansion shell - Index >= 1: the index of the shell (1 is the most inner one) - The thickness of the shells is a. """ - self.shell_index_grid = np.zeros(self.dim, dtype=int) - self.shells = {} - for i, x in enumerate(self.grid_points[0]): - for j, y in enumerate(self.grid_points[1]): - for k, z in enumerate(self.grid_points[2]): - vec = np.array((x,y,z)) - self.origin - norm = np.linalg.norm(vec) - if norm <= self.R_0: - index = int(round(norm/self.a)) + 1 - if index in self.shells: - self.shells[index] += 1 - else: - self.shells[index] = 1 - self.shell_index_grid[i,j,k] = index - - - def mark_needed_basis_functions(self): - """ Chech which basis functions are needed in order to calculate - the wave functions inside the expansion sphere. """ - self.needed_orbitals = np.zeros(self.norb ,dtype=bool) - positions = self.calc.el.get_positions() - orbitals = self.calc.el.orbitals() - for m in range(self.norb): - orbital = orbitals[m] - atom = orbital['atom'] - orbital_type = orbital['orbital'] - symbol = orbital['symbol'] - wf_range = self.calc.el.elements[symbol].get_wf_range(orbital_type) - if wf_range == None: - raise Exception('No radial function %s found for %s (maybe the element file does not contain it?).' % (orbital_type, symbol)) - R = positions[atom] - if np.linalg.norm(R - self.origin) < self.R_0 + wf_range: - self.needed_orbitals[m] = True - self.norb_needed = np.sum(np.where(self.needed_orbitals, 1, 0)) - - - def ylms_to_grid(self): - """ Calculates the values of spherical harmonics centered - to the origin of the expansion to the grid. """ - self.ylms = {} - origin = self.origin - for l in self.l_array: - for m in range(-l,l+1): - y_lm = Ylm(l, m) - t1 = time.time() - print >> self.log, "Calculating Y_(l=%i, m=%s) to grid..." % (l, repr(m).rjust(2)) - self.log.flush() - values = np.zeros(self.dim, dtype=np.complex) - for i, x in enumerate(self.grid_points[0]): - for j, y in enumerate(self.grid_points[1]): - for k, z in enumerate(self.grid_points[2]): - r, theta, phi = to_spherical_coordinates(np.array((x,y,z))-self.origin) - values[i,j,k] = y_lm((theta, phi)) - print >> self.log, " in %i seconds." % (time.time() - t1) - self.ylms[l,m] = values - - - def basis_functions_to_grid(self): - """ Calculate the basis functions into the grid. """ - for m in range(self.norb): - orbital = self.calc.el.orbitals()[m] - atom = orbital['atom'] - R = self.calc.el.get_positions()[atom] - orbital_type = orbital['orbital'] - if self.needed_orbitals[m] == False: - print >> self.log, "Basis function %i/%i is outside the range." % (orbital['index']+1, self.norb) - self.basis_functions[m] = None - else: - t1 = time.time() - print >> self.log, "Calculating basis function %i/%i to grid..." % (orbital['index']+1, self.norb) - self.log.flush() - r_nl = orbital['Rnl'] - basis_function = np.zeros(self.dim, dtype=np.float) - for i, x in enumerate(self.grid_points[0]): - for j, y in enumerate(self.grid_points[1]): - for k, z in enumerate(self.grid_points[2]): - vec = np.array((x,y,z))-np.array(R) - r, theta, phi = to_spherical_coordinates(vec) - basis_function[i,j,k] = r_nl(r)*angular(vec, orbital_type) - print >> self.log, " in %i seconds." % (time.time() - t1) - self.basis_functions[m] = basis_function - - - def get_ylm(self, l, m): - """ Return spherical harmonic Y_lm on grid. """ - return self.ylms[l,m] - - - def get_basis_function(self, m): - """ Return m:th basis function on grid. """ - return self.basis_functions[m] - - - def get_state(self, k): - """ Return the k:th wave function inside the expansion grid. """ - wf_coeffs = self.calc.st.wf[0,k,:] - assert np.sum(wf_coeffs.imag < 1e-3) - wf_coeffs = wf_coeffs.real - state_grid = np.zeros(self.dim, dtype=np.float) - for wf_coef, orb in zip(wf_coeffs, self.calc.el.orbitals()): - basis_function = self.get_basis_function(orb['index']) - if basis_function != None: - state_grid += wf_coef * basis_function - return state_grid - - - def analyse_states(self): - """ Perform the angular momentum analysis on all states. """ - for n in range(self.norb): - if self.analyzed_states[n] == False: - print >> self.log, "Analysing state no. %i (%i/%i)..." % (n, n+1, self.norb) - self.log.flush() - t1 = time.time() - state_grid = self.get_state(n) - state_grid_squared = state_grid.conjugate() * state_grid - self.weights[n] = np.sum(state_grid_squared * np.where(self.shell_index_grid != 0, 1, 0)) * self.dV - for l in self.l_array: - self.c_nl[n,l] = self.weights[n] * self.analyse_state(state_grid, l) - print >> self.log, " %i seconds." % (time.time() - t1) - self.analyzed_states[n] = True - self.write() - self.finished = True - for n in range(self.norb): - if float(np.sum(self.c_nl[n,:])) > 0.01: - self.c_nl[n,:] = self.c_nl[n,:]/float(np.sum(self.c_nl[n,:])) - self.log.flush() - self.write_readable('ja.dat') - - - def analyse_state(self, state_grid, l): - """ Performs the angular momentum analysis with respect to - angular momentum l to the state n. """ - c = 0.0 - for m in range(-l,l+1): - ylm = self.get_ylm(l, m) - # The integration - for i in self.shells.keys(): - # the mask that gives the grid points of the shell - shell_grid = np.where(self.shell_index_grid == i, 1, 0) - # the number of boxes in the i:th shell - N_shell = self.shells[i] - # the integration over the solid angle - phi_nlm = np.sum(shell_grid * ylm.conjugate() * state_grid) - c += phi_nlm.conjugate() * phi_nlm * 4*pi*self.dV / N_shell - return c - - - def greetings(self): - print >> self.log, "\n*** Starting the angular momentum analysis. ***" - if self.loaded: - print >> self.log, "Using data from %s" % self.file - print >> self.log, "The grid contains %i x %i x %i grid points" % tuple(self.dim) - print >> self.log, "The grid spacing is %0.3f (Ang)" % (self.a*Bohr) - print >> self.log, "The center of the expansion (Ang): %0.2f, %0.2f, %0.2f" % tuple(self.origin * Bohr) - print >> self.log, "The radius of the expansion: %0.2f (ang)" % (self.R_0 * Bohr) - print >> self.log, "The analysis is performed on angular momenta:", - for l in self.l_array: - print >> self.log, self.letters[l], - print >> self.log, "" - print >> self.log, "There are %i basis functions, %i are needed." % (self.norb, self.norb_needed) - print >> self.log, "There are %i/%i states left to analyze." % (np.sum(np.where(self.analyzed_states, 0, 1)), self.norb) - if self.finished == False: - print >> self.log, "Estimated amount of memory required: %s" % (self.estimate_memory_consumption(human_readable=True)) - print >> self.log, "" - self.log.flush() - - - def write_readable(self, file): - """ Write the spherical harmonic expansion coefficients to file. """ - f = open(file, 'w') - print >> f, "# The center of the expansion (in Ang): %0.2f, %0.2f, %0.2f" % tuple(self.origin * Bohr) - print >> f, "# The radius of the expansion (in Ang): %0.2f" % (self.R_0 * Bohr) - print >> f, "# The shell thickness (in Ang): %0.2f" % (self.a * Bohr) - print >> f, "#state energy(eV) weight occ", - for l in self.l_array: - print >> f, "%6s" % self.letters[l], - print >> f, "" - for n in range(self.norb): - print >> f, "%5i %12.4f %7.4f %7.4f" % (n, self.e[0,n]*Hartree, self.weights[n], self.occ[0,n]), - for l in self.l_array: - print >> f, "%6.3f" % self.c_nl[n,l], - print >> f, "" - f.close() - - - def run(self): - if self.finished == False: - self.atoms.get_potential_energy() - self.ylms_to_grid() - self.basis_functions_to_grid() - self.analyse_states() - self.write() - - -def make_plot(file, width=0.1, xlimits=None, ylimits=None, out=None): - """ Make a cumulative plot from the angular momentum analysis - of the electron states. - - file: data file produced by the Jellium analysis object - width: the FWHM of the gaussians used to broaden the energies - xlimits: the limits of the x-axis [xmin, xmax] - ylimits: the limits of the y-axis [ymin, ymax] - out: the output file (None=screen) - - """ - import pylab - f = open(file) - data = {} - while True: - try: - name, dat = pickle.load(f) - data[name] = dat - except EOFError: - break - print "" - print "" - print "*** Spherical harmonics analysis ***" - print "center:", data["origin"] * Bohr, "Ang" - print "radius:", data["R_0"] * Bohr, "Ang" - print "grid box size (shell thickness):", data["a"] * Bohr, "Ang" - print "analysis performed on angular momenta:", data["letters"].replace("",",")[1:-1] - print "Fermi level (subtracted):", data["fermi_level"] * Hartree, "eV" - - pylab.figure() - colors = ['#FFFF00','#FF0000','#2758D3','#5FD300', - '#058C00','#E1AB18','#50E1D0'] - - weights = data["c_nl"].transpose() - e = (data["e"][0] - data["fermi_level"]) * Hartree - if xlimits == None: - e_min, e_max = min(e), max(e) - empty = 0.1*(e_max - e_min) - else: - e_min, e_max = xlimits - empty = 0.0 - x_grid = np.linspace(e_min-empty, e_max+empty, 2000) - make_cumulative_plot(x_grid, e, width, weights, - labels=data["letters"], colors=colors) - pylab.xlabel("Energy (eV)") - pylab.ylabel("Arbitrary units") - pylab.title("Angular momentum analysis") - pylab.legend() - pylab.ylim(ylimits) - if out == None: - pylab.show() - else: - pylab.savefig(out) - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/aseinterface.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/aseinterface.py deleted file mode 100644 index d2f155c..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/aseinterface.py +++ /dev/null @@ -1,1228 +0,0 @@ -# Copyright (C) 2008 NSC Jyvaskyla -# Please see the accompanying LICENSE file for further information. - -""" - ASE-calculator interface for HOTBIT. - (Hybrid Open-source Tight-Binding Tool) - -""" -import os -import glob -import sys -import numpy as np -from auxil import k_to_kappa_points -from ase.units import Bohr, Hartree -from ase import Atoms -from box.timing import Timer -from elements import Elements -from interactions import Interactions -from environment import Environment -from pairpotential import PairPotential -from repulsion import Repulsion -from states import States -from grids import Grids -from hotbit.version import hotbit_version -from hotbit.analysis import MullikenAnalysis -from hotbit.analysis import MullikenBondAnalysis -from hotbit.analysis import DensityOfStates -from hotbit.output import Output -from hotbit.vdw import setup_vdw -from box.mix import broaden -import box.mix as mix -from time import time -hbar=0.02342178268 - - -class Hotbit(Output): - def __init__(self,parameters=None, - elements=None, - tables=None, - verbose=False, - charge=0.0, - SCC=True, - kpts=(1,1,1), - rs='kappa', - physical_k=True, - maxiter=50, - gamma_cut=None, - txt=None, - verbose_SCC=False, - width=0.02, - mixer=None, - coulomb_solver=None, - charge_density='Gaussian', - vdw=False, - vdw_parameters=None, - sepsilon=0.0, - filename=None): - """ - Hotbit -- density-functional tight-binding calculator - for atomic simulation environment (ASE). - - - - Parameters: - ----------- - parameters: The directory for parametrization files. - * If parameters==None, use HOTBIT_PARAMETERS environment variable. - * Parametrizations given by 'elements' and 'tables' keywords - override parametrizations in this directory. - - elements: Files for element data (*.elm). - example: {'H':'H_custom.elm','C':'/../C.elm'} - * If extension '.elm' is omitted, it is assumed. - * Items can also be elements directly: {'H':H} (H is type Element) - * If elements==None, use element info from default directory. - * If elements['rest']=='default', use default parameters for all other - elements than the ones specified. E.g. {'H':'H.elm','rest':'default'} - (otherwise all elements present have to be specified explicitly). - - tables: Files for Slater-Koster tables. - example: {'CH':'C_H.par','CC':'C_C.par'} - * If extension '.par' is omitted, it is assumed. - * If tables==None, use default interactions. - * If tables['rest']='default', use default parameters for all other - interactions, e.g. {'CH':'C_H.par','rest':'default'} - * If tables['AB']==None, ignore interactions for A and B - (both chemical and repulsive) - - mixer: Density mixer. - example: {'name':'Anderson','mixing_constant':0.2, 'memory':5}. - charge: Total charge for system (-1 means an additional electron) - width: Width of Fermi occupation (eV) - SCC: Self-Consistent Charge calculation - * True for SCC-DFTB, False for DFTB - kpts: Number of k-points. - * For translational symmetry points are along the directions - given by the cell vectors. - * For general symmetries, you need to look at the info - from the container used - rs: * 'kappa': use kappa-points - * 'k': use normal k-points. Only for Bravais lattices. - physical_k Use physical (realistic) k-points for generally periodic systems. - * Ignored with normal translational symmetry - * True for physically allowed k-points in periodic symmetries. - maxiter: Maximum number of self-consistent iterations - * only for SCC-DFTB - coulomb_solver: The Coulomb solver object. If None, a DirectCoulomb - object will the automatically instantiated. - * only for SCC-DFTB - charge_density: Shape of the excess charge on each atom. Possibilities - are: - * 'Gaussian': Use atom centered Gaussians. This is the - default. - * 'Slater': Slater-type exponentials as used in the - original SCC-DFTB scheme. - * only for SCC-DFTB - gamma_cut: Range for Coulomb interaction if direct summation is - selected (coulomb_solver = None). - * only for SCC-DFTB - vdw: Include van der Waals interactions - vdw_parameters: Dictionary containing the parameters for the van-der-Waals - interaction for each element. - i.e. { el: ( p, R0 ), ... } - where *el* is the element name, *p* the polarizability and - *R0* the radius where the van-der-Waals interaction starts. - Will override whatever read from .elm files. - sepsilon: Number added to the diagonal of S-matrix, if S is not positive - definite, e.g. 1E-3. The origin for the problem is physical, - and there is no perfect cure; this treatment is quick'n dirty. - txt: Filename for log-file. - * None: standard output - * '-': throw output to trash (/null) - verbose_SCC: Increase verbosity in SCC iterations. - """ - from copy import copy - import os - - if gamma_cut!=None: gamma_cut=gamma_cut/Bohr - self.__dict__={ 'parameters':parameters, - 'elements':elements, - 'tables':tables, - 'verbose':verbose, - 'charge':charge, - 'width':width/Hartree, - 'SCC':SCC, - 'kpts':kpts, - 'rs':rs, - 'physical_k':physical_k, - 'maxiter':maxiter, - 'gamma_cut':gamma_cut, - 'vdw':vdw, - 'vdw_parameters':vdw_parameters, - 'sepsilon':sepsilon, - 'txt':txt, - 'verbose_SCC':verbose_SCC, - 'mixer':mixer, - 'coulomb_solver':coulomb_solver, - 'charge_density':charge_density} - - if parameters!=None: - os.environ.data['HOTBIT_PARAMETERS']=parameters - - self.init=False - self.notes=[] - self.dry_run = '--dry-run' in sys.argv - #self.set_text(self.txt) - #self.timer=Timer('Hotbit',txt=self.get_output()) - - if filename is not None: - self.load(filename) - - def copy(self): - return self.__copy__() - - def __copy__(self): - """ - Returns an uninitialized calculator. - """ - import sys - from os.path import sameopenfile - if self.init == True: - raise NotImplementedError('Calculator has been initialized and it cannot be copied. Please create a new calculator.') - - params_to_copy = ['SCC', - 'mixer', - 'width', - 'tables', - 'charge', - 'verbose', - 'maxiter', - 'elements', - 'gamma_cut', - 'parameters', - 'txt', - 'verbose_SCC', - 'sepsilon', - 'kpts', - 'rs', - 'coulomb_solver'] - - ret = Hotbit() - # TODO: if output file already opened (unless /null or stdout) - # open a file with another name - for key in params_to_copy: - ret.__dict__[key] = self.__dict__[key] - return ret - - - def __del__(self): - """ Delete calculator -> timing summary. """ - if self.get('SCC'): - try: - print>>self.txt, self.st.solver.get_iteration_info() - self.txt.flush() - except: - pass - if len(self.notes)>0: - print>>self.txt, 'Notes and warnings:' - for note in self.notes: - print>>self.txt, note - if self.init: - self.timer.summary() - Output.__del__(self) - - - def write(self, filename='restart.hb'): - """ Write data from calculation to a file. """ - if self.init == False: - raise RuntimeError('The calculator is not initialized.') - state = {} - self.get_data_to_save(state) - import pickle - f = open(filename, 'w') - pickle.dump(state, f) - f.close() - - - def write_electronic_data(self,filename,keys=None): - """ - Write key electronic data into a file with *general* format. - - Hotbit is not needed to analyze the resulting data file. - The data will be in a dictionary with the following items: - - N the number of atoms - norb the number of orbitals - nelectrons the number of electrons - charge system charge - epot potential energy - ebs band structure energy - ecoul coulomb energy - erep repulsive energy - forces atomic forces - symbols element symbols - e single-particle energies - occ occupations - nk number of k-points - k k-point vectors - wk k-point weights - dq excess Mulliken populations - gap energy gap - gap_prob certainty of the gap determination above - dose energies for density of states (all states over k-points as well) - 0 = Fermi-level - dos density of states (including k-point weights) - - Access to data, simply: - - data = numpy.load(filename) - print data['epot'] - - parameters: - ----------- - filename: output file name - keys: list of items (key names) to save. - If None, save all. - """ - data = {} - data['N'] = self.el.N - data['norb'] = self.st.norb - data['charge'] = self.get('charge') - data['nelectrons'] = self.el.get_number_of_electrons() - data['erep'] = self.rep.get_repulsive_energy() - data['ecoul'] = self.get_coulomb_energy(self.el.atoms) - data['ebs'] = self.get_band_structure_energy(self.el.atoms) - data['epot'] = self.get_potential_energy(self.el.atoms) - data['forces'] = self.get_forces(self.el.atoms) - data['symbols'] = self.el.symbols - data['e'] = self.st.e - data['occ'] = self.st.f - data['nk'] = self.st.nk - data['k'] = self.st.k - data['wk'] = self.st.wk - data['dq'] = self.st.mulliken() - data['gap'], data['gap_prob'] = self.get_energy_gap() - data['dose'], data['dos'] = self.get_density_of_states(False) - - for key in data.keys(): - if keys!=None and key not in keys: - del data[key] - import pickle - f = open(filename, 'w') - pickle.dump(data,f) - f.close() - - - def get_data_to_save(self, state): - """ Gather data from different objects. """ - atoms = {} - atoms['positions'] = self.el.atoms.get_positions() - atoms['numbers'] = self.el.atoms.get_atomic_numbers() - atoms['pbc'] = self.el.atoms.get_pbc() - atoms['cell'] = self.el.atoms.get_cell() - state['atoms'] = atoms - - calc = {} - params = ['parameters','mixer','elements','SCC','rs', - 'maxiter','tables','gamma_cut','charge','width','sepsilon'] - for key in params: - calc[key] = self.__dict__[key] - state['calc'] = calc - - states = {} - states['prev_dq'] = self.st.prev_dq - states['count'] = self.st.count - state['states'] = states - - - - def load(self, filename): - """ Load saved state and initialize calculator using that state.""" - import pickle - f = open(filename) - state = pickle.load(f) - f.close() - - atoms = state['atoms'] - pos = atoms['positions'] - num = atoms['numbers'] - pbc = atoms['pbc'] - cell = atoms['cell'] - atoms = Atoms(positions=pos, numbers=num, pbc=pbc, cell=cell) - - calc = state['calc'] - for key in calc: - self.__dict__[key] = calc[key] - self._initialize(atoms) - - states = state['states'] - self.st.prev_dq = states['prev_dq'] - self.st.count = states['count'] - - - def set(self,key,value): - if key == 'txt': - self.set_text(value) - elif self.init==True or key not in ['charge']: - raise AssertionError('Parameters cannot be set after initialization.') - else: - self.__dict__[key]=value - - - def get_atoms(self): - """ Return the current atoms object. """ - atoms = self.el.atoms.copy() - atoms.calc = self - return atoms - - - def add_note(self,note): - """ Add warning (etc) note to be printed in log file end. """ - self.notes.append(note) - - - def greetings(self): - """ Simple greetings text """ - from time import asctime - from os import uname - from os.path import abspath, curdir - from os import environ - - self.version=hotbit_version - print>>self.txt, '\n\n\n\n\n' - print>>self.txt, ' _ _ _ _ _' - print>>self.txt, '| |__ ___ | |_ | |__ |_| |_' - print>>self.txt, '| _ \ / _ \| _|| _ \| | _|' - print>>self.txt, '| | | | ( ) | |_ | ( ) | | |_' - print>>self.txt, '|_| |_|\___/ \__|\____/|_|\__| ver.',self.version - print>>self.txt, 'Distributed under GNU GPL; see %s' %environ.get('HOTBIT_DIR')+'/LICENSE' - print>>self.txt, 'Date:',asctime() - dat=uname() - print>>self.txt, 'Nodename:',dat[1] - print>>self.txt, 'Arch:',dat[4] - print>>self.txt, 'Dir:',abspath(curdir) - print>>self.txt, 'System:',self.el.get_name() - print>>self.txt, ' Charge=%4.1f' % self.charge - print>>self.txt, ' Container', self.el.container_info() - print>>self.txt, 'Symmetry operations (if any):' - rs = self.get('rs') - kpts = self.get('kpts') - if not isinstance(kpts,tuple): - kpts = (NaN,NaN,NaN) - M = self.el.get_number_of_transformations() - for i in range(3): - print>>self.txt, ' %i: pbc=' %i, self.el.atoms.get_pbc()[i], - print>>self.txt, ', %s-points=%i, M=%.f' %(rs,kpts[i],M[i]) - print>>self.txt, 'Electronic temperature:', self.width*Hartree,'eV' - mixer = self.st.solver.mixer - print>>self.txt, 'Mixer:', mixer.get('name'), 'with memory =', mixer.get('memory'), ', mixing constant =', mixer.get('beta') - print>>self.txt, self.el.greetings() - print>>self.txt, self.ia.greetings() - print>>self.txt, self.rep.greetings() - if self.pp.exists(): - print>>self.txt, self.pp.greetings() - - - def out(self,text): - print>>self.txt, text - self.txt.flush() - - - def set_text(self,txt): - """ Set up the output file. """ - if txt=='-' or txt=='null': - self.txt = open('/dev/null','w') - elif hasattr(txt, 'write'): - self.txt = txt - elif txt is None: - from sys import stdout - self.txt=stdout - else: - self.txt=open(txt,'a') - # check if the output of timer must be changed also - if 'timer' in self.__dict__: - self.timer.txt = self.get_output() - - - def get(self,arg=None): - if arg==None: - return self.__dict__ - else: - return self.__dict__[arg] - - - def memory_estimate(self): - """ - Print an estimate for memory consumption in GB. - - If script run with --dry-run, exit. - """ - if self.st.nk>1: - number = 16. #complex - else: - number = 8. #real - M = self.st.nk*self.st.norb**2*number - # H S dH0 dS wf H1 dH rho rhoe - mem = M + M + 3*M + 3*M + M + M + 3*M + M + M - print>>self.txt, 'Memory consumption estimate: > %.2f GB' %(mem/1E9) - self.txt.flush() - if self.dry_run: - raise SystemExit - - - def solve_ground_state(self,atoms): - """ If atoms moved, solve electronic structure. """ - if not self.init: - self._initialize(atoms) - if self.calculation_required(atoms,'ground state'): - self.el.update_geometry(atoms) - t0 = time() - self.st.solve() - self.el.set_solved('ground state') - t1 = time() - self.flags['Mulliken'] = False - self.flags['DOS'] = False - self.flags['bonds'] = False - if self.verbose: - print >> self.get_output(), "Solved in %0.2f seconds" % (t1-t0) - if self.get('SCC'): - atoms.set_charges(-self.st.get_dq()) - else: - pass - - - def _initialize(self,atoms): - """ Initialization of hotbit. """ - self.init=True - self.set_text(self.txt) - self.timer=Timer('Hotbit',txt=self.get_output()) - self.start_timing('initialization') - self.el=Elements(self,atoms) - self.ia=Interactions(self) - self.st=States(self) - self.rep=Repulsion(self) - self.pp=PairPotential(self) - if self.get('vdw'): - if self.get('vdw_parameters') is not None: - self.el.update_vdw(self.get('vdw_parameters')) - setup_vdw(self) - self.env=Environment(self) - pbc=atoms.get_pbc() - # FIXME: gamma_cut -stuff - #if self.get('SCC') and np.any(pbc) and self.get('gamma_cut')==None: - # raise NotImplementedError('SCC not implemented for periodic systems yet (see parameter gamma_cut).') - if np.any(pbc) and abs(self.get('charge'))>0.0: - raise AssertionError('Charged system cannot be periodic.') - self.flush() - self.el.set_atoms(atoms) - self.greetings() - self.flags = {} - self.flags['Mulliken'] = False - self.flags['DOS'] = False - self.flags['bonds'] = False - self.flags['grid'] = False - self.stop_timing('initialization') - - - def calculation_required(self,atoms,quantities): - """ Check if a calculation is required. - - Check if the quantities in the quantities list have already been calculated - for the atomic configuration atoms. The quantities can be one or more of: - 'ground state', 'energy', 'forces', 'magmoms', and 'stress'. - """ - return self.el.calculation_required(atoms,quantities) - - - def get_potential_energy(self,atoms): - """ Return the potential energy of present system. """ - if self.calculation_required(atoms,['energy']): - self.solve_ground_state(atoms) - self.start_timing('energy') - ebs=self.get_band_structure_energy(atoms) - ecoul=self.get_coulomb_energy(atoms) - erep=self.rep.get_repulsive_energy() - epp=self.pp.get_energy() - self.epot = ebs + ecoul + erep + epp - self.el.efree*Hartree - self.stop_timing('energy') - self.el.set_solved('energy') - return self.epot.copy() - - - def get_forces(self,atoms): - """ - Return forces (in eV/Angstrom) - - Ftot = F(band structure) + F(coulomb) + F(repulsion). - """ - if self.calculation_required(atoms,['forces']): - self.solve_ground_state(atoms) - self.start_timing('forces') - fbs=self.st.get_band_structure_forces() - frep=self.rep.get_repulsive_forces() - fcoul=self.st.es.gamma_forces() #zero for non-SCC - fpp = self.pp.get_forces() - self.stop_timing('forces') - self.f = (fbs+frep+fcoul+fpp)*(Hartree/Bohr) - self.el.set_solved('forces') - return self.f.copy() - - - def get_band_energies(self, kpts=None, shift=True, rs='kappa'): - ''' - Return band energies for explicitly given list of k-points. - - parameters: - =========== - kpts: list of k-points; e.g. kpts=[(0,0,0),(pi/2,0,0),(pi,0,0)] - k- or kappa-points, depending on parameter rs. - if None, return for all k-points in the calculation - shift: shift zero to the Fermi-level - rs: use 'kappa'- or 'k'-points in reciprocal space - ''' - if kpts==None: - e = self.st.e * Hartree - else: - if rs=='k': - klist = k_to_kappa_points(kpts,self.el.atoms) - elif rs=='kappa': - klist = kpts - e = self.st.get_band_energies(klist)*Hartree - - if shift: - return e-self.get_fermi_level() - else: - return e - - - def get_stress(self,atoms): - self.solve_ground_state(atoms) - return None - - - def get_charge(self): - """ Return system's total charge. """ - return self.get('charge') - - - def get_eigenvalues(self): - """ Return eigenvalues without shifts. - - For alternative, look at method get_band_energies. - """ - return self.st.get_eigenvalues()*Hartree - - - def get_energy_gap(self): - """ - Return the energy gap. (in eV) - - Gap is the energy difference between the first states - above and below Fermi-level. Return also the probability - of having returned the gap; it is the difference - in the occupations of these states, divided by 2. - """ - eigs = (self.get_eigenvalues() - self.get_fermi_level()).flatten() - occ = self.get_occupations().flatten() - ehi, elo=1E10,-1E10 - for e,f in zip(eigs,occ): - if elo0.0).argmax(),(self.st.nk,self.st.norb)) - if state=='LUMO': - k,a = np.unravel_index(np.ma.masked_array(eigs,eigs<0.0).argmin(),(self.st.nk,self.st.norb)) - return k,a - - - def get_occupations(self): - #self.solve_ground_state(atoms) - return self.st.get_occupations() - - - def get_band_structure_energy(self,atoms): - if self.calculation_required(atoms, ['ebs']): - self.solve_ground_state(atoms) - self.ebs = self.st.get_band_structure_energy()*Hartree - self.el.set_solved('ebs') - return self.ebs - - - def get_coulomb_energy(self,atoms): - if self.calculation_required(atoms,['ecoul']): - self.solve_ground_state(atoms) - self.ecoul = self.st.es.coulomb_energy()*Hartree - self.st - return self.ecoul - - - # some not implemented ASE-assumed methods - def get_fermi_level(self): - """ - Return the Fermi-energy (chemical potential) in eV. - """ - return self.st.occu.get_mu() * Hartree - - - def set_atoms(self,atoms): - """ Initialize the calculator for given atomic system. """ - if self.init==True and atoms.get_chemical_symbols()!=self.el.atoms.get_chemical_symbols(): - raise RuntimeError('Calculator initialized for %s. Create new calculator for %s.' - %(self.el.get_name(),mix.parse_name_for_atoms(atoms))) - else: - self._initialize(atoms) - - - def get_occupation_numbers(self,kpt=0): - """ Return occupation numbers for given k-point index. """ - return self.st.f[kpt].copy() - - - def get_number_of_bands(self): - """ Return the total number of orbitals. """ - return self.st.norb - - - def start_timing(self, label): - self.timer.start(label) - - - def stop_timing(self, label): - self.timer.stop(label) - - - # - # various analysis methods - # - def get_dielectric_function(self,width=0.05,cutoff=None,N=400): - """ - Return the imaginary part of the dielectric function for non-SCC. - - Note: Uses approximation that requires that the orientation of - neighboring unit cells does not change much. - (Exact for Bravais lattice.) - - See, e.g., Marder, Condensed Matter Physics, or - Popov New J. Phys 6, 17 (2004) - - parameters: - ----------- - width: energy broadening in eV - cutoff: cutoff energy in eV - N: number of points in energy grid - - return: - ------- - e[:], d[:,0:2] - """ - self.start_timing('dielectric function') - width = width/Hartree - otol = 0.05 # tolerance for occupations - if cutoff==None: - cutoff = 1E10 - else: - cutoff = cutoff/Hartree - - st = self.st - nk, e, f, wk = st.nk, st.e, st.f, st.wk - ex, wt = [], [] - for k in range(nk): - wf = st.wf[k] - wfc = wf.conjugate() - dS = st.dS[k].transpose((0,2,1)) - ek = e[k] - fk = f[k] - kweight = wk[k] - # electron excitation ka-->kb; restrict the search: - bmin = list(fk<2-otol).index(True) - amin = list(ek>ek[bmin]-cutoff).index(True) - amax = list(fkek[a]+cutoff).index(True) - for b in range(max(a+1,bmin),bmax+1): - de = ek[b]-ek[a] - df = fk[a]-fk[b] - if df - P = 1j*hbar*np.dot(wfc[a],np.dot(dS,wf[b])) - ex.append( de ) - wt.append( kweight*df*np.abs(P)**2 ) - - ex, wt = np.array(ex), np.array(wt) - cutoff = min( ex.max(),cutoff ) - y = np.zeros((N,3)) - for d in range(3): - # Lorenzian should be used, but long tail would bring divergence at zero energy - x,y[:,d] = broaden( ex,wt[:,d],width,'gaussian',N=N,a=width,b=cutoff ) - y[:,d] = y[:,d]/x**2 - const = (4*np.pi**2/hbar) - self.stop_timing('dielectric function') - return x*Hartree, y*const #y also in eV, Ang - - # - # grid stuff - # - def set_grid(self,h=0.2,cutoff=3.0): - if self.calculation_required(self.el.atoms,['energy']): - raise AssertionError('Electronic structure is not solved yet!') - if self.flags['grid']==False: - self.gd = Grids(self,h,cutoff) - self.flags['grid']=True - - - def get_grid_basis_orbital(self,I,otype,k=0,pad=True): - """ - Return basis orbital on grid. - - parameters: - =========== - I: atom index - otype: orbital type ('s','px','py',...) - k: k-point index (basis functions are really the extended - Bloch functions for periodic systems) - pad: padded edges in the array - """ - if self.flags['grid']==False: - raise AssertionError('Grid needs to be set first by method "set_grid".') - return self.gd.get_grid_basis_orbital(I,otype,k,pad) - - - def get_grid_wf(self,a,k=0,pad=True): - """ - Return eigenfunction on a grid. - - parameters: - =========== - a: state (band) index - k: k-vector index - pad: padded edges - """ - if self.flags['grid']==False: - raise AssertionError('Grid needs to be set first by method "set_grid".') - return self.gd.get_grid_wf(a,k,pad) - - - def get_grid_wf_density(self,a,k=0,pad=True): - """ - Return eigenfunction density. - - Density is not normalized; accurate quantitative analysis - on this density are best avoided. - - parameters: - =========== - a: state (band) index - k: k-vector index - pad: padded edges - """ - if self.flags['grid']==False: - raise AssertionError('Grid needs to be set first by method "set_grid".') - return self.gd.get_grid_wf_density(a,k,pad) - - - def get_grid_density(self,pad=True): - """ - Return electron density on grid. - - Do not perform accurate analysis on this density. - Integrated density differs from the total number of electrons. - Bader analysis inaccurate. - - parameters: - pad: padded edges - """ - if self.flags['grid']==False: - raise AssertionError('Grid needs to be set first by method "set_grid".') - return self.gd.get_grid_density(pad) - - - def get_grid_LDOS(self,bias=None,window=None,pad=True): - """ - Return electron density over selected states around the Fermi-level. - - parameters: - ----------- - bias: bias voltage (eV) with respect to Fermi-level. - Negative means probing occupied states. - window: 2-tuple for lower and upper bounds wrt. Fermi-level - pad: padded edges - """ - if self.flags['grid']==False: - raise AssertionError('Grid needs to be set first by method "set_grid".') - return self.gd.get_grid_LDOS(bias,window,pad) - - - # - # Mulliken population analysis tools - # - def _init_mulliken(self): - """ Initialize Mulliken analysis. """ - if self.calculation_required(self.el.atoms,['energy']): - raise AssertionError('Electronic structure is not solved yet!') - if self.flags['Mulliken']==False: - self.MA = MullikenAnalysis(self) - self.flags['Mulliken']=True - - def get_dq(self): - """ Return atoms' excess Mulliken populations. - - The total populations subtracted by - the numbers of valence electrons. - - """ - return self.st.get_dq() - - def get_atom_mulliken(self,I): - """ - Return Mulliken population for atom I. - - This is the total population, without the number - of valence electrons subtracted. - - parameters: - =========== - I: atom index - """ - self._init_mulliken() - return self.MA.get_atom_mulliken(I) - - - def get_basis_mulliken(self,mu): - """ - Return Mulliken population of given basis state. - - parameters: - =========== - mu: orbital index (see Elements' methods for indices) - """ - self._init_mulliken() - return self.MA.get_basis_mulliken(mu) - - - def get_atom_wf_mulliken(self,I,k,a,wk=True): - """ - Return Mulliken population for given atom and wavefunction. - - parameters: - =========== - I: atom index - k: k-vector index - a: eigenstate index - wk: embed k-point weight in population - """ - self._init_mulliken() - return self.MA.get_atom_wf_mulliken(I,k,a,wk) - - - def get_atom_wf_all_orbital_mulliken(self,I,k,a): - """ - Return orbitals' Mulliken populations for given atom and wavefunction. - - parameters: - =========== - I: atom index (returned array size = number of orbitals on I) - k: k-vector index - a: eigenstate index - """ - self._init_mulliken() - return self.MA.get_atom_wf_all_orbital_mulliken(I,k,a) - - - def get_atom_wf_all_angmom_mulliken(self,I,k,a,wk=True): - """ - Return atom's Mulliken populations for all angmom for given wavefunction. - - parameters: - =========== - I: atom index - k: k-vector index - a: eigenstate index - wk: embed k-point weight into population - - return: array (length 3) containing s,p and d-populations - """ - self._init_mulliken() - return self.MA.get_atom_wf_all_angmom_mulliken(I,k,a,wk) - - - # - # Densities of states methods - # - def _init_DOS(self): - """ Initialize Density of states analysis. """ - if self.calculation_required(self.el.atoms,['energy']): - raise AssertionError('Electronic structure is not solved yet!') - if self.flags['DOS']==False: - self.DOS = DensityOfStates(self) - self.flags['DOS']=True - - - def get_local_density_of_states(self,projected=False,width=0.05,window=None,npts=501): - """ - Return state density for all atoms as a function of energy. - - parameters: - =========== - projected: return local density of states projected for - angular momenta 0,1 and 2 (s,p and d) - width: energy broadening (in eV) - window: energy window around Fermi-energy; 2-tuple (eV) - npts: number of grid points for energy - - return: projected==False: - energy grid, ldos[atom,grid] - projected==True: - energy grid, - ldos[atom, grid], - pldos[atom, angmom, grid] - """ - self._init_DOS() - return self.DOS.get_local_density_of_states(projected,width,window,npts) - - - def get_density_of_states(self,broaden=False,projected=False,occu=False,width=0.05,window=None,npts=501): - """ - Return the full density of states. - - Sum of states over k-points. Zero is the Fermi-level. - Spin-degeneracy is NOT counted. - - parameters: - =========== - broaden: * If True, return broadened DOS in regular grid - in given energy window. - * If False, return energies of all states, followed - by their k-point weights. - projected: project DOS for angular momenta - occu: for not broadened case, return also state occupations - width: Gaussian broadening (eV) - window: energy window around Fermi-energy; 2-tuple (eV) - npts: number of data points in output - - return: * if projected: e[:],dos[:],pdos[l,:] (angmom l=0,1,2) - * if not projected: e[:],dos[:] - * if broaden: e[:] is on regular grid, otherwise e[:] are - eigenvalues and dos[...] corresponding weights - * if occu: e[:],dos[:],occu[:] - - """ - self._init_DOS() - return self.DOS.get_density_of_states(broaden,projected,occu,width,window,npts) - - - - # Bonding analysis - def _init_bonds(self): - """ Initialize Mulliken bonding analysis. """ - if self.calculation_required(self.el.atoms,['energy']): - raise AssertionError('Electronic structure is not solved yet!') - if self.flags['bonds']==False: - self.bonds = MullikenBondAnalysis(self) - self.flags['bonds']=True - - - def get_atom_energy(self,I=None): - """ - Return the energy of atom I (in eV). - - Warning: bonding & atom energy analysis less clear for - systems where orbitals overlap with own periodic images. - - parameters: - =========== - I: atom index. If None, return all atoms' energies - as an array. - """ - self._init_bonds() - return self.bonds.get_atom_energy(I) - - - - def get_mayer_bond_order(self,i,j): - """ - Return Mayer bond-order between two atoms. - - Warning: bonding & atom energy analysis less clear for - systems where orbitals overlap with own periodic images. - - parameters: - =========== - I: first atom index - J: second atom index - """ - self._init_bonds() - return self.bonds.get_mayer_bond_order(i,j) - - - def get_promotion_energy(self,I=None): - """ - Return atom's promotion energy (in eV). - - Defined as: - E_prom,I = sum_(mu in I) [q_(mu) - q_(mu)^0] epsilon_mu - - parameters: - =========== - I: atom index. If None, return all atoms' energies - as an array. - """ - self._init_bonds() - return self.bonds.get_promotion_energy(I) - - - def get_bond_energy(self,i,j): - """ - Return the absolute bond energy between atoms (in eV). - - Warning: bonding & atom energy analysis less clear for - systems where orbitals overlap with own periodic images. - - parameters: - =========== - i,j: atom indices - """ - self._init_bonds() - return self.bonds.get_bond_energy(i,j) - - - def get_atom_and_bond_energy(self,i=None): - """ - Return given atom's contribution to cohesion. - - parameters: - =========== - i: atom index. If None, return all atoms' energies - as an array. - """ - self._init_bonds() - return self.bonds.get_atom_and_bond_energy(i) - - - def get_covalent_energy(self,mode='default',i=None,j=None,width=None,window=None,npts=501): - """ - Return covalent bond energies in different modes. (eV) - - ecov is described in - Bornsen, Meyer, Grotheer, Fahnle, J. Phys.:Condens. Matter 11, L287 (1999) and - Koskinen, Makinen Comput. Mat. Sci. 47, 237 (2009) - - - - parameters: - =========== - mode: 'default' total covalent energy - 'orbitals' covalent energy for orbital pairs - 'atoms' covalent energy for atom pairs - 'angmom' covalent energy for angular momentum components - i,j: atom or orbital indices, or angular momentum pairs - width: * energy broadening (in eV) for ecov - * if None, return energy eigenvalues and corresponding - covalent energies in arrays, directly - window: energy window (in eV wrt Fermi-level) for broadened ecov - npts: number of points in energy grid (only with broadening) - - return: - ======= - x,y: * if width==None, x is list of energy eigenvalues (including k-points) - and y covalent energies of those eigenstates - * if width!=None, x is energy grid for ecov. - * energies (both energy grid and ecov) are in eV. - - Note: energies are always shifted so that Fermi-level is at zero. - Occupations are not otherwise take into account (while k-point weights are) - """ - self._init_bonds() - return self.bonds.get_covalent_energy(mode,i,j,width,window,npts) - - - def add_pair_potential(self,i,j,v,eVA=True): - """ - Add pair interaction potential function for elements or atoms - - parameters: - =========== - i,j: * atom indices, if integers (0,1,2,...) - * elements, if strings ('C','H',...) - v: Pair potential function. - Only one potential per element and atom pair allowed. - Syntax: v(r,der=0), v(r=None) returning the - interaction range in Bohr or Angstrom. - eVA: True for v in eV and Angstrom - False for v in Hartree and Bohr - """ - self.pp.add_pair_potential(i,j,v,eVA) - - - - - -### Helper functions - -def database_from_path(path): - if path is None: - path = '.' - - if not type(path) == list: - path = [ path ] - - fns = [ ] - for p in path: - fns += glob.glob('%s/*.elm' % p) - - elements = { } - tables = { } - - if len(fns) > 0: - for fn in fns: - i0 = fn.rfind('/') - i1 = fn.rfind('.') - el1 = fn[i0+1:i1] - - elements[el1] = fn - - for fn2 in fns: - i0 = fn.rfind('/') - i1 = fn.rfind('.') - el2 = fn2[i0+1:i1] - - for p in path: - if os.path.exists('%s/%s_%s.par' % ( p, el1, el2 )): - tables['%s%s' % ( el1, el2 )] = \ - '%s/%s_%s.par' % ( p, el1, el2 ) - else: - if os.path.exists('%s/%s_%s.par' % ( p, el2, el1 )): - tables['%s%s' % ( el1, el2 )] = \ - '%s/%s_%s.par' % ( p, el2, el1 ) - - else: - fns = [ ] - for p in path: - fns = glob.glob('%s/*-*.skf' % p) - - if len(fns) > 0: - for fn in fns: - i0 = fn.rfind('/') - i1 = fn.rfind('-') - i2 = fn.rfind('.') - el1 = fn[i0+1:i1] - el2 = fn[i1+1:i2] - - if el1 == el2: - elements[el1] = fn - tables['%s%s' % ( el1, el2 )] = fn - else: - raise RuntimeError('No Slater-Koster database found in directory ' - '%s.' % path) - - return { 'elements': elements, 'tables': tables } diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/atoms.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/atoms.py deleted file mode 100644 index b082d8d..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/atoms.py +++ /dev/null @@ -1,306 +0,0 @@ -from ase import Atoms as ase_Atoms -import numpy as np -from copy import copy -from hotbit.containers import * -from ase.io import PickleTrajectory - - - -def container_magic(atoms,container=None): - """ - Set or get container - (according to the element [0,0]) - """ - lst = ['Wedge','Chiral','DoubleChiral','Sphere','Slab'] - magic = -0.0123454321 - cell = atoms.get_cell() - if container==None: - x = cell[0,0]/magic - if np.abs(x)>1E-10 and np.abs(round(x)-x)<1E-10: - i = int(x-1) - return lst[i] - else: - return 'Bravais' - else: - if container!='Bravais': - i = lst.index(container)+1 - cell[0,0] = i*magic - atoms.set_cell(cell) - - - -class Atoms(ase_Atoms): - def __init__(self, symbols=None, - positions=None, numbers=None, - tags=None, momenta=None, masses=None, - magmoms=None, charges=None, - scaled_positions=None, - cell=None, pbc=None, - constraint=None, - calculator=None, - container=None, - atoms=None): - """ - Modified atoms class for hotbit. - - Input parameters as for ase.Atoms, except for keyword container. - - @param container: either container type ('Bravais','Wedge','Chiral' or any other - container from hotbit/containers/*.py), or - dictionary describing the generalized unit cell, where - container['type'] selects the cell class; for other keywords, - look at the selected classes - """ - ase_Atoms.__init__(self,symbols=symbols, - positions=positions, numbers=numbers, - tags=tags, momenta=momenta, masses=masses, - magmoms=magmoms, charges=charges, - scaled_positions=scaled_positions, - cell=cell, pbc=pbc, - constraint=constraint, - calculator=calculator) - - if type(atoms)!=type(None): - self += atoms - self.set_pbc( atoms.get_pbc() ) - self.set_cell( atoms.get_cell() ) - - if container==None: - dict = {'type':container_magic(self)} - elif type(container)==type(''): - dict = {'type':container} - else: - dict = container.copy() - - # create the container instance - assert 'type' in dict - exec( 'self.container_class = %s' %dict['type'] ) - self.container = self.container_class(atoms=self,type=dict['type']) - container_magic(self,container=dict['type']) - dict.pop('type') - if dict!={}: - self.container.set(**dict) - - # these are just for shorter references - self._transform = self.container.transform - self._rotation = self.container.rotation - - def get_container_type(self): - """ - Return container type (string, such as 'Chiral') - """ - return self.container.get_type() - - def get_container(self,key): - """ - Return container parameter - """ - return self.container.get(key) - - def set_container(self,**cont): - ''' - Set the container class and its parameters - - @param dict: dictionary of container parameters - ''' - if 'type' in cont: - if cont['type']!=self.container.type: - raise AssertionError('Container type cannot be changed.') - self.container.set(**cont) - - - def get_symmetry_operation_ranges(self): - ''' - Return the ranges for symmetry operations in different directions. - ''' - return self.container.get_symmetry_operation_ranges() - - - def is_cluster(self): - """ - Check whether the system a cluster, i.e. nonperiodic all directions. - """ - return np.all(np.abs(self.get_symmetry_operation_ranges()) != np.Inf) - - - def _check_symmetry_operation(self,n): - ''' - Check that given symmetry operation is allowed. - - @param n: tuple for number of symmetry operations - ''' - r = self.container.get_symmetry_operation_ranges() - for i in range(3): - a,b=r[i] - if not a<=n[i]<=b: - raise ValueError('Illegal symmetry operation: %i %i %i. For direction %i span [%i,%i] allowed.' %(n[0],n[1],n[2],i,a,b) ) - - - def transform(self,r,n): - ''' - Transform position r according to symmetry operation n. - - @param r: position vector - @param n: 3-tuple for symmetry operation. - ''' - self._check_symmetry_operation(n) - return self._transform(r,n) - - - def tensor(self,r,n): - ''' - Return the dyadic tensor - - d (R_j^n)_a - T(jn)_ab = ------------- hat_a hat_b - d (R_j)b - - @param r: position vector - @param n: symmetry operation 3-tuple - ''' - assert False - self._check_symmetry_operation(n) - return self._tensor(r,n) - - - def rotation_of_axes(self,n): - ''' - Return the 3x3 rotation matrix of coordination axes for given operation. - - @param n: 3-tuple for symmetry operation - ''' - assert False - self._check_symmetry_operation(n) - return self._rotation_of_axes(n) - - def rotation(self,n): - self._check_symmetry_operation(n) - return self._rotation(n) - - def extended_copy(self,n): - """ Get copies of atoms for all listed symmetry operations n. - - @param: n i) list of 3-tuples for transformations explicitly - e.g. [(0,0,0),(1,0,0),(0,1,0)] - ii) 3-tuple for the number of transformations - (for infinite extensions -> start from zero; - for finite extensions -> symmetry ops around zero) - e.g. (10,10,1) - iii) 3-tuple of 2-tuples that give the ranges for symmetry ops - e.g. ((-3,3),(-3,3),1) - - Return normal ase.Atoms -instance. - """ - r = self.container.get_symmetry_operation_ranges() - if isinstance(n,list): - n_list = copy(n) - elif isinstance(n,tuple): - ops = [] - for i in range(3): - if isinstance(n[i],tuple): - ops.append( np.arange(n[i][0],n[i][1]+1) ) - elif isinstance(n[i],int): - assert n[i]>0 - if r[i,0]==-np.Inf: - # this symmetry operation has the full range - rng = np.arange(0,n[i]) - else: - # take copies around the 0-operation - start = max(r[i,0],-n[i]/2) - rng = np.arange(start,start+n[i]) - ops.append( rng ) - - - n_list=[] - for n1 in ops[0]: - for n2 in ops[1]: - for n3 in ops[2]: - n_list.append( (n1,n2,n3) ) - - atoms2=None - for n in n_list: - self._check_symmetry_operation(n) - atomsn = ase_Atoms() - atomsn += self - atomsn.set_positions( [self.transform(r,n) for r in self.get_positions()] ) - try: - atoms2 += atomsn - except: - atoms2 = atomsn - - atoms2.set_pbc(False) - atoms2.set_cell((1,1,1)) - return atoms2 - - def repeat(self,n): - return self.extended_copy(n) - - def __eq__(self,other): - return ase_Atoms.__eq__(self,other) - #print self._cell - #print other._cell - #print ase_Atoms.__eq__(self,other) - #======================================================================= - # if ase_Atoms.__eq__(self,other): - # # for Bravais ase's Atoms.__eq__ is enough - # if self.container.type == 'Bravais': - # return True - # else: - # if hasattr(other,'container'): - # return self.same_container(other) - # else: - # raise AssertionError('Comparing Bravais and non-Bravais containers should not happen. Check the code.') - # else: - # return False - #======================================================================= - - def same_container(self,other): - """ Check if atoms has the same container. """ - return self.container==other.container - - - def copy(self): - """Return a copy.""" - cp = Atoms(atoms=self,container=self.container.type) - #cp += self - # set cell and pbc for initialization - #cp.set_pbc( self.get_pbc() ) - #cp.set_cell( self.get_cell() ) - #if self.container.type!='Bravais': - # cp.set_container(container=self.container) - # reset cell (for ase and visualization use) exactly the same - # (ase cell in set_container is taken from present atom positions, - # even though originally it might have been set earlier) - #assert np.all( self.get_pbc()==cp.get_pbc() ) - #cp.set_cell( self.get_cell() ) - return cp - - def __imul__(self, m): - raise NotImplementedError('*= not implemented yet, use extended_copy.') - - - -class ExtendedTrajectory: - def __init__(self,filename,atoms,n,mode='w'): - """ - Trajectory for multiple copies of unit cell. - - parameters: - =========== - filename: output .traj -file - atoms: hotbit.Atoms object - n: tuple of number of symmetry operations - or list of tuples for the symmetry operations - mode: 'w' write or 'a' append - """ - self.atoms = atoms - self.n = n - self.ext = self.atoms.extended_copy(n) - self.traj = PickleTrajectory(filename,mode,self.ext) - - def write(self): - cp = self.atoms.extended_copy(self.n) - self.ext.set_positions( cp.get_positions() ) - self.traj.write() - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/auxil.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/auxil.py deleted file mode 100644 index 90c80fc..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/auxil.py +++ /dev/null @@ -1,86 +0,0 @@ -import numpy as np - - -def k_to_kappa_points(k,atoms): - """ Transform normal k-points into kappa-points. - - parameters: - =========== - kpts: list of k-vectors - atoms: hotbit.Atoms -object - """ - if atoms.container.type!='Bravais': - raise AssertionError('For other than Bravais lattices only kappa-points are allowed.') - L = atoms.get_cell() - kappas = [] - for kpt in k: - kappas.append( np.dot(L,kpt) ) - return np.array(kappas) - - -def separate_symbols(string): - """ From given string, separate element symbols AuC=>Au,C""" - if string[1].islower(): - return string[:2],string[2:] - else: - return string[0],string[1:] - - -def make_hermitian(H): - """ Make matrix H hermitian using fast numpy routines. """ - H2=H+H.transpose().conjugate() - return H2-H.diagonal()*np.identity(H.shape[0]) - - -def make_derivative_antihermitian(dH): - """ Make vector matrix H antihermitian using fast numpy routines. """ - dH2=np.zeros_like(dH) - for a in range(3): - dH2[:,:,a]=dH[:,:,a]-dH[:,:,a].transpose().conjugate() - return dH2 - -def wf_dot_product(wf1,wf2,S): - """ Return the inner product of two wave functions wrt. metric S. """ - return np.dot( wf1.conjugate(),np.dot(S,wf2) ) - - -def same_matrix(M1,M2,tol=1E-13): - return np.all( abs(M1.flatten()-M2.flatten())2: return False - return A.shape[0]==A.shape[1] - elif property=='hermitian': - return same_matrix(A, A.conjugate().transpose(), tol ) - elif property=='symmetric': - return same_matrix(A, A.transpose(), tol ) - elif property=='orthogonal': - return same_matrix( np.dot(A,A.transpose()), np.identity(A.shape[0]), tol ) - elif property=='unitary': - #return same_matrix( np.dot(A,np.linalg.inv(A)), np.identity(A.shape[0]), tol ) - return same_matrix( np.dot(A,A.conjugate().transpose()), np.identity(A.shape[0]), tol ) - else: - raise NotImplementedError('Property %s is not defined yet.' %property) - - -if __name__=='__main__': - A=np.array([[np.cos(1.3),np.sin(1.3)],\ - [-np.sin(1.3),np.cos(1.3)]]) - print matrix_has_property(A,'hermitian') - print matrix_has_property(A,'square') - print matrix_has_property(A,'unitary') \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/__init__.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/__init__.py deleted file mode 100644 index e363bfb..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from bravais import Bravais -from chiral import Chiral -from doublechiral import DoubleChiral -from test1 import ContainerTest1 -from wedge import Wedge -from sphere import Sphere -from saddle import Saddle -from gaussian import Gaussian -from slab import Slab \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/bravais.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/bravais.py deleted file mode 100644 index b697a17..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/bravais.py +++ /dev/null @@ -1,87 +0,0 @@ -import numpy as np -from box.mix import phival -from math import sin,cos -from weakref import proxy - -class Bravais: - - def __init__(self,atoms,type): - """ - Class for Bravais lattice, for hotbit.Atoms -class - - More documentation for the methods can be found from hotbit.Atoms -class. - """ - self.type = 'Bravais' - assert type==self.type - self.atoms = proxy(atoms) - - def get_type(self): - return self.type - - def __repr__(self): - pbc=self.atoms.get_pbc() - cell=self.atoms.get_cell() - d = [] - for a in range(3): - d.append( np.linalg.norm(cell[a,:]) ) - - a12 = np.dot(cell[0],cell[1])/(d[0]*d[1]) - a13 = np.dot(cell[0],cell[2])/(d[0]*d[2]) - a23 = np.dot(cell[1],cell[2])/(d[1]*d[2]) - x='Bravais: pbc:[%i,%i,%i], ' %(pbc[0],pbc[1],pbc[2]) - x+='cell:[%.2f,%.2f,%.2f] Ang, \n cosines(12,13,23):[%.2f,%.2f,%.2f]' %(d[0],d[1],d[2],a12,a13,a23) - return x - - def set(self,**args): - if args!={}: - raise NotImplementedError('For Bravais use set_pbc and set_cell as normal.') - - def get_pbc(self): - """ Return atoms's pbc as normal.""" - return self.atoms.get_pbc() - - def __eq__(self,other): - if isinstance(other,Bravais) and np.all(self.get_pbc()==other.get_pbc()) \ - and self.get_cell()==other.get_cell(): - return True - else: - return False - - def get_table(self): - table = [] - for i,p in enumerate(self.atoms.get_pbc()): - if p: - M=np.Inf - else: - M=0 - table.append({'M':M}) - return table - - - def get_symmetry_operation_ranges(self): - """ Return ranges for symmetry operations. """ - #self._set_table() - ranges = [] - pbc = self.atoms.get_pbc() - for i in range(3): - if pbc[i]: - ranges.append([-np.Inf,np.Inf]) - else: - ranges.append([0,0]) - return np.array(ranges) - - - def transform(self,r,n): - """ Symmetry transformation n for position r. """ - rn = np.asarray(r).copy() - cell = self.atoms.get_cell() - for a in range(3): - rn = rn + n[a]*cell[a,:] - return rn - - def rotation(self,n): - """ No rotation in translations. """ - return np.eye(3) - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/chiral.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/chiral.py deleted file mode 100644 index 7f62928..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/chiral.py +++ /dev/null @@ -1,117 +0,0 @@ -import numpy as np -from box.mix import phival -from math import sin,cos -from weakref import proxy - - -class Chiral: - - def __init__(self,atoms,type): - ''' - Class for chiral boundary conditions. - - @param: atoms hotbit.Atoms -instance - @param: type Should equal to "Chiral" - - More documentation for the methods can be found from hotbit.Atoms -class. - ''' - self.type='Chiral' - assert type == self.type - self.atoms = proxy(atoms) - self.par = {'height':(1,0),'angle':(2,0)} - self.atoms.set_pbc( (False,False,True) ) - - def get_type(self): - return self.type - - def get_table(self): - return [{'M':1},{'M':1},{'M':np.Inf}] - - def __repr__(self): - angle = self.get('angle') - height = self.get('height') - if angle==None: - raise AssertionError('Chiral angle was not set yet.') - if angle<1E-14: - x='Chiral: angle=0.0, height=%.4f Ang' %(height) - else: - x='Chiral: angle=%.4f (2*pi/%.2f), height=%.4f Ang' %(angle,2*np.pi/angle,height) - return x - - - def get(self,key): - """ - Return container parameters. - - parameters: - =========== - key: 'angle','height' - """ - if key not in ['angle','height']: - raise AssertionError('Invalid keyword %s' %key) - if key=='angle': - return self.atoms.get_cell()[self.par['angle']] - elif key=='height': - return self.atoms.get_cell()[self.par['height']] - - def _set(self,**kwargs): - for key in kwargs: - cell = self.atoms.get_cell() - cell[self.par[key]] = kwargs[key] - self.atoms.set_cell(cell) - - - def set(self,angle=None,height=None,scale_atoms=False,container=None): - """ - Reset angle or height, and maybe scale atoms. - - @param: height Height of the primitive cell in z-direction - @param: angle angle (in radians) of rotation - """ - if container!=None: - # copy container - assert angle==None and height==None and scale_atoms==False - self.set( angle=container.get('angle'),height=container.get('height') ) - else: - if not scale_atoms: - if angle!=None: self._set(angle=angle) - if height!=None: self._set(height=height) - else: - if angle is None: - da = 0.0 - else: - da = angle - self.get('angle') - self._set(angle=angle) - - old_height = self.get('height') - if height != None: - self._set(height=height) - - newr = [] - for r in self.atoms.get_positions(): - x,y = r[0],r[1] - rad = np.sqrt( x**2+y**2 ) - frac = r[2]/old_height - # twist atoms z/h * da (more) - newphi = phival(x,y) + frac * da - newr.append( [rad*np.cos(newphi),rad*np.sin(newphi),frac*self.get('height')] ) - self.atoms.set_positions(newr) - - def __eq__(self,other): - return self.atoms == other.atoms - - def get_symmetry_operation_ranges(self): - """ Return ranges for symmetry operations. """ - return np.array( [[0,0],[0,0],[-np.Inf,np.Inf]] ) - - def transform(self,r,n): - """ Rotate r by n2*angle + translate (in z) by n2*height.""" - R = self.rotation(n) - return np.dot(R,r) + (0,0,n[2]*self.get('height')) - - def rotation(self,n): - """ Return the (active) rotation matrix for symmetry operation n. """ - angle = n[2]*self.get('angle') - R = np.array([[cos(angle),-sin(angle),0],[sin(angle),cos(angle),0],[0,0,1]]) - return R - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/doublechiral.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/doublechiral.py deleted file mode 100644 index 074c4bc..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/doublechiral.py +++ /dev/null @@ -1,148 +0,0 @@ -import numpy as np -from box.mix import phival -from math import sin,cos -from weakref import proxy - - -class DoubleChiral: - - def __init__(self,atoms,type): - ''' - Class for doubly chiral boundary conditions. - - Symmetry operations are: - 1) 180 degrees rotation around z-axis + - completing chiral transformation if system has translational symmetry - - S_1: R_z(n_1*pi + n_1*angle*x) + n_1*x*height*z - - 3) Rotation around z-axis and simultaneous translation along z-axis: - - S_3: R_z(n_3*angle)r + n_3*height*z - - The total symmetry operation is hence - - S(n_1,n_3): r' = R_z(n_3*angle + n_1*(pi + angle*x) + - (n_3 + n_1*x)*height*z - - where n_3 = 0,+-1,+-2,+-3,... - n_1 = 0,1 - x = 0....1 (fraction of full translation) - - parameters: - =========== - - atoms: hotbit.Atoms -instance - type: Should equal to "DoubleChiral" - - More documentation for the methods can be found from hotbit.Atoms -class. - ''' - self.type='DoubleChiral' - assert type==self.type - self.atoms = proxy(atoms) - self.par = {'angle':(1,0),'height':(2,0),'x':(0,1)} - self.atoms.set_pbc((True,False,True)) - - - def __repr__(self): - height, angle, x = self.get('height'), self.get('angle'), self.get('x') - if angle<1E-14: - st = 'DoubleChiral: angle=0.0, height=%.4f Ang, x=%.4f' %(height,x) - else: - st = 'DoubleChiral: angle=%.4f (2*pi/%.2f), height=%.4f Ang, x=%.4f' %(angle,2*np.pi/angle,height,x) - return st - - def get_type(self): - return self.type - - def get_table(self): - if abs(self.get('x'))>1E-12: - eq = ( 0,0,int(np.round(2*self.get('x'))) ) - return [{'M':2,'equivalent':eq},{'M':1},{'M':np.Inf}] - else: - return [{'M':2},{'M':1},{'M':np.Inf}] - - - def get(self,key): - """ - Return current angle, height, or x - """ - cell = self.atoms.get_cell() - if key in ['angle','height','x']: - return cell[self.par[key]] - else: - raise AssertionError('Invalid keyword %s' %key) - - - def _set(self,**kwargs): - assert len(kwargs)==1 - for key in kwargs: - cell = self.atoms.get_cell() - cell[self.par[key]] = kwargs[key] - self.atoms.set_cell(cell) - - - def set(self,angle=None,height=None,x=None,scale_atoms=False,container=None): - """ - Reset angle, height, or x, and maybe scale atoms. - - parameters: - =========== - height: Height of the primitive cell in z-direction - angle: angle (in radians) of rotation - x: fractional translation offset related to 180 rotation - Only integers and half-integers allowed. - """ - if container!=None: - # copy container - assert angle==None and height==None and x==None and scale_atoms==False - self.set(angle=container.get('angle'),height=container.get('height'),x=container.get('x')) - else: - if x!=None: - assert abs(np.round(2*x)-2*x)<1E-15 - if not scale_atoms: - if angle!=None: self._set(angle=angle) - if height!=None: self._set(height=height) - if x!=None: self._set(x=x) - else: - if x!=None: - raise AssertionError('It is probably illegal to change x. This changes the symmetry, right?') - if angle is None: - da = 0.0 - else: - da = angle - self.get('angle') - self._set(angle=angle) - - old_height = self.get('height') - if height != None: - self._set(height=height) - - newr = [] - for r in self.atoms.get_positions(): - x,y = r[0],r[1] - rad = np.sqrt( x**2+y**2 ) - frac = r[2]/old_height - # twist atoms z/h * da (more) - newphi = phival(x,y) + frac * da - newr.append( [rad*np.cos(newphi),rad*np.sin(newphi),frac*self.get('height')] ) - self.atoms.set_positions(newr) - - def __eq__(self,other): - return self.atoms == other.atoms - - def get_symmetry_operation_ranges(self): - """ Return ranges for symmetry operations. """ - return np.array( [[0,1],[0,0],[-np.Inf,np.Inf]] ) - - def transform(self,r,n): - """ See init doc for transformation.""" - R = self.rotation(n) - return np.dot(R,r) + (0,0,(n[2]+n[0]*self.get('x'))*self.get('height')) - - - def rotation(self,n): - """ Return the (active) rotation matrix for symmetry operation n. """ - angle = n[2]*self.get('angle') + n[0]*(np.pi+self.get('angle')*self.get('x')) - R = np.array([[cos(angle),-sin(angle),0],[sin(angle),cos(angle),0],[0,0,1]]) - return R - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/gaussian.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/gaussian.py deleted file mode 100644 index 2ab1861..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/gaussian.py +++ /dev/null @@ -1,115 +0,0 @@ -import numpy as np -from box.mix import phival -from math import sin,cos -from numpy import abs -from weakref import proxy -from box.mix import rotation_matrix - -class Gaussian: - def __init__(self,atoms,type): - ''' - Class for arbitrary Gaussian curvature. - - @param: atoms hotbit.Atoms instance - @param: type Should equal to "Saddle" - - More documentation for the methods can be found from hotbit.Atoms -class. - ''' - self.type='Gaussian' - assert type==self.type - self.atoms = proxy(atoms) - self.angle1 = None - self.angle2 = None - self.n1 = np.array([-1,0,0]) - self.n2 = np.array([0,1,0]) - self.R1 = None - self.R2 = None - - raise NotImplementedError('Gaussian container does not work properly') - - def __repr__(self): - x='Gaussian: angle1=%.4f, angle2=%.4f, R1=%.4f, R2=%.4f' %(self.angle1,self.angle2,self.R1,self.R2) - return x - - - def set(self, angle1=None, angle2=None, R1=None, R2=None, container=None): - """ - TODO: doc - n1 and n2 should be in xy-plane - """ - if container!=None: - assert angle1==None and angle2==None and R1==None and R2==None - self.set(angle1=container.angle1, angle2=container.angle2, R1=container.R1, R2=container.R2) - - if angle1!=None: - self.angle1=angle1 - if angle2!=None: - self.angle2=angle2 - if R1!=None: - self.R1 = R1 - if R2!=None: - self.R2 = R2 - - self.atoms.set_pbc((True,True,False)) - self.atoms.set_cell(self.get_ase_cell()) - - - def __eq__(self,other): - e=1E-12 - if isinstance(other,Saddle) and \ - abs(self.angle1-other.angle1)=min( abs(R1),abs(R2) ) - A = np.array( [0,0,abs(R1)+abs(R2)] ) # another center of curvature - rot = self.rotation(n) - if R>0: - #return np.array([0,0,0]) - return np.dot(rot,r) - else: - if R>0: - B=(0,0,R1-R) - else: - B=A-(0,0,R) - #B = (0,0,R1+abs(R2)-R) - #return np.array([0,0,0]) - return B + np.dot(rot,r-B) - - def rotation(self,n): - """ Rotate around two axes, ordering depending on mode. """ - if n[0]==n[1]==0: - return np.eye(3) - else: - R1, R2 = self.R1, self.R2 - a,b = self.angle1*n[0], self.angle2*n[1] - R = ( (a*R1)**2+(b*R2)**2 )/( a**2*R1+b**2*R2 ) - - axis = np.array( [R2*b,R1*a,0] ) - angle = ( a**2*R1+b**2*abs(R2) )/np.sqrt( (a*R1)**2+(b*R2)**2 ) - return rotation_matrix( axis,angle ) - \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/saddle.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/saddle.py deleted file mode 100644 index 50d47aa..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/saddle.py +++ /dev/null @@ -1,109 +0,0 @@ -import numpy as np -from box.mix import phival -from math import sin,cos -from weakref import proxy -from box.mix import rotation_matrix -from scipy import linalg - -expm = linalg.matfuncs.expm - -class Saddle: - def __init__(self,atoms,type): - ''' - Class for saddle point structure. - - @param: atoms hotbit.Atoms instance - @param: type Should equal to "Saddle" - - More documentation for the methods can be found from hotbit.Atoms -class. - ''' - self.type='Saddle' - assert type==self.type - self.atoms = proxy(atoms) - self.angle1 = None - self.angle2 = None - self.n1 = np.array([0,1,0]) - self.n2 = np.array([1,0,0]) - self.R = None - self.M = 50 - #raise NotImplementedError('Saddle container does not work properly') - - def __repr__(self): - x='Saddle: angle1=%.4f, angle2=%.4f, R=%.4f' %(self.angle1,self.angle2,self.R) - return x - - - def set(self, angle1=None, angle2=None, R=None, container=None): - """ - TODO: doc - n1 and n2 should be in xy-plane - """ - if container!=None: - assert angle1==None and angle2==None and R==None - self.set(angle1=container.angle1, angle2=container.angle2, R=container.R) - - if angle1!=None: - self.angle1=angle1 - if angle2!=None: - self.angle2=angle2 - if R!=None: - self.R = R - - self.atoms.set_pbc((True,True,False)) - self.atoms.set_cell(self.get_ase_cell()) - - - def __eq__(self,other): - e=1E-12 - if isinstance(other,Saddle) and \ - abs(self.angle1-other.angle1)1E-12 ): - x2 = np.array( np.round(2*self.x),int ) - eq = (x2[0],x2[1],0) - self.table = [{'M':np.Inf},{'M':np.Inf},{'M':2,'equivalent':eq}] - else: - self.table = [{'M':np.Inf},{'M':np.Inf},{'M':2}] - - - def set(self,container=None,x=None): - """ - Reset x. - - parameters: - =========== - x: fractional translation offset related to reflection. - Only integers and half-integers allowed. - """ - if container!=None: - # copy container - assert x==None - self.set(x=container.x) - else: - x = np.array(x) - if x!=None: - assert np.all( abs(np.round(2*x)-2*x)<1E-15 ) - self.x = np.array(x) - self._set_table() - - - def get_pbc(self): - """ Return atoms's pbc as normal.""" - return self.atoms.get_pbc() - - def get_ase_cell(self): - """ cell used for visualization """ - return self.atoms.get_cell() - - def __eq__(self,other): - - if isinstance(other,Slab) and np.all(self.atoms.get_pbc()==other.atoms.get_pbc()) \ - and np.all(np.abs(self.atoms.get_cell()-other.atoms.get_cell())<1E-12) \ - and np.all(np.abs(self.x-other.x)<1E-12): - return True - else: - return False - - - def get_symmetry_operation_ranges(self): - """ Return ranges for symmetry operations. """ - return np.array( [[-np.Inf,np.Inf],[-np.Inf,np.Inf],[0,1]] ) - - - def transform(self,r,n): - """ Symmetry transformation n for position r. """ - rn=r.copy() - cell = self.atoms.get_cell() - for a in range(2): - rn = rn + n[a]*cell[a,:] - if n[2]==1: - rn = rn + cell[a,:]*self.x[a] - if n[2]==1: - rn[2] = -rn[2] - return rn - - def rotation(self,n): - """ No rotation in translations. """ - R = np.eye(3) - if n[2]==0: - return R - else: - R[2,2] = -1.0 - return R - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/sphere.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/sphere.py deleted file mode 100644 index 961f9a8..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/containers/sphere.py +++ /dev/null @@ -1,148 +0,0 @@ -import numpy as np -from box.mix import phival -from math import sin,cos -from weakref import proxy -from box.mix import rotation_matrix - -class Sphere: - def __init__(self,atoms,type): - ''' - Class for spherical boundary conditions. - - ______ - /_____/ - - - - |z - | - |_________ y - / - / - /x - - @param: atoms hotbit.Atoms instance - @param: type Should equal to "Sphere" - - More documentation for the methods can be found from hotbit.Atoms -class. - ''' - self.type='Sphere' - assert type==self.type - self.atoms = proxy(atoms) - self.angle1 = None - self.angle2 = None - self.n1 = None - self.n2 = None - self.mode = 4 # mode 4 appears to be the best - self._set_table() - - def _set_table(self): - self.table = [{'M':np.Inf},{'M':np.Inf},{'M':1}] - - def get_type(self): - return self.type - - def __repr__(self): - x='Sphere: angle1=%.4f, angle2=%.4f, cos1=(%.2f,%.2f,%.2f), cos2=(%.2f,%.2f,%.2f)' %(self.angle1,self.angle2,self.n1[0],self.n1[1],self.n1[2],self.n2[0],self.n2[1],self.n2[2]) - return x - - - def set(self, angle1=None, angle2=None, n1=None, n2=None, mode=None, container=None): - """ - TODO: doc - n1 and n2 should be in xy-plane - """ - if container!=None: - assert angle1==None and angle2==None and n1==None and n2==None and mode==None - self.set(angle1=container.angle1, angle2=container.angle2, - n1=container.n1, n2=container.n2, mode=container.mode) - - if angle1!=None: - self.angle1=angle1 - if angle2!=None: - self.angle2=angle2 - if n1!=None: - assert abs(n1[2])<1E-10 - if self.n1!=None: - raise AssertionError('Rotation axis n1 cannot be changed.') - self.n1 = n1 - if n2!=None: - assert abs(n2[2])<1E-10 - if self.n2!=None: - raise AssertionError('Rotation axis n2 cannot be changed.') - self.n2 = n2 - if mode!=None: - self.mode = mode - - if self.n1!=None: - self.n1 = self.n1/np.linalg.norm(self.n1) - if self.n2!=None: - self.n2 = self.n2/np.linalg.norm(self.n2) - self.atoms.set_pbc((True,True,False)) - self.atoms.set_cell(self.get_ase_cell()) - - - def __eq__(self,other): - e=1E-12 - if isinstance(other,Sphere) and \ - abs(self.angle1-other.angle1) x-axis - - @param: atoms hotbit.Atoms instance - @param: type Should equal to "Wedge" - - More documentation for the methods can be found from hotbit.Atoms -class. - ''' - self.type='Wedge' - assert type==self.type - self.atoms = proxy(atoms) - self.par = {'height':(1,0),'angle':(2,0),'pbcz':(0,1),'physical':(1,1)} - #self.height = None - #self.angle = None - #self.physical = None - #self.pbcz = False - self.atoms.set_pbc((True,False,atoms.get_pbc()[2])) - #self._set_table() - - def get_type(self): - return self.type - - def __repr__(self): - angle, height, pbcz, physical = self.get('angle'), self.get('height'), self.get('pbcz'), self.get('physical') - x='Wedge: angle=%.4f (2*pi/%.2f, ' %(angle,2*np.pi/angle) - if physical: - x+='physical), ' - else: - x+='not physical), ' - x+='height=%.4f Ang ' %height - if pbcz: - x+='(z:pbc)' - else: - x+='(z:no pbc)' - return x - - def get_table(self): - M = int( round(2*np.pi/self.get('angle')) ) - if self.get('pbcz'): - return [{'M':M},{'M':1},{'M':np.Inf}] - else: - return [{'M':M},{'M':1},{'M':1}] - - - def get(self,key): - """ - Get container parameters - - key: 'angle','height','pbcz','physical' - """ - if key=='pbcz': - return self.atoms.get_pbc()[2] - else: - x = self.atoms.get_cell()[self.par[key]] - if key in ['angle','height']: - return x - else: - return bool(np.round(x)) - - def _set(self,**kwargs): - assert len(kwargs)==1 - if 'pbcz' in kwargs: - self.atoms.set_pbc( (True,False,kwargs['pbcz']) ) - else: - for key in kwargs: - cell = self.atoms.get_cell() - cell[self.par[key]] = kwargs[key] - self.atoms.set_cell(cell) - - - def set(self, angle=None, height=None, M=None, physical=True, pbcz=None, scale_atoms=False, container=None): - """ Only height can be reset, not angle. - - parameters: - =========== - angle angle (in radians) of the wedge (and M=None) - height Height of the primitive cell in z-direction - M set angle to 2*pi/M (and angle=None) - physical (only if M=None) if angle is small, it does not be - exactly 2*pi/integer, i.e. situation has no physical meaning - (use for calculating stuff continuously) - pbcz True if wedge is periodic in z-direction - scale_atoms Scale atoms according to changes in parameters - """ - if container!=None: - assert angle==None and height==None and M==None and pbcz==None - self.set(angle=container.get('angle'),height=container.get('height'),\ - physical=container.get('physical'), pbcz=container.atoms.get_pbc()[2]) - - if angle!=None or M!=None: - #assert not scale_atoms - assert not (angle!=None and M!=None) - old_angle = self.get('angle') - if M != None: - assert isinstance(M,int) - self._set(angle=2*np.pi/M) - elif angle != None: - M = int( round(2*np.pi/angle) ) - self._set(angle=angle) - - # check parameters - self._set( physical=float(physical) ) - if self.get('angle')<1E-6: - raise Warning('Too small angle (%f) may bring numerical problems.' %self.get('angle')) - if self.get('angle')>np.pi: - raise AssertionError('angle>pi') - if np.abs(M-2*np.pi/self.get('angle'))>1E-12 and self.get('physical'): - raise AssertionError('angle not physical: angle != 2*pi/M') - if not self.get('physical') and M<20: - warnings.warn('Quite large, non-physical angle 2*pi/%.4f.' %(2*np.pi/self.get('angle')) ) - - if scale_atoms: - if abs(old_angle)<1E-10: - raise ValueError('Atoms cannot be scaled; old wedge angle too small.') - newr = [] - for r in self.atoms.get_positions(): - x,y = r[0],r[1] - rad = np.sqrt( x**2+y**2 ) - newphi = phival(x,y)*(self.get('angle')/old_angle) - newr.append( [rad*np.cos(newphi),rad*np.sin(newphi),r[2]] ) - self.atoms.set_positions(newr) - - if height!=None: - if scale_atoms: - r = self.atoms.get_positions() - r[:,2] = r[:,2] * height/self.get('height') - self.atoms.set_positions(r) - self._set(height=height) - - if pbcz!=None: - self._set(pbcz=float(pbcz)) - - #self._set_table() - - - def __eq__(self,other): - return self.atoms == other.atoms - - - def get_symmetry_operation_ranges(self): - """ Return ranges for symmetry operations. """ - M = int( round(2*np.pi/self.get('angle')) ) - i = M/2 - zi = 0 - if self.get('pbcz'): - zi = np.Inf - if np.mod(M,2)==1: - ranges = np.array([[-i,i],[0,0],[-zi,zi]]) - else: - ranges = np.array([[-i+1,i],[0,0],[-zi,zi]]) - return ranges - - - def transform(self,r,n): - """ Rotate r by n2*angle. """ - R = self.rotation(n) - trans = np.zeros((3)) - if self.get('pbcz'): - trans = n[2]*np.array([0,0,self.get('height')]) - return np.dot(R,r) + np.array(trans) - - def rotation(self,n): - """ Active rotation matrix of given angle wrt. z-axis.""" - angle = n[0]*self.get('angle') - R = np.array([[cos(angle),-sin(angle),0],[sin(angle),cos(angle),0],[0,0,1]]) - return R - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/__init__.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/__init__.py deleted file mode 100644 index d9d131e..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from hotbit.coulomb.direct_coulomb import DirectCoulomb -from hotbit.coulomb.ewald_sum import EwaldSum -from hotbit.coulomb.multipole_expansion import MultipoleExpansion diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/baseclass.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/baseclass.py deleted file mode 100644 index 2868c78..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/baseclass.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -Coulomb base class. -""" - - -class Coulomb: - def __init__(self): - pass - - def get_potential(self, a=None): - """ - Return the electrostatic potential for each atom. - """ - raise NotImplementedError() - - def get_potential_and_field(self, a=None): - """ - Return the both, the electrostatic potential and the field for each - atom. - """ - raise NotImplementedError() - - def get_gamma(self, a=None): - """ - Return the gamma correlation matrix, i.e. phi(i) = gamma(i, j)*q(j). - """ - raise NotImplementedError() - - def get_potential_energy(self, a=None): - """ - Return the Coulomb energy. - """ - raise NotImplementedError() - - def get_forces(self, a=None): - """ - Return forces. - """ - raise NotImplementedError() - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/direct_coulomb.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/direct_coulomb.py deleted file mode 100644 index ade3392..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/direct_coulomb.py +++ /dev/null @@ -1,192 +0,0 @@ -""" -This module contains the MultipoleExpansion class, which computes the -electrostatic potential and field for a set of point charges under the -respective symmetry operations. - -The potential and field returned here does not include the contribution -of the shape (Gaussian/Slater) of the charges, which is short ranged and -can be easily added later. -""" - -# Copyright (C) 2010 NSC Jyvaskyla, Fh-IWM -# Please see the accompanying LICENSE file for further information. - -from math import pi, sqrt - -import numpy as np -from scipy.special import erfc - -from hotbit.neighbors import get_neighbors -from box.timing import Timer - -from hotbit.coulomb.baseclass import Coulomb - -# diag_indices_from was introduced in numpy 1.4.0 -if hasattr(np, 'diag_indices_from'): - diag_indices_from = np.diag_indices_from -else: - def diag_indices_from(m): - i = [ ] - for n in m.shape: - i += [ np.arange(n, dtype=int) ] - return tuple(i) - - -class DirectCoulomb(Coulomb): - def __init__(self, cutoff=None, timer=None): - """ - Instantiate a new DirectCoulomb object which computes the electrostatic - interaction by direct summation. - - Parameters: - ----------- - cutoff: If not None, the Coulomb interaction will be smoothly forced - to zero at this distance by multiplication with erfc(r/cutoff) - """ - if timer is None: - self.timer = Timer('DirectCoulomb') - else: - self.timer = timer - - self.cutoff = cutoff - - # Last positions - self.r_av = None - # Last charges - self.q_a = None - - - def update(self, a, q=None): - if q is None: - q = a.get_charges() - - r = a.get_positions() - # FIXME!!! Check for change in cell, symmetries - if self.r_av is None or self.q_a is None: - self._update(a, q) - elif np.any(r != self.r_av) or np.any(q != self.q_a): - self._update(a, q) - - - def _update(self, a, q): - """ - Compute the electrostatic potential and field on each atom in a. - - Parameters: - ----------- - a: Hotbit Atoms object, or atoms object that implements the transform - and rotation interface. - q: Charges - """ - self.timer.start('direct_coulomb') - - self.a = a - self.r_av = a.get_positions().copy() - self.q_a = q.copy() - - nat = len(a) - - il, jl, dl, nl = get_neighbors(a, self.cutoff) - - if il is not None: - if self.cutoff is None: - phi = q[jl]/dl - dl **= 2 - E = q[jl].reshape(-1, 1)*nl/dl.reshape(-1, 1) - else: - f = erfc(dl/self.cutoff) - df = 2/sqrt(pi)*np.exp(-(dl/self.cutoff)**2)/self.cutoff - phi = q[jl]*f/dl - E = q[jl]*(df + f/dl)/dl - E = E.reshape(-1, 1)*nl - - self.phi_a = np.zeros(nat, dtype=float) - self.E_av = np.zeros([nat, 3], dtype=float) - - if il is not None: - # FIXME!!! Is there some fast numpy magic to compute this? - for i in xrange(nat): - self.phi_a[i] = phi[il == i].sum() - self.E_av[i, :] = E[il == i].sum(axis=0) - - self.timer.stop('direct_coulomb') - - - def get_potential(self, a=None): - """ - Return the electrostatic potential for each atom. - """ - if a is not None: - self.update(a) - - return self.phi_a - - - def get_field(self, a=None): - """ - Return the electrostatic field for each atom. - """ - if a is not None: - self.update(a) - - return self.E_av - - - def get_potential_and_field(self, a=None): - """ - Return the both, the electrostatic potential and the field for each - atom. - """ - if a is not None: - self.update(a) - - return self.phi_a, self.E_av - - - def get_gamma(self, a=None): - """ - Return the gamma correlation matrix, i.e. phi(i) = gamma(i, j)*q(j) - """ - if a is not None: - self.update(a) - - self.timer.start('get_gamma') - - nat = len(self.a) - - il, jl, dl, nl = get_neighbors(self.a, self.cutoff) - - if il is None: - G = None - else: - G = np.zeros([nat, nat], dtype=float) - if self.cutoff is None: - for i, j, d in zip(il, jl, dl): - G[i, j] += 1.0/d - else: - for i, j, d in zip(il, jl, dl): - G[i, j] += 1.0*erfc(d/self.cutoff)/d - - self.timer.stop('get_gamma') - return G - - -### For use as a standalone calculator - - def get_potential_energy(self, a=None): - """ - Return the Coulomb energy. - """ - if a is not None: - self.update(a) - - return np.sum(self.q_a*self.phi_a)/2 - - def get_forces(self, a=None): - """ - Return forces - """ - if a is not None: - self.update(a) - - return self.q_a.reshape(-1, 1)*self.E_av diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/ewald_sum.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/ewald_sum.py deleted file mode 100644 index 8552d48..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/ewald_sum.py +++ /dev/null @@ -1,165 +0,0 @@ -""" -Ewald summation. - -The potential and field returned here does not include the contribution -of the shape (Gaussian/Slater) of the charges, which is short ranged and -can be easily added later. -""" - -# Copyright (C) 2010 NSC Jyvaskyla, Fh-IWM -# Please see the accompanying LICENSE file for further information. - -from math import log, pi, sqrt - -import numpy as np -# FIXME!!! Requires scipy, contribute erfc to numpy -from scipy.special import erfc - -from ase.units import Hartree, Bohr - -from box.timing import Timer - -from hotbit.coulomb.baseclass import Coulomb - -# diag_indices_from was introduced in numpy 1.4.0 -if hasattr(np, 'diag_indices_from'): - diag_indices_from = np.diag_indices_from -else: - def diag_indices_from(m): - i = [ ] - for n in m.shape: - i += [ np.arange(n, dtype=int) ] - return tuple(i) - - -# FIXME!!! No field yet in Ewald sum -class EwaldSum(Coulomb): - def __init__(self, accuracy_goal, weight, timer=None): - self.accuracy_goal = accuracy_goal - self.weight = weight - - if timer is None: - self.timer = Timer('EwaldSum') - else: - self.timer = timer - - - def update(self, a, q): - """ - Compute the electrostatic potential. - - Parameters: - ----------- - a: Hotbit Atoms object, or atoms object that implements the transform - and rotation interface. - q: Charges - """ - self.alpha = (self.weight*pi**3*len(a)/a.get_volume())**(1./3) - self.sqrt_alpha = sqrt(self.alpha) - - self.G_cutoff = 2*sqrt(log(10.0)*self.accuracy_goal*self.alpha) - self.r_cutoff = sqrt(log(10.0)*self.accuracy_goal/self.alpha) - - cell_cv = a.get_cell() - rec_cell_vc = np.linalg.inv(cell_cv) - r_av = a.get_positions() - - self.timer.start('reciprocal sum') - - # Reciprocal sum - lx, ly, lz = np.sqrt(np.sum(rec_cell_vc**2, axis=0)) - - maxGx = int(self.G_cutoff/(2*pi*lx))+1 - maxGy = int(self.G_cutoff/(2*pi*ly))+1 - maxGz = int(self.G_cutoff/(2*pi*lz))+1 - - Gx = 2*pi * np.arange(-maxGx, maxGx+1).reshape(-1, 1, 1, 1) - Gy = 2*pi * np.arange(-maxGy, maxGy+1).reshape( 1, -1, 1, 1) - Gz = 2*pi * np.arange(-maxGz, maxGz+1).reshape( 1, 1, -1, 1) - - G = Gx*np.array([1,0,0])+Gy*np.array([0,1,0])+Gz*np.array([0,0,1]) - G = np.dot(G, rec_cell_vc) - - si = np.sum( np.sin(np.tensordot(G, r_av, axes=(3,1)))*q, axis=3) - co = np.sum( np.cos(np.tensordot(G, r_av, axes=(3,1)))*q, axis=3) - - G_sq = np.sum( G*G, axis=3 ) - - rec_G_sq = 1.0/G_sq - rec_G_sq[maxGx, maxGy, maxGz] = 0.0 - - phase = np.tensordot(G, r_av, axes=(3, 1)) - - si.shape = ( 2*maxGx+1, 2*maxGy+1, 2*maxGz+1, 1 ) - co.shape = ( 2*maxGx+1, 2*maxGy+1, 2*maxGz+1, 1 ) - - self.phi_a = np.sum( np.sum( np.sum( - ( np.exp(-G_sq/(4*self.alpha))*rec_G_sq - ).reshape(2*maxGx+1, 2*maxGy+1, 2*maxGz+1, 1) * - ( si * np.sin(phase) + co * np.cos(phase) ), - axis=0 ), axis=0 ), axis=0 ) - self.phi_a *= 4*pi/a.get_volume() - - self.timer.stop('reciprocal sum') - - self.timer.start('real space sum') - - # Real space sum - lx, ly, lz = np.sqrt(np.sum(cell_cv**2, axis=1)) - - maxrx = int(self.r_cutoff/lx)+1 - maxry = int(self.r_cutoff/ly)+1 - maxrz = int(self.r_cutoff/lz)+1 - - nat = len(a) - r = a.get_positions() - for x in range(-maxrx, maxrx+1): - for y in range(-maxry, maxry+1): - for z in range(-maxrz, maxrz+1): - if x != 0 or y != 0 or z != 0: - r1 = np.dot([x,y,z], cell_cv) - - dr = r.reshape(nat, 1, 3) - \ - (r1+r).reshape(1, nat, 3) - abs_dr = np.sqrt(np.sum(dr*dr, axis=2)) - - phi = q*erfc(self.sqrt_alpha*abs_dr)/abs_dr - - self.phi_a += np.sum(phi, axis=1) - - - ## Self-contribution - dr = r.reshape(nat, 1, 3) - r.reshape(1, nat, 3) - abs_dr = np.sqrt(np.sum(dr*dr, axis=2)) - - ## Avoid divide by zero - abs_dr[diag_indices_from(abs_dr)] = 1.0 - - phi = q*erfc(self.sqrt_alpha*abs_dr)/abs_dr - - phi[diag_indices_from(phi)] = 0.0 - - self.phi_a += np.sum(phi, axis=1) - - self.timer.stop('real space sum') - - # Self energy - self.phi_a -= 2*q*sqrt(self.alpha/pi) - - - def get_potential(self): - """ - Return the electrostatic potential for each atom. - """ - return self.phi_a - - -### For use as a standalone calculator -### Note: These functions assume eV/A units - - def get_potential_energy(self, a, q=None): - if q is None: - q = a.get_charges() - - self.update(a, q) - return Hartree * Bohr * np.sum(q*self.phi_a)/2 diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/multipole.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/multipole.py deleted file mode 100644 index eb9e6ad..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/multipole.py +++ /dev/null @@ -1,64 +0,0 @@ -""" -Multipole expansion module - -Naming conventions for arrays: - -index description ------ ----------- -l angular momentum number -L l and m for l != 0 -""" - -# Copyright (C) 2010 NSC Jyvaskyla, Fh-IWM -# Please see the accompanying LICENSE file for further information. - -import numpy as np - -from _hotbit import solid_harmonic_R, multipole_to_multipole -from _hotbit import multipole_to_local, local_to_local, transform_multipole - - -def lm2index(l, m): - """ - Return unique index for the off-diagonal elements - of the multipole moments. - - The mapping is l,m -> l*(l-1)/2 + m - 1 - - Parameters: - ----------- - l, m - """ - - return l*(l-1)/2 + m - 1 - - -def zero_moments(l_max): - """ - Return array with zero moments. - """ - - return np.zeros([l_max+1], dtype=float), \ - np.zeros([lm2index(l_max,l_max)+1], dtype=complex) - - -def get_moments(r, q, l_max, r0): - """ - Compute the multipole moments of a set of atoms - - Parameters: - r: Positions - q: Charges - l_max: Maximum angular momentum number for the expansion - r0: Expansion origin - """ - - # This could be easily moved to C if it turns out to be slow - M0_l, M_L = zero_moments(l_max) - for r, q in zip(r, q): - cR0_l, cR_L = solid_harmonic_R(r-r0, l_max) - M0_l += q*cR0_l - M_L += q*cR_L - - return M0_l, M_L.conj() - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/multipole_expansion.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/multipole_expansion.py deleted file mode 100644 index 6a93aee..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/coulomb/multipole_expansion.py +++ /dev/null @@ -1,409 +0,0 @@ -""" -This module contains the MultipoleExpansion class, which computes the -electrostatic potential and field for a set of point charges under the -respective symmetry operations. - -The potential and field returned here does not include the contribution -of the shape (Gaussian/Slater) of the charges, which is short ranged and -can be easily added later. -""" - -# Copyright (C) 2010 NSC Jyvaskyla, Fh-IWM -# Please see the accompanying LICENSE file for further information. - -from math import pi, sqrt - -import numpy as np - -from hotbit.neighbors import n_from_ranges - -from hotbit.coulomb.multipole import get_moments, zero_moments -from hotbit.coulomb.multipole import multipole_to_multipole, multipole_to_local -from hotbit.coulomb.multipole import local_to_local, transform_multipole - -from box.timing import Timer - -from hotbit.coulomb.baseclass import Coulomb - -# diag_indices_from was introduced in numpy 1.4.0 -if hasattr(np, 'diag_indices_from'): - diag_indices_from = np.diag_indices_from -else: - def diag_indices_from(m): - i = [ ] - for n in m.shape: - i += [ np.arange(n, dtype=int) ] - return tuple(i) - - -class MultipoleExpansion(Coulomb): - _TOL = 1e-6 - - def __init__(self, l_max=8, n=3, k=5, r0=None, timer=None): - """ - Instantiate a new MultipoleExpansion object which computes - the electrostatic interaction by direct summation using a - telescoped multipole expansion. - - Parameters: - ----------- - l_max: Order of the expansion (maximum angular momentum, - typically 5 to 8) - n: Number of cells to combine during each telescoping step - k: Summation cutoff. The interaction range will be n**k - (number of cells, typically k = 5). - """ - if l_max < 1: - raise ValueError('l_max must be >= 1.') - if np.any(np.array(n) < 1): - raise ValueError('n must be >= 1.') - if np.any(np.array(k) < 1): - raise ValueError('k must be >= 1.') - - self.l_max = l_max - - if type(n) == int: - n = np.array([n]*3) - else: - n = np.array(n) - - if len(n) != 3: - raise TypeError('n must be an integer scalar or a 3-tuple.') - - # The multipole-to-multipole operation is carried out over the - # range [self.n1, self.n2] - self.n1 = -((n-1)/2) - self.n2 = n/2 - #self.dx = -0.5*(self.n1 + self.n2) - - # The multipole-to-local operation is carried out over cells farther - # away, hence the range [self.m1, self.m2] - n **= 2 - self.m1 = -((n-1)/2) - self.m2 = n/2 - - if type(k) == int: - self.k = np.array([k]*3) - else: - self.k = np.array(k) - - if len(self.k) != 3: - raise TypeError('k must be an integer scalar or a 3-tuple.') - - self.r0_v = None - if r0 is not None: - self.r0_v = np.asarray(r0).copy() - - if timer is None: - self.timer = Timer('MultipoleExpansion') - else: - self.timer = timer - - # Last positions - self.r_av = None - # Last charges - self.q_a = None - - - def update(self, a, q=None): - if q is None: - q = a.get_charges() - - r = a.get_positions() - # FIXME!!! Check for change in cell, symmetries - if self.r_av is None or self.q_a is None: - self._update(a, q) - elif np.any(r != self.r_av) or np.any(q != self.q_a): - self._update(a, q) - - - def _update(self, a, q): - """ - Compute multipoles, do the transformations, and compute the - electrostatic potential and field on each atom in a. - - Parameters: - ----------- - a: Hotbit Atoms object, or atoms object that implements the transform - and rotation interface. - q: Charges - """ - self.timer.start('multipole_to_multipole') - - self.r_av = a.get_positions().copy() - self.q_a = q.copy() - - nat = len(a) - r = a.get_positions() - - if self.r0_v is None: - r0_v = np.sum(r, axis=0)/len(a) - else: - r0_v = self.r0_v - - T0_l, T_L = get_moments(r, q, self.l_max, r0_v) - - self.M = [ ( T0_l.copy(), T_L.copy() ) ] - self.r0 = [ r0_v ] - - sym_ranges = a.get_symmetry_operation_ranges() - for ( s1, s2 ), k in zip(sym_ranges, self.k): - if s2 != np.Inf and k != 1: - print sym_ranges - print self.k - raise ValueError('For non-periodic symmetries the k-value must ' - 'be 1.') - n1, n2, n3 = n_from_ranges(sym_ranges, self.n1, self.n2) - - # Compute telescoped multipoles - level = np.ones(3, dtype=int) - for k in range(np.max(self.k)-2): - M0_l = T0_l - M_L = T_L - - T0_l = np.zeros_like(M0_l) - T_L = np.zeros_like(M_L) - - if k >= self.k[0]-2: - _n1 = [ 0, 1 ] - else: - _n1 = n1 - - if k >= self.k[1]-2: - _n2 = [ 0, 1 ] - else: - _n2 = n2 - - if k >= self.k[2]-2: - _n3 = [ 0, 1 ] - else: - _n3 = n3 - - r0_v = np.zeros(3, dtype=float) - n = 0 - # Determine center of gravity - for x1 in range(*_n1): - for x2 in range(*_n2): - for x3 in range(*_n3): - x = np.array([x1, x2, x3]) - r0_v += a.transform(self.r0[k], x*level) - n += 1 - r0_v /= n - self.r0 += [ r0_v ] - #self.r0 += [ self.r0[0] ] - - # Transform multipoles - for x1 in range(*_n1): - for x2 in range(*_n2): - for x3 in range(*_n3): - # Loop over all symmetry operations and compute - # telescoped multipoles - # FIXME!!! Currently only supports continuous - # symmetries, think about discrete/recurrent ones. - x = np.array([x1, x2, x3]) #+ self.dx - - # The origin is already okay, skip it - #if np.any(np.abs(x) > self._TOL): - r1 = a.transform(self.r0[k], x*level) - T = a.rotation(x*level) - S0_l, S_L = transform_multipole(T, self.l_max, - M0_l, M_L) - multipole_to_multipole(r1-self.r0[k], self.l_max, - S0_l, S_L, T0_l, T_L) - - self.M += [ ( T0_l.copy(), T_L.copy() ) ] - - level *= self.n2-self.n1+1 - - self.timer.stop('multipole_to_multipole') - - ### - - self.timer.start('multipole_to_local') - - # Compute the local expansion from telescoped multipoles - L0_l, L_L = zero_moments(self.l_max) - m1, m2, m3 = n_from_ranges(sym_ranges, self.m1, self.m2) - Mi = len(self.M)-1 - for k in range(np.max(self.k)-1): - M0_l, M_L = self.M[Mi] - - if k >= self.k[0]-1: - _m1 = [ 0, 1 ] - else: - _m1 = m1 - - if k >= self.k[1]-1: - _m2 = [ 0, 1 ] - else: - _m2 = m2 - - if k >= self.k[2]-1: - _m3 = [ 0, 1 ] - else: - _m3 = m3 - - for x1 in range(*_m1): - for x2 in range(*_m2): - for x3 in range(*_m3): - # Loop over all symmetry operations and compute the - # local expansion from the telescoped multipoles - x = np.array([x1, x2, x3]) #+ self.dx - - # No local expansion in the inner region - if np.any(x < self.n1) or np.any(x > self.n2): - r1 = a.transform(self.r0[Mi], x*level) - T = a.rotation(x*level) - S0_l, S_L = transform_multipole(T, self.l_max, - M0_l, M_L) - multipole_to_local(-r1+self.r0[Mi], self.l_max, - S0_l, S_L, L0_l, L_L) - - level /= self.n2-self.n1+1 - Mi -= 1 - - self.L = ( L0_l, L_L ) - - self.timer.stop('multipole_to_local') - - ### - - self.phi_a = np.zeros(nat, dtype=float) - self.E_av = np.zeros([nat, 3], dtype=float) - - ### - - self.timer.start('local_to_local') - - for i in a: - loc0_l, loc_L = local_to_local(i.get_position()-self.r0[0], - self.l_max, L0_l, L_L, 1) - self.phi_a[i.index] = loc0_l[0] - self.E_av[i.index, :] = [ -loc_L[0].real, - -loc_L[0].imag, - loc0_l[1] ] - - self.timer.stop('local_to_local') - - ### - - self.timer.start('near_field') - - # Contribution of neighboring boxes - for x1 in range(*n1): - for x2 in range(*n2): - for x3 in range(*n3): - # self-interaction needs to be treated separately - if x1 != 0 or x2 != 0 or x3 != 0: - x = np.array([x1, x2, x3]) - - # construct a matrix with distances - r1 = a.transform(self.r0[0], x) - T = a.rotation(x) - - rT = np.dot(r-self.r0[0], np.transpose(T)) - - dr = r.reshape(nat, 1, 3) - \ - (r1+rT).reshape(1, nat, 3) - abs_dr = np.sqrt(np.sum(dr*dr, axis=2)) - phi = q/abs_dr - E = q.reshape(1, nat, 1)*dr/ \ - (abs_dr**3).reshape(nat, nat, 1) - - self.phi_a += np.sum(phi, axis=1) - self.E_av += np.sum(E, axis=1) - - # Self-contribution - dr = r.reshape(nat, 1, 3) - r.reshape(1, nat, 3) - abs_dr = np.sqrt(np.sum(dr*dr, axis=2)) - - # Avoid divide by zero - abs_dr[diag_indices_from(abs_dr)] = 1.0 - - phi = q/abs_dr - E = q.reshape(1, nat, 1)*dr/(abs_dr**3).reshape(nat, nat, 1) - - phi[diag_indices_from(phi)] = 0.0 - E[diag_indices_from(phi)] = 0.0 - - self.phi_a += np.sum(phi, axis=1) - self.E_av += np.sum(E, axis=1) - - # Dipole correction for 3D sum - s1, s2, s3 = sym_ranges - if s1[1] == np.Inf and s2[1] == np.Inf and s3[1] == np.Inf: - Ml0, Mlm = self.M[0] - - dip = np.array([-2*Mlm[0].real, 2*Mlm[0].imag, Ml0[1]]) - dip *= 4*pi/(3*a.get_volume()) - - self.phi_a -= np.dot(r-self.r0[0], dip) - self.E_av += dip - - self.timer.stop('near_field') - - - def get_moments(self): - """ - Return the multipole moments. - """ - return self.M - - - def get_local_expansion(self): - """ - Return the local expansion of the potential. - """ - return self.L - - - def get_potential(self, a=None): - """ - Return the electrostatic potential for each atom. - """ - if a is not None: - self.update(a) - - return self.phi_a - - - def get_field(self, a=None): - """ - Return the electrostatic field for each atom. - """ - if a is not None: - self.update(a) - - return self.E_av - - - def get_potential_and_field(self, a=None): - """ - Return the both, the electrostatic potential and the field for each - atom. - """ - if a is not None: - self.update(a) - - return self.phi_a, self.E_av - - -### For use as a standalone calculator - - def get_potential_energy(self, a=None): - """ - Return the Coulomb energy. - """ - if a is not None: - self.update(a) - - return np.sum(self.q_a*self.phi_a)/2 - - def get_forces(self, a=None): - """ - Return forces - """ - if a is not None: - self.update(a) - - return self.q_a.reshape(-1, 1)*self.E_av diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/electrostatics.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/electrostatics.py deleted file mode 100644 index 76ab21b..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/electrostatics.py +++ /dev/null @@ -1,289 +0,0 @@ -""" -Compute electrostatic interaction and construct the 'electrostatic' -matrix h1 containing the shift in on-site energies. - -This module only adds the contribution of the charge density. The interaction -of point charges is computed by one of the solvers in the Coulomb submodule. -""" - -# Copyright (C) 2008 NSC Jyvaskyla -# Please see the accompanying LICENSE file for further information. - -from math import exp, log, pi, sqrt -from weakref import proxy -from math import sqrt - -from ase.units import Hartree, Bohr - -import numpy as np -from scipy.special import erf, erfc -norm=np.linalg.norm -dot=np.dot - -from neighbors import get_neighbors -from hotbit.coulomb import DirectCoulomb - -# diag_indices_from was introduced in numpy 1.4.0 -if hasattr(np, 'diag_indices_from'): - diag_indices_from = np.diag_indices_from -else: - def diag_indices_from(m): - i = [ ] - for n in m.shape: - i += [ np.arange(n, dtype=int) ] - return tuple(i) - - -# Some constants -log2 = log(2.0) - - -def get_Gaussian_gamma_correction(a, U, FWHM=None, - cutoff=None, accuracy_goal=12): - """ - Gaussian charge distribution. - """ - if FWHM is None: - FWHM = sqrt(8*log2/pi)/U - - max_FWHM = np.max(FWHM) - if max_FWHM <= 0.0: - raise ValueError("Maximum FWHM (%f) smaller than or equal to zero. " % - max_FWHM) - - if cutoff is None and not a.is_cluster(): - # Estimate a cutoff from the accuracy goal if the - # system is periodic and no cutoff was given - cutoff = sqrt(log(10.0)*accuracy_goal*max_FWHM/(sqrt(4*log2))) - - il, jl, dl, nl = get_neighbors(a, cutoff) - - nat = len(a) - G = np.zeros([nat, nat], dtype=float) - dG = np.zeros([nat, nat, 3], dtype=float) - G[diag_indices_from(G)] = U - - if il is not None: - for i, j, d, n in zip(il, jl, dl/Bohr, nl): - const = 2*sqrt( log2/(FWHM[i]**2+FWHM[j]**2) ) - ecr = -erfc(const*d) - decr = 2/sqrt(pi)*exp(-(const*d)**2)*const - G[i, j] += ecr/d - dG[i, j, :] += (ecr/d-decr)*n/d - - return G, dG - - -def get_Slater_gamma_correction(a, U, FWHM=None, - cutoff=None, accuracy_goal=12): - """ - Slater-type charge distribution. - See: M. Elstner et al., Phys. Rev. B 58, 7260 (1998) - """ - min_U = np.min(U) - if min_U <= 0.0: - raise ValueError("Minimum U (%f) smaller than or equal to zero. " % - min_U) - - if cutoff is None and not a.is_cluster(): - # Estimate a cutoff from the accuracy goal if the - # system is periodic and no cutoff was given - cutoff = sqrt(log(10.0)*accuracy_goal/(sqrt(pi/2)*min_U)) - - tau = 16*np.asarray(U)/5 - - il, jl, dl, nl = get_neighbors(a, cutoff) - - nat = len(a) - G = np.zeros([nat, nat], dtype=float) - dG = np.zeros([nat, nat, 3], dtype=float) - G[diag_indices_from(G)] = U - - if il is not None: - for i, j, d, n in zip(il, jl, dl/Bohr, nl): - if abs(tau[i] - tau[j]) < 1e-6: - src = 1.0/(tau[i]+tau[j]) - fac = tau[i]*tau[j]*src - avg = 1.6*(fac+fac*fac*src) - fac = avg*d - fac2 = fac*fac - efac = exp(-fac)/(48*d) - h = -(48 + 33*fac + fac2*(9+fac))*efac - G[i, j] += \ - h - dG[i, j, :] += \ - ( h/d \ - + avg*h \ - + (33*avg + 18*fac*avg + 3*fac2*avg)*efac )*n - else: - fi1 = 1.0/(2*(tau[i]**2-tau[j]**2)**2) - fj1 = -tau[i]**4*tau[j]*fi1 - fi1 *= -tau[j]**4*tau[i] - - fi2 = 1.0/((tau[i]**2-tau[j]**2)**3) - fj2 = -(tau[i]**6-3*tau[i]**4*tau[j]**2)*fi2 - fi2 *= (tau[j]**6-3*tau[j]**4*tau[i]**2) - - expi = exp(-tau[i]*d) - expj = exp(-tau[j]*d) - - G[i, j] += \ - expi*(fi1+fi2/d) \ - + expj*(fj1+fj2/d) - dG[i, j, :] += \ - ( expi*(tau[i]*(fi1+fi2/d) + fi2/(d**2)) \ - + expj*(tau[j]*(fj1+fj2/d) + fj2/(d**2)) )*n - - return G, dG - - -_gamma_correction_dict = { - 'Gaussian': get_Gaussian_gamma_correction, - 'Slater': get_Slater_gamma_correction - } - - -class Electrostatics: - def __init__(self, calc, charge_density='Gaussian', - solver=None, accuracy_goal=12): - self.calc=proxy(calc) - self.norb=calc.el.get_nr_orbitals() - self.SCC=calc.get('SCC') - self.N=len(calc.el) - self.dq=np.zeros((self.N)) - self.G=np.zeros((self.N,self.N)) - self.dG=np.zeros((self.N,self.N,3)) - - self.accuracy_goal = accuracy_goal - - if not charge_density in _gamma_correction_dict.keys(): - raise RuntimeError("Unknown charge density type: %s." % - charge_density) - - self.gamma_correction = _gamma_correction_dict[charge_density] - - if solver is None: - cut = self.calc.get('gamma_cut') - if self.SCC and cut==None and np.any(self.calc.el.atoms.get_pbc()): - raise AssertionError('gamma_cut must be provided for periodic calculations and with DirectCoulomb') - self.solver = DirectCoulomb(cut) - else: - self.solver = solver - - - def set_dq(self,dq): - """ (Re)setting dq gives new gamma-potential. """ - self.dq=dq - self.epsilon = np.sum(self.G*self.dq, axis=1) - if self.solver is not None: - self.solver.update(self.calc.el.atoms, dq) - # Unit mess: The Coulomb solver is unit agnostic, but the Elements - # object returns the distances in Bohr (from get_distances()) - self.epsilon += self.solver.get_potential()*Bohr - - - def coulomb_energy(self): - """ Return Coulomb energy. """ - self.calc.start_timing('ecoul') - ecoul = 0.0 - if not self.SCC: - ecoul = 0.0 - else: - ecoul = 0.5 * dot(self.dq,self.epsilon) - self.calc.stop_timing('ecoul') - return ecoul - - - def gamma_forces(self): - """ Return forces due to electrostatic interactions. """ - if not self.SCC: - return np.zeros((self.N,3)) - else: - self.calc.start_timing('f_es') - if self.solver is None: - E = np.zeros((self.N,3)) - else: - # Unit mess: The Coulomb solver is unit agnostic, but the - # Elements object returns the distances in Bohr - # (from get_distances()) - E = self.solver.get_field()*Bohr**2 - depsilon = np.sum(self.dq.reshape(1, -1, 1)*self.dG, axis=1) - f = self.dq.reshape(-1, 1) * ( depsilon + E ) - self.calc.stop_timing('f_es') - return f - - - def construct_h1(self,dq=None): - """ Make the electrostatic part of the Hamiltonian. """ - self.calc.start_timing('h1') - if dq!=None: - self.set_dq(dq) - - lst = self.calc.el.get_property_lists(['i','o1','no']) - - aux = np.zeros((self.norb,self.norb)) - for i,o1i,noi in lst: - aux[o1i:o1i+noi,:] = self.epsilon[i] - h1 = 0.5 * ( aux+aux.transpose() ) - - # external electrostatics - if np.any(abs(self.ext)>1E-12): - aux = np.zeros((self.norb,self.norb)) - for i,o1i,noi in lst: - aux[o1i:o1i+noi,:] = self.ext[i] - h1 = h1 + 0.5 * (-1) * (aux+aux.transpose()) - - self.calc.stop_timing('h1') - self.h1=h1 - return self.h1 - - - def get_h1(self): - """ Get the current electrostatic Hamiltonian. """ - return self.h1 - - - def construct_Gamma_matrix(self, a): - ''' - Construct the G-matrix and its derivative. - - Done once for each geometry; - G_ij = sum_n gamma_ij(Rijn) - dG_ij = sum_n gamma'_ij(Rijn) hat(Rijn) - ''' - self.calc.start_timing('gamma matrix') - - U = [ self.calc.el.get_element(i).get_U() - for i in range(len(a)) ] - FWHM = [ self.calc.el.get_element(i).get_FWHM() - for i in range(len(a)) ] - - G, dG = self.gamma_correction(a, U, - FWHM = FWHM, - cutoff = self.calc.get('gamma_cut'), - accuracy_goal = self.accuracy_goal) - - self.G, self.dG = G, dG - - self.ext = np.array( [self.calc.env.phi(i) for i in range(self.N)] ) - self.calc.stop_timing('gamma matrix') - - - def get_gamma(self): - return self.G + self.solver.get_gamma()*Bohr - - -### For use as a standalone calculator, return eV/A units - - def get_potential_energy(self, a): - self.calc.el.update_geometry(a) - self.construct_Gamma_matrix(a) - self.set_dq(a.get_charges()) - return self.coulomb_energy()*Hartree - - def get_forces(self, a): - self.calc.el.update_geometry(a) - self.construct_Gamma_matrix(a) - self.set_dq(a.get_charges()) - return self.gamma_forces()*Hartree/Bohr - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/element.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/element.py deleted file mode 100644 index c563200..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/element.py +++ /dev/null @@ -1,208 +0,0 @@ -import os -import numpy as np -from box import mix -import numpy as npy -from box.data import data -from hotbit.io import read_element - -orbital_list=['s','px','py','pz','dxy','dyz','dzx','dx2-y2','d3z2-r2'] - -class Element: - def __init__(self,element): - """ - Initialize element with given symbol (e.g. 'C') or from file (e.g. 'C.elm'). - (elm file first searched from present directory, - then from the default HOTBIT_PARAMETERS/[symbol].elm - """ - i=element.rfind('.')+1 - - if i>0: - # element is full file name; get symbol - filename=element - j=element.rfind('/') - if j>=0: - ind=j+1 - else: - ind=0 - symbol=element[ind] - if element[ind+1].islower() and element[ind+1].isalpha(): - symbol+=element[ind+1] - else: - symbol=element - filename=element+'.elm' - - # if .elm file exists, read more data - hbp = os.environ.get('HOTBIT_PARAMETERS') - default='%s/%s' %(hbp,filename) - if os.path.isfile(filename): - file=filename - elif os.path.isfile(default): - file=default - else: - raise AssertionError('Element data for %s not found neither in %s ' - 'nor in %s' % (element,'.',hbp)) - - self.data, self.functions = read_element(file, symbol) - self.data['file']=file - - - def set(self,key,value): - self.data[key]=value - - - def get_free_atom_energy(self): - ''' - Return the energy of a free element (sum_i f_i*e_i) - ''' - e=0.0 - for valence in self.data['valence_orbitals']: - e += self.data['configuration'][valence]*self.get_epsilon(valence) - return e - - - def get_comment(self): - """ Get comments describing the present element. """ - return self.data['comment'] - - - def _transform_orbital(self,orb): - """ Transform 'px->'2p' etc. """ - if orb in self.data['valence_orbitals']: - return orb - for v in self.data['valence_orbitals']: - if orb[0]==v[1]: return v - - - def get_valence_orbitals(self): - """ Return ['2s','2p']... """ - return self.data['valence_orbitals'] - - - def get_symbol(self): - """ Return 'H', 'C', etc. """ - return self.data['symbol'] - - - def get_valence_number(self): - """ Return the number of valence electrons. """ - return self.data['valence_number'] - - - def get_epsilon(self,nl): - """ Return on-site energy for given orbital '2p',... """ - return self.data['epsilon'][nl] - - - def get_comments(self): - """ Return comments regarding the element file. """ - return self.data['comment'] - - - def get_nr_basis_orbitals(self): - """ Return the total number of basis orbitals (1,4 or 9) """ - return self.data['nr_basis_orbitals'] - - - def get_onsite_energies(self): - """ Return on-site energies for all basis functions. """ - return self.data['onsite_energies'] - - - def get_orbital_types(self): - """ Return list of valence orbital types ['s','px','py',...] """ - no=self.get_nr_basis_orbitals() - return orbital_list[:no] - - - def get_U(self): - return self.data['U'] - - - def get_FWHM(self): - return self.data['FWHM'] - - - def get_Z(self): - return self.data['Z'] - - - def get_C6(self): - return self.data['C6'] - - - def get_p(self): - return self.data['p'] - - - def get_R0(self): - return self.data['R0'] - - - def get_file(self): - """ Return file name where data was read. """ - return self.data['file'] - - - def unl(self,r,nl,der=0): - """ Return unl=Rnl*r. """ - nl=self._transform_orbital(nl) - return self.functions['unl'][nl](r,der=der) - - - def Rnl(self,r,nl,der=0): - """ Return Rnl(r). """ - nl=self._transform_orbital(nl) - return self.functions['Rnl'][nl](r,der=der) - - - def get_Rnl_function(self,nl): - """ Return the actual Rnl function object. """ - nl=self._transform_orbital(nl) - return self.functions['Rnl'][nl] - - - def has_Rnl_functions(self): - """ Does this element has basis function information? """ - return self.functions is not None - - - def effective_potential(self,r): - """ Return Kohn-Sham effective potential. """ - return self.functions['effective_potential'](r) - - - def confinement_potential(self,r): - """ Return the confinement potential used to generate pseudo-atom. """ - return self.functions['confinement_potential'](r) - - - def get_wf_range(self,nl,fractional_limit=1E-7): - """ Return the maximum r for which |R(r)|fractional_limit*wfmax: - return r - - - def write_to_file(self,file): - """ - Write simple element file (.elm) - """ - f=open(file,'w') - for item in self.data: - print>>f, item,'=',self.data[item] - f.close() - - - def update_vdw(self,p,R0): - self.data['p'] = p - self.data['R0'] = R0 - self.data['C6'] = None - - -if __name__=='__main__': - elm=Element('H.elm') - print elm.get_symbol() - print elm.__dict__ diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/elements.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/elements.py deleted file mode 100644 index a8a242c..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/elements.py +++ /dev/null @@ -1,572 +0,0 @@ -from element import Element -from ase import Atoms as ase_Atoms -from hotbit.atoms import Atoms -import numpy as np -import hotbit.auxil as aux -import box.mix as mix -from numpy.linalg.linalg import norm -from ase.units import Hartree,Bohr -from os import environ,path -from weakref import proxy -from copy import copy, deepcopy -from hotbit.atoms import container_magic - - - -class Elements: - def __init__(self,calc,atoms,charge=None): - """ - Read element info from atoms and set up the input files - for reading element data. - - If atoms is ASE.atoms object, convert it into box.Atoms object - """ - elements = calc.get('elements') - if elements!=None: - elements=elements.copy() - - if not isinstance(atoms, ase_Atoms): - raise AssertionError('Given atoms object has to be ase.Atoms type.') - - self._update_atoms(atoms) - - self.calc=proxy(calc) - self.symbols=atoms.get_chemical_symbols() - self.N=len(atoms) - self.name = None - self.positions=None - if charge == None: - self.charge = calc.get_charge() - - self.present=[] - for element in self.symbols: - if element not in self.present: - self.present.append(element) - - # default input files if defined. Override them by the custom - # input files, if specified. - - self.files={} - for key in self.symbols: - self.files[key]=None - - # set customized files - current = path.abspath('.') - default = environ.get('HOTBIT_PARAMETERS') - if elements!=None: - for key in elements: - if key=='rest': continue - file = elements[key] - if not path.isfile(file): - raise RuntimeError('Custom element file "%s" for %s not found.' %(file,key)) - else: - file = path.abspath(file) - self.files[key] = file - - # find element data from default place - if elements==None or elements!=None and 'rest' in elements and elements['rest']=='default': - for key in self.symbols: - if self.files[key]!=None: continue - file = path.join(default,'%s.elm' %key) - if not path.isfile(file): - raise RuntimeError('Default element file "%s" for %s not found.' %(file,key)) - else: - self.files[key] = file - - self._elements_initialization() - self.solved={'ground state':None,'energy':None,'forces':None,'stress':None,'ebs':None,'ecoul':None,'magmoms':None} - - def __len__(self): - return len(self.symbols) - - def __del__(self): - pass - - def get_N(self): - """ Return the number of atoms. """ - return self.N - - def greetings(self): - """ Return documentation for elements from .elm files. """ - txt='%i atoms, %i states, %.1f electrons (%.1f filled states)\n' %(self.N,self.norb,self.electrons,self.electrons/2) - txt+=self.range_message+'\n' - for s in self.present: - el=self.elements[s] - comment=el.get_comment() - if comment is not None and len(comment) > 0: - if type(self.files[s])==type(''): - file=self.files[s] - txt+='Element %s in %s\n' %(s,file) - else: - txt+='Element %s (object given)\n' %s - for line in comment: - txt+=' *'+line.lstrip()+'\n' - if txt=='': - txt='No comments for elements.' - return txt - - def set_atoms(self,atoms): - """ Set the atoms object ready for calculations. """ - self._update_atoms(atoms) - - # determine ranges if they go to infinity - r = self.atoms.get_symmetry_operation_ranges() - Mlarge = 5 # TODO: chek Mlarge to be large enough - self.ranges = [] - s = 'Initial n ranges:' - for i in range(3): - assert r[i,0]<=r[i,1] - if not self.atoms.get_pbc()[i]: assert r[i,0]==r[i,1]==0 - if r[i,0]==-np.Inf: - assert r[i,1]==np.Inf - r[i,:] = [-Mlarge,Mlarge] - elif r[i,0]<-Mlarge: - assert r[i,1]>=Mlarge - r[i,:] = [-Mlarge,Mlarge] - - a,b = int(round(r[i,0])), int(round(r[i,1])) - s += '[%i,%i] ' %(a,b) - self.ranges.append( range(a,b+1) ) - self.range_message = s - - - - def calculation_required(self,atoms,quantities): - """ Return True if quantities are solved for atoms. - - The quantities can be one or more of: 'ground state', 'energy', 'forces', and 'stress'. - 'ebs' or 'ecoul', 'magmoms' - """ - if not isinstance(quantities,(list,tuple)): - quantities=[quantities] - - if type(self.solved['ground state']) == type(None): - return True - - # check that all quantities have been solved for identical atoms - for quantity in quantities: - solved_atoms = self.solved[quantity] - if type(solved_atoms)==type(None): - return True - if solved_atoms!=atoms: - return True - return False - - - def set_solved(self,quantities): - """ Set quantities solved for current atoms. """ - if not isinstance(quantities,(list,tuple)): - quantities=[quantities] - for quantity in quantities: - self.solved[quantity]=self.atoms.copy() - - - def _update_atoms(self,atoms): - """ Update atoms-object, whether it is ase.Atoms or hotbit.Atoms. """ - - if hasattr(atoms,'container'): - self.atoms = atoms.copy() - else: - container = container_magic(atoms) - #print 'cc',container - atoms_cont = Atoms(atoms=atoms,container=container) - self.atoms = atoms_cont.copy() - - - def update_geometry(self,atoms): - ''' - Update all properties related to geometry (calculate once/geometry) - ''' - self.calc.start_timing('geometry') - self._update_atoms(atoms) - # select the symmetry operations n where atoms still interact chemically - nmax = len(self.ranges[0])*len(self.ranges[1])*len(self.ranges[2]) - ijn = np.zeros( (self.N,self.N,nmax),int ) - ijnn = np.zeros( (self.N,self.N),int ) - - # add the n=(0,0,0) first (separately) - self.Rn = [[self.nvector(r=i,ntuple=(0,0,0)) for i in xrange(self.N)]] - self.Rot = [ self.rotation((0,0,0)) ] - self.ntuples = [(0,0,0)] - - for i in xrange(self.N): - for j in xrange(self.N): - dij = np.linalg.norm( self.Rn[0][i]-self.Rn[0][j] ) - if dij < self.calc.ia.hscut[i,j]: - ijn[i,j,ijnn[i,j]] = 0 - ijnn[i,j] += 1 - - - # calculate the distances from unit cell 0 to ALL other possible; select chemically interacting - self.calc.start_timing('operations') - # FIXME!!! This does not consider 'gamma_cut'! - cut2 = self.calc.ia.hscut**2 - n = 1 - for n1 in self.ranges[0]: - for n2 in self.ranges[1]: - for n3 in self.ranges[2]: - nt = (n1,n2,n3) - if nt==(0,0,0): continue - # check that any atom interacts with this unit cell - R = np.array([self.nvector(r=i,ntuple=nt) for i in xrange(self.N)]) - rn = np.array(self.Rn[0]) - - dRt = rn[:, 0].reshape(1,-1)-R[:, 0].reshape(-1,1) - dR = dRt*dRt - dRt = rn[:, 1].reshape(1,-1)-R[:, 1].reshape(-1,1) - dR += dRt*dRt - dRt = rn[:, 2].reshape(1,-1)-R[:, 2].reshape(-1,1) - dR += dRt*dRt - addn = np.any(dR <= cut2) - - if addn: - n += 1 - self.ntuples.append(nt) - self.Rn.append(R) - self.Rot.append( self.rotation(nt) ) - - self.ijn = ijn - self.ijnn = ijnn - self.Rn = np.array(self.Rn) - self.Rot = np.array(self.Rot) - self.calc.stop_timing('operations') - - self.calc.start_timing('displacements') - rijn = np.zeros((len(self.ntuples),self.N,self.N,3)) - dijn = np.zeros((len(self.ntuples),self.N,self.N)) - # Fixme!!! Think about how to use numpy for speedup! - for i in range(self.N): - for j in range(self.N): - rijn[:,i,j,:] = self.Rn[:,j,:] - self.Rn[0,i,:] - dijn[:,i,j] = np.sqrt( (rijn[:,i,j,:]**2).sum(axis=1) ) - self.rijn = rijn - self.dijn = dijn - self.calc.stop_timing('displacements') - - -#=============================================================================== -# # TODO -# def check_too_close_distances(self): -# # FIXME: move this to elements--it's their business; and call in geometry update -# """ If some element pair doesn't have repulsive potential, -# check that they are not too close to each other. """ -# for si in self.present: -# for sj in self.present: -# d = self.calc.el.distance_of_elements(si,sj,mode='minimum') -# if d != None and self.kill_radii[si,sj] != None: -# if d < self.kill_radii[si,sj]: -# raise AssertionError("Atoms with no repulsive potential are too close to each other: %s and %s" % (si, sj)) -#=============================================================================== - - - # TODO: calc.ia should also know the smallest allowed distances between elements - # (maybe because of lacking repulsion or SlaKo tables), this should be checked here! - - self.calc.stop_timing('geometry') - - def get_pbc(self): - return self.atoms.get_pbc() - - def get_transforms(self): - return self.ntuples - - def get_distances(self): - # FIXME!!! Update distances first? - return self.rijn, self.dijn - - - def rotation_of_axes(self,n): - ''' - Return the quantization axis rotation matrix for given symmetry operation. - - @param n: 3-tuple for transformation - ''' - return self.atoms.rotation_of_axes(n) - - - def rotation(self,n): - ''' - Return the quantization axis rotation matrix for given symmetry operation. - - @param n: 3-tuple for transformation - ''' - return self.atoms.rotation(n) - - - def nvector(self,r,ntuple=(0,0,0),r0=np.array([0,0,0]),lst='vec'): - ''' - Return position vector rn-r0, when r is operated by S(n)r=rn. - - Positions should be in atomic units. - @param r: position (array) or atom index (integer) which is operated - @param ntuple: operate on r with S(n) - @param r0: if integer, use atom r0's position as r0 - @param l: list of properties to return, 'vec'=vector, 'hat'=unit vector, 'norm'=norm - ''' - if not isinstance(lst,(list,tuple)): - lst=[lst] - assert not( np.all(r0!=np.array([0,0,0])) and 'tensor' in lst ) - if isinstance(r,int): - r=self.atoms.positions[r] - else: - r=r*Bohr - if isinstance(r0,int): - r0=self.atoms.positions[r0] - else: - r0=r0*Bohr - vec=(self.atoms.transform(r,ntuple)-r0)/Bohr - - ret=[] - for l in lst: - if l=='vec': - ret.append(vec) - elif l=='hat': - norm = np.linalg.norm(vec) - if norm<1E-6: raise AssertionError('Suspiciously short vector') - ret.append( vec/norm ) - elif l=='norm': - ret.append( np.linalg.norm(vec) ) - else: - raise AssertionError('Keyword %s not defined' %l) - - if len(ret)==1: - return ret[0] - else: - return ret - - def set_cutoffs(self,cutoffs): - """ Set the maximum interaction cutoffs (dict of ranges for element pair SlaKo tables). """ - self.cut=cutoffs - self.maxcut=0.0 - for key in self.cut: - self.maxcut=max(self.maxcut,self.cut[key]) - - - def get_name(self): - """ Get the name of the system, e.g. 'benzene'. Default are symbols, 'H2O' """ - if self.name == None: - self.name = mix.parse_name_for_atoms(self.atoms) - return self.name - - def container_info(self): - return repr(self.atoms.container) - - def set_name(self, name): - self.name = name - - - def _elements_initialization(self): - ''' - Initialize element objects, orbital tables etc. - - This initialization is done only once for given set of element info. - Initialization of any geometrical properties is done elsewhere. - ''' - self.elements={} - for symb in self.present: - if symb not in self.files: - raise KeyError('Element file for %s was not defined.' % symb) - if self.files[symb] is None: - raise KeyError('Element file for %s was not defined.' % symb) - if type(self.files[symb])==type(''): - self.elements[symb]=Element(self.files[symb]) - else: - self.elements[symb]=self.files[symb] - self.efree = self.get_free_atoms_energy() - - self.orb=[] - self.pbc = self.atoms.get_pbc() - # index: the number of the orbital - # atomindex: the number of the orbital on the atom - # atom: the number of atom the orbital is centered on - self.atomorb=[] - self.nr_orbitals=[] - self.first_orbitals=[] - self.orbital_atoms=[] - self.norb=0 - ls = ['s','p','d'] - for i,symb in enumerate(self.symbols): - el=self.elements[symb] - atomorb=[] - self.first_orbitals.append(self.norb) - for k,(ao,e) in enumerate(zip(el.get_orbital_types(), - el.get_onsite_energies())): - self.norb+=1 - - self.orbital_atoms.append(i) - angmom = ls.index(ao[0]) - - d = { 'atom': i, - 'symbol': symb, - 'orbital': ao, - 'angmom': angmom, - 'index': self.norb-1, - 'energy': e, - 'atomindex': k } - - if el.has_Rnl_functions(): - Rnl = el.get_Rnl_function(ao) - d['Rnl'] = Rnl - - atomorb.append(d) - - self.nr_orbitals.append(len(atomorb)) - self.atomorb.append(atomorb) - self.orb.extend(atomorb) - - # number of valence electrons on atoms and the total number of electrons - self.nr_of_valences=np.array( [self.elements[symb].get_valence_number() for symb in self.symbols] ) - self.electrons=self.get_valences().sum()-self.charge - - # set list of element pairs - #self.el_pair_list=[] - #for i,si in enumerate(self.present): - # for j,sj in enumerate(self.present): - # self.el_pair_list.append([si,sj]) - - self.atom_orb_indices=[[orb['index'] for orb in self.atomorb[i]] for i in range(self.N)] - - self.atom_orb_indices2=np.zeros((self.N,9),int)-1 - for i,noi in enumerate(self.nr_orbitals): - self.atom_orb_indices2[i,:noi]=self.atom_orb_indices[i] - - - def get_number_of_transformations(self): - ''' - Return the number of symmetry transformations in different directions. - ''' - n = [] - r = self.atoms.get_symmetry_operation_ranges() - for i in range(3): - if r[i,0]==-np.Inf: - n.append(np.Inf) - else: - n.append( int(round(r[i,1]-r[i,0]+1)) ) - return n - - def get_valences(self): - """ Number of valence electrons for atoms. """ - return self.nr_of_valences - - def get_number_of_electrons(self): - """ Total number of electrons in system. """ - return self.electrons - - def get_files(self): - """ Return the dictionary for element input files. """ - return self.files - - def get_present(self): - """ Return list of elements present. """ - return self.present - - def get_positions(self): - return self.atoms.get_positions()/Bohr - - def get_center_of_mass(self): - """ Return the center of mass. """ - return self.atoms.get_center_of_mass() / Bohr - - def get_atomic_numbers(self): - """ Return the atomic numbers. """ - return self.atoms.get_atomic_numbers() - - def get_symbols(self): - return self.symbols - - def symbol(self,i): - return self.symbols[i] - - def get_element(self,i): - ''' - Return the element object of given atom. - - @param i: atom index or element symbol - ''' - if isinstance(i,int): - return self.elements[self.symbols[i]] - else: - return self.elements[i] - - - def orbitals(self,i=None,basis=False,atom=False,indices=False,number=False): - """ Return data related to system orbitals. - - Parameters: - ----------- - Default: return list of orbital-dictionaries for all atoms. - i: return dict of orbitals for given atom (dict incluldes 'atom','symbol','orbital',...) - basis: return the data for basis orbital i. - atom: return atom index for the basis orbital index i. - indices: return orbital indices for atom i. - number: return number of orbitals for atom i. - """ - if i==None: - return self.orb - elif i!=None: - if atom: - return self.orbital_atoms[i] - elif indices: - return self.atom_orb_indices[i] #[orb['index'] for orb in self.atomorb[i]] - elif number: - return self.nr_orbitals[i] #len(self.atomorb[i]) - elif basis: - return self.orb[i] - else: - return self.atomorb[i] - - - def get_nr_orbitals(self): - """ Total number of orbitals. """ - return self.norb - - - def get_property_lists(self,lst=['i']): - ''' - Return lists of atoms' given properties. - - @param lst: 'i'=index; 's'=symbol; 'no'=number of orbitals; 'o1'= first orbital - ''' - def get_list(p): - if p=='i': return range(self.N) - elif p=='s': return self.symbols - elif p=='no': return self.nr_orbitals - elif p=='o1': return self.first_orbitals - else: - raise NotImplementedError('Property not defined') - l = [ get_list(item) for item in lst ] - return zip(*l) - - - def get_cube(self): - """ Return the (orthorhombic) unit cell cube dimensions. """ - cell=abs(self.atoms.get_cell()) - e=1E-10 - if cell[0,1]>e or cell[0,2]>e or cell[1,2]>e: - raise AssertionError('For cube the unit cell has to be orthorombic') - return self.atoms.get_cell().diagonal()/Bohr - - - def get_free_population(self, m): - """ Return the population of the basis state m when the atom - is isolated (a number between zero and two). """ - orb = self.orb[m] - i_element = orb['atom'] - n_el = self.get_valences()[i_element] - atomindex = orb['atomindex'] # atomindex states before this - return max(0, min(2, n_el - 2*atomindex)) - - - def get_free_atoms_energy(self): - ''' - Return the total of free atom energies for the system. - ''' - e = 0.0 - for s in self.symbols: - e += self.elements[s].get_free_atom_energy() - return e - - - def update_vdw(self, vdw_parameters): - for s, par in vdw_parameters.iteritems(): - self.elements[s].update_vdw(*par) diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/environment.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/environment.py deleted file mode 100644 index 06a0cd5..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/environment.py +++ /dev/null @@ -1,86 +0,0 @@ -import numpy as np -from ase.units import Hartree -from weakref import proxy -hbar=0.02342178 - - -class LinearlyPolarizedLaser: - """ Class for laser potential. """ - - def __init__(self,energy,flux,polarization,phase=0.0): - """ Laser parameters. - - electrostatic potential=-E0*sin(omega*t+phase)*dot(polarization,r) - - Parameters: - ----------- - omega: laser energy (in eV) - flux: electric field flux [ E_0=5.3E-9*sqrt(flux) ] - flux ~ 10E8...10E16, ~10E12='normal' laser? - polarization: direction for static polarization (3-array) - phase: phase for laser pulse (do not start from zero) - """ - self.omega=(energy/Hartree)/hbar # hbar*omega=energy - self.E0=np.sqrt(flux)*5.33802445585E-09 - self.pol=polarization/np.linalg.norm(polarization) - self.phase=phase - - - - def __call__(self,r,t): - """ Return the electrostatic potential. - - Parameters: - ----------- - r: position in Bohrs - t: time in atomic units (~fs) - """ - return -self.E0*np.sin(self.omega*t+self.phase)*np.dot(r,self.pol) - - - - -class Environment: - def __init__(self,calc): - self.t=0.0 - self.phis=[] - self.calc=proxy(calc) - - def __del__(self): - pass - - def propagate_time(self,dt): - """ Increase time by dt (dt in atomic units) """ - self.t+=dt - - - def add_phi(self,phi): - """ Add external electrostatic potential function in atomic units. - - phi=phi(r,t) is any function, where r is position (Bohrs) - and t time (atomic units, ~fs) - """ - self.phis.append(phi) - - - def phi(self,r): - """ Return external electrostatic potential. - - Current internal environment time is used. - - Parameters: - ----------- - r: position (Bohrs) or atom index; - index if r is an integer - """ - if isinstance(r,int): - r=self.calc.el.nvector(r) - pot=0.0 - for f in self.phis: - pot+=f(r,self.t) - return pot - - - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/grids.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/grids.py deleted file mode 100644 index d81d627..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/grids.py +++ /dev/null @@ -1,278 +0,0 @@ -import numpy as np -from weakref import proxy -from ase.units import Bohr, Hartree -from hotbit.analysis.wavefunctions import angular -from math import sqrt -from scipy.special import erf - - -class Grids: - def __init__(self,calc,h,cutoff=3.0): - """ - Initialize grids. - - parameters: - =========== - h: grid spacing in Angstroms - pad: True for padded edges (grid points at opposite edges - have the same value) - cutoff: cutoff for atomic orbitals - """ - self.calc = proxy(calc) - self.el = proxy(self.calc.el) - self.h = h/Bohr - self.cutoff = cutoff/Bohr # cutoff for atomic orbitals - self.clip = 100.0 #clip wfs - self.calc.start_timing('init grid') - - - self.L = self.el.get_cube() - self.N = np.array( np.round(self.L/h),int ) - self.dr = self.L/(self.N-1) - - self.grid=[] - for i in range(3): - self.grid.append( np.linspace(0,self.L[i],self.N[i]) ) - - - self.dV = np.prod(self.dr) - self.ng = np.prod(self.N) - - # partial grids (where atomic orbitals are first put) - self.pN = [] - self.pL = [] - for i in range(3): - N = int( np.round(self.cutoff*2/self.dr[i]) ) - if np.mod(N,2)==0: - N+=1 - self.pN.append(N) - self.pL.append((N-1)*self.dr[i]) - - self.pL = np.array(self.pL) - self.pgrid = [] - for i in range(3): - self.pgrid.append( [p*self.dr[i]-self.pL[i]/2 for p in xrange(self.pN[i])] ) - - - self._all_basis_orbitals_to_partial_grid() - self.calc.stop_timing('init grid') - - - def _return_array(self,a,pad): - a=a.copy() - a = a.real.clip(-self.clip,self.clip) + 1j*a.imag.clip(-self.clip,self.clip) - if np.all(abs(a.imag)<1E-10): - a=a.real - if pad: - return a - else: - return a[:-1,:-1,:-1] - - - def _atomic_orbital_to_partial_grid(self,symbol,otype): - """ - Put atomic orbital on a grid. - - It looks like this; atom is right in the middle of the grid - (number of grid points is odd in each direction) - - |----------v----------| - | | | | | - |---------------------| - | | | | | - |----------X----------| - | | | | | - |---------------------| - | | | | | - |----------^----------- - - - parameters: - =========== - symbol: atom symbol - otype: orbital type ('s','px','py',...) - """ - el = self.calc.el.elements[symbol] - Rnl = el.get_Rnl_function(otype) - range = el.get_wf_range(otype,fractional_limit=1E-5) - - wf = np.zeros(self.pN) - for i in xrange(self.pN[0]): - for j in xrange(self.pN[1]): - for k in xrange(self.pN[2]): - r = np.array( [self.pgrid[0][i],self.pgrid[1][j],self.pgrid[2][k]] ) - d = sqrt( r[0]**2+r[1]**2+r[2]**2 ) - if d>self.cutoff or d>range: - continue - else: - rnl = Rnl(d) - if abs(rnl)>1E-7: - wf[i,j,k] = rnl*angular(r,otype) - return wf - - - def _all_basis_orbitals_to_partial_grid(self): - """ - Put all atomic orbitals into partial grids -> e.g. patomic['C']['px'] - """ - self.calc.start_timing('atomic orbitals to grid') - self.patomic={} - for symb in self.el.present: - el = self.el.elements[symb] - symbol = el.get_symbol() - self.patomic[symbol] = {} - for otype in el.get_orbital_types(): - wf = self._atomic_orbital_to_partial_grid(symbol,otype) - self.patomic[symbol][otype] = wf - self.calc.stop_timing('atomic orbitals to grid') - - - - def get_grid_basis_orbital(self,I,otype,k=0,pad=True): - """ - Return basis orbital on grid. - - parameters: - =========== - I: atom index - otype: orbital type ('s','px','py',...) - k: k-point index (basis functions are really the extended - Bloch functions for periodic systems) - pad: padded edges in the array - """ - symbol = self.el.symbols[I] - pwf = self.patomic[symbol][otype] - wf = np.zeros(self.N) - phases = self.calc.ia.get_phases()[:,k] - for ni,n in enumerate(self.el.ntuples): - ri = self.el.nvector(I,n) - inside = True - # check first roughly that basis reaches the inside of cell - for i in range(3): - if ri[i]<-self.cutoff or self.L[i]+self.cutoff grid point N - N = np.array( np.round(ri/self.dr),int ) - a,b = [],[] - - for i in range(3): - lo = N[i]-(self.pN[i]-1)/2 - hi = N[i]+(self.pN[i]-1)/2 - # these are indices - a1,a2 = max(0,lo), min(self.N[i]-1,hi) - an = a2-a1 - b1 = max(0,-lo) - b2 = b1 + an - a.append( slice(a1,a2+1) ) - b.append( slice(b1,b2+1) ) - if b1>b2 or a1>a2: - inside = False - if inside: - wf[a[0],a[1],a[2]] = wf[a[0],a[1],a[2]] + phases[ni]*pwf[b[0],b[1],b[2]] - return self._return_array(wf,pad) - - - - def get_grid_wf(self,a,k=0,pad=True): - """ - Return eigenfunction on a grid. - - parameters: - =========== - a: state (band) index - k: k-vector index - pad: padded edges - """ - wf = self.calc.st.wf - - if np.all( abs(self.calc.ia.get_phases()[:,k]-1)<1E-10 ): - gwf = np.zeros(self.N) #TODO: complex - else: - gwf = np.zeros(self.N,complex) - - for mu,orb in enumerate(self.el.orbitals()): - I,otype = orb['atom'],orb['orbital'] - if abs(wf[k,a,mu])**2>1E-13: - gwf += wf[k,a,mu]*self.get_grid_basis_orbital(I,otype,k) - return self._return_array(gwf,pad) - - - def get_grid_wf_density(self,a,k=0,pad=True): - """ - Return eigenfunction density. - - Density is not normalized; accurate quantitative analysis - on this density are best avoided. - - parameters: - =========== - a: state (band) index - k: k-vector index - pad: padded edges - """ - wf = self.get_grid_wf(a,k,pad=True) - return self._return_array(wf*wf.conjugate(),pad) - - - def get_grid_density(self,pad): - """ - Return electron density on grid. - - Do not perform accurate analysis on this density. - Integrated density differs from the total number of electrons. - Bader analysis will be inaccurate. - - parameters: - ----------- - pad: padded edges - """ - rho = np.zeros(tuple(self.N)) - for k,wk in enumerate(self.calc.st.wk): - for a,f in enumerate(self.calc.st.f[k,:]): - if f<1E-6: break - rho = rho + wk*self.get_grid_wf_density(a,k,pad=True) - return self._return_array(rho,pad) - - - def get_grid_LDOS(self,bias=None,window=None,pad=True): - """ - Return electron density over selected states around the Fermi-level. - - parameters: - ----------- - bias: bias voltage (eV) with respect to Fermi-level. - Negative means probing occupied states. - window: 2-tuple for lower and upper bounds wrt. Fermi-level - pad: padded edges - """ - assert not (bias==None and window==None) - if bias!=None: - bias/=Hartree - else: - window = (window[0]/Hartree,window[1]/Hartree) - - rho = np.zeros(tuple(self.N)) - for k,wk in enumerate(self.calc.st.wk): - for a,f in enumerate(self.calc.st.f[k,:]): - e = self.calc.st.e[k,a] - # select occupation weight from the applied scheme - if window!=None: - if window[0]<=e<=window[1]: - w_occu=1.0 - else: - w_occu=0.0 - else: - if bias<0.0: # probe occupied states - w_occu=f/2*(1-self.calc.st.occu.fermi_function(e-bias)) - elif bias>0.0: # probe unoccupied states - w_occu=(1-f/2)*self.calc.st.occu.fermi_function(e-bias) - else: # no bias, no current - w_occu=0.0 - weight=wk*w_occu*2 - if weight<1E-4: - continue - rho = rho + weight*self.get_grid_wf_density(a,k,pad=True) - return self._return_array(rho,pad) - \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/interactions.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/interactions.py deleted file mode 100644 index dd74466..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/interactions.py +++ /dev/null @@ -1,708 +0,0 @@ -# Copyright (C) 2008 NSC Jyvaskyla -# Please see the accompanying LICENSE file for further information. - -from box import mix -import numpy as np -from hotbit import auxil -from box.interpolation import MultipleSplineFunction -from weakref import proxy -from copy import copy -from os import path -from hotbit.io import read_HS - -from _hotbit import fast_slako_transformations - -dot=np.dot -array=np.array -norm=np.linalg.norm -outer=np.outer -zeros=np.zeros - -aux={'s':0,'p':1,'d':2} -itypes={'ss':['s'],'sp':['s'],'ps':['s'],'sd':['s'],'ds':['s'], - 'pp':['s','p'],'pd':['s','p'],'dp':['s','p'],'dd':['s','p','d']} -integrals={'dds':0,'ddp':1,'ddd':2,'pds':3,'pdp':4,'pps':5,'ppp':6,\ - 'sds':7,'sps':8,'sss':9,'dps':10,'dpp':11,'dss':12,'pss':13} - - - - - -class Interactions: - - def __init__(self,calc): - """ - Set up the input files for interactions. - - If tables==None, use default tables. - If tables['rest']=='default' use default interactions for the ones not given in tables. - - """ - from os import environ - from os.path import isfile - - tables = copy(calc.get('tables')) - present = calc.el.get_present() - default = environ.get('HOTBIT_PARAMETERS') -# current = path.abspath('.') - self.nullpar = path.join(default,'null.par') - - files={} - for k1 in present: - for k2 in present: - files[k1+k2] = None - - # set customized files - if tables!=None: - for key in tables: - if key=='rest': continue - e1,e2 = auxil.separate_symbols(key) - file = tables[key] - if file==None: - file = self.nullpar - #if file[-4:]!='.par': - # file+='.par' - if not isfile(file): - raise RuntimeError('Custom parameter file "%s" for %s-%s interaction not found.' %(file,e1,e2)) - file = path.abspath(file) - files[e1+e2] = file - if not e2+e1 in tables: - files[e2+e1] = file - - # set interactions from default place - if tables==None or tables!=None and 'rest' in tables and tables['rest']=='default': - for e1 in present: - for e2 in present: - if files[e1+e2]!=None: - continue - def12 = path.join(default,'%s_%s.par' %(e1,e2)) - def21 = path.join(default,'%s_%s.par' %(e2,e1)) - - if isfile(def12): - file = def12 - elif isfile(def21): - file = def21 - else: - raise RuntimeError('Default parameter files "%s" or "%s" for %s-%s interaction not found.' %(def12,def21,e1,e2)) - file = path.abspath(file) - files[e1+e2] = file - files[e2+e1] = file - - self.files=files - self.calc=proxy(calc) - self.present=present - self.max_cut = 0.0 # maximum interaction range in Bohrs - self.read_tables() - self.first=True - - def __del__(self): - pass - - def get_files(self): - """ Return the list of Slater-Koster table files.""" - return self.files - - def get_cutoffs(self): - """ Return element pair cutoff dictionary. """ - return self.cut - - def greetings(self): - """ Return the interaction specifications """ - txt='Interactions:\n' - for i,s1 in enumerate(self.present): - for s2 in self.present: - file = self.files[s1+s2] - if file==None: - txt+=' %s%s: None\n' %(s1,s2) - else: - txt+=' %s%s in %s\n' %(s1,s2,file) - doc=mix.find_value(file,'slako_comment',fmt='strings',default=['no slako doc']) - for line in doc: - txt+=' *'+line.lstrip()+'\n' - return txt - - - def read_tables(self): - """ - Read par-file tables. Files are tabulated with |ket> having >= angular momentum, - so one has to copy values for interaction the other way round. - """ - self.h={} - self.s={} - self.cut={} - self.maxh={} -# self.kill_radii={} - - for si in self.present: - for sj in self.present: - if self.files[si+sj] is None: - raise RuntimeError('No parametrization specified for %s-%s ' - 'interaction.' % ( si, sj )) - if self.files[sj+si] is None: - raise RuntimeError('No parametrization specified for %s-%s ' - 'interaction.' % ( sj, si )) - x_ij, table_ij = read_HS(self.files[si+sj], si, sj) - self.cut[si+sj] = x_ij[-1] - x_ji, table_ji = read_HS(self.files[sj+si], sj, si) - self.cut[sj+si] = x_ji[-1] - self.max_cut=max(self.max_cut,self.cut[si+sj]) - self.maxh[si+sj]=max( [max(np.abs(table_ij[:,i])) for i in range(1,11)] ) - - ei, ej=self.calc.el.elements[si], self.calc.el.elements[sj] - valence_i, valence_j=ei.get_valence_orbitals(), ej.get_valence_orbitals() - - pair=si+sj - self.h[pair]=MultipleSplineFunction(x_ij) - self.s[pair]=MultipleSplineFunction(x_ji) - for vi in valence_i: - for vj in valence_j: - li, lj=vi[1], vj[1] - # for given valence orbitals, go through all possible integral types (sigma,pi,...) - for itype in itypes[li+lj]: - table='%s(%s)-%s(%s)-%s' %(si,li,sj,lj,itype) - short='%s%s%s' %(li,lj,itype) - # self.h['C(p)-H(s)-sigma']=... - if short[0:2]=='ps' or short[0:2]=='ds' or short[0:2]=='dp': - # this is tabulated in other table; switch order -> parity factor - parity=(-1)**( aux[li]+aux[lj] ) - index=integrals[short[1]+short[0]+short[2]] - self.h[pair].add_function(table_ji[:,index]*parity,table,integrals[short]) - self.s[pair].add_function(table_ji[:,index+10]*parity,table,integrals[short]) - else: - index=integrals[short] - self.h[pair].add_function(table_ij[:,index],table,integrals[short]) - self.s[pair].add_function(table_ij[:,index+10],table,integrals[short]) - - # cutoffs for atom pair indices - N = self.calc.el.N - self.hscut=np.zeros((N,N),float) - for i,si in enumerate(self.calc.el.symbols): - for j,sj in enumerate(self.calc.el.symbols): - self.hscut[i,j]=self.cut[si+sj] - self.calc.el.set_cutoffs(self.cut) - - - def get_tables(self, si, sj): - return self.h[si+sj], self.s[si+sj] - - - def plot_table(self,e1,e2,der=0): - """ Plot SlaKo table for given elements. """ - import pylab as pl - R=np.linspace(0,self.cut[e1+e2],1000) - n=self.h[e1+e2].get_number_of_functions() - nx=max(n/2, 1) - ny=n/nx - for i in range(n): - pl.subplot(nx,ny,i+1) - pl.plot(R,[self.h[e1+e2](r,der=der)[i] for r in R],label='H') - pl.plot(R,[self.s[e1+e2](r,der=der)[i] for r in R],label='S') - pl.xlim(0,R[-1]) - pl.ylim(-self.maxh[e1+e2],self.maxh[e1+e2]) - #pl.title('%s-%s integral %s (der=%i)' %(e1,e2,self.integrals[i],der)) - pl.title('%s-%s (der=%i)' %(e1,e2,der)) - pl.xlabel('r (Bohr)') - pl.ylabel('H (Hartree) and S') - pl.show() - - - def rotation_transformation(self,n): - ''' - Return the transpose of 9x9 rotation transformation matrix for given symmetry operation. - - | 1 0 0 0 0 0 0 0 0 | s } s-orbital - | 0 ca -sa 0 0 0 0 0 0 | px - | 0 sa ca 0 0 0 0 0 0 | py } p-orbitals ca = cos(a) - | 0 0 0 1 0 0 0 0 0 | pz sa = sin(a) - D= | 0 0 0 0 c2a 0 0 s2a 0 | dxy c2a = cos(2a) - | 0 0 0 0 0 ca sa 0 0 | dyz s2a = sin(2a) - | 0 0 0 0 0 -sa ca 0 0 | dzx } d-orbitals - | 0 0 0 0 -s2a 0 0 c2a 0 | dx2-y2 - | 0 0 0 0 0 0 0 0 1 | d3z2-r2 - - @param n: 3-tuple of symmetry transformation - ''' - R = self.calc.el.rotation(n) - - if np.any(np.array(self.calc.el.get_property_lists(['no']))>4) and abs(R[2,2]-1)>1E-12: - if abs(R[2,2]+1)<1E-12: - # only xy-plane reflection FIXME!! (this was sheer lazyness; implement the general rotation!) - D = np.eye(9) - D[3,3] = -1 - D[5,5] = -1 - D[6,6] = -1 - return D - else: - raise NotImplementedError('General non-z-axis rotation not implemented for d-orbitals') - - if np.all(abs(R.diagonal()-1)<1E-12): #no rotation - return np.eye(9) - - ca, sa = R[0,0], -R[0,1] - c2a, s2a = 2*ca**2-1, 2*sa*ca - - D = np.diag((1.0,ca,ca,1.0,c2a,ca,ca,c2a,1.0)) - - #D[1,2] = -sa - #D[2,1] = sa - #D[5,6] = sa - #D[6,5] = -sa - #D[4,7] = s2a - #D[7,4] = -s2a - - D[1,2] = sa - D[2,1] = -sa - D[5,6] = -sa - D[6,5] = sa - D[4,7] = -s2a - D[7,4] = s2a - - #print R - D[1:4,1:4] = R[:,:].transpose() - return D.transpose() - - - def get_phases(self): - """ Return phases for symmetry operations and k-points. - - phases[n,k] - """ - return np.array(self.phases) - - - def get_matrices(self, kpts=None): - """ Hamiltonian and overlap matrices. """ - timing = False - el = self.calc.el - states = self.calc.st - start = self.calc.start_timing - stop = self.calc.stop_timing - seps = self.calc.get('sepsilon') - start('matrix construction') - orbs=el.orbitals() - norb=len(orbs) - - if kpts is None: - nk = states.nk - ks = states.k - else: - ks = np.asarray(kpts) - ks.shape = (-1, 3) - nk = ks.shape[0] - - H0 = np.zeros((nk,norb,norb),complex) - S = np.zeros((nk,norb,norb),complex) - dH0 = np.zeros((nk,norb,norb,3),complex) - dS = np.zeros((nk,norb,norb,3),complex) - -# orbitals=[[orb['orbital'] for orb in el.orbitals(i)] -# for i in range(len(el))] -# orbindex=[el.orbitals(i,indices=True) -# for i in range(len(el))] - h, s, dh, ds = zeros((14,)), zeros((14,)), zeros((14,3)), zeros((14,3)) - - phases = [] - DTn = [] - Rot = [] - for n in range(len(el.ntuples)): - nt = el.ntuples[n] - phases.append( np.array([np.exp(1j*np.dot(nt,k)) - for k in ks]) ) - DTn.append( self.rotation_transformation(nt) ) - Rot.append( self.calc.el.rotation(nt) ) - self.phases = phases - - lst = el.get_property_lists(['i','s','no','o1']) - Rijn, dijn = self.calc.el.get_distances() - for i,si,noi,o1i in lst: - a, b = o1i, o1i+noi - # on-site energies only for n==0 - for orb in el.orbitals(i): - ind=orb['index'] - H0[:,ind,ind] = orb['energy'] - S[:,ind,ind] = 1.0 + seps - for j,sj,noj,o1j in lst[i:]: - c, d = o1j, o1j+noj - htable = self.h[si+sj] - stable = self.s[si+sj] - ij_interact = False - r1, r2= htable.get_range() - - for n, (rij,dij) in enumerate(zip(Rijn[:,i,j],dijn[:,i,j])): - if i==j and n==0: - continue - nt = el.ntuples[n] - h.fill(0) - s.fill(0) - dh.fill(0) - ds.fill(0) - - rijh = rij/dij - if dij<0.1: - print nt - raise AssertionError('Distance between atoms %i and %i is only %.4f Bohr' %(i,j,dij) ) - assert dij>0.1 - if not r1<=dij<=r2: - continue - ij_interact = True - - # interpolate Slater-Koster tables and derivatives - if timing: start('splint+SlaKo+DH') - hij, dhij = htable(dij) - sij, dsij = stable(dij) - - indices = htable.get_indices() - h[indices], s[indices] = hij, sij - dh[indices], ds[indices] = outer(dhij,rijh), outer(dsij,rijh) - - # make the Slater-Koster transformations -# obsi, obsj=orbindex[i], orbindex[j] - ht, st, dht, dst = \ - fast_slako_transformations(rijh,dij,noi,noj,h,s,dh,ds) - - # Here we do the MEL transformation; - # H'_ij = sum_k H_ik * D_kj^T ( |j> = sum_k D_jk |k> ) - DT = DTn[n] - ht = dot( ht,DT[0:noj,0:noj] ) - st = dot( st,DT[0:noj,0:noj] ) - dht = dot( dht.transpose((2,0,1)),DT[0:noj,0:noj] ).transpose((1,2,0)) - dst = dot( dst.transpose((2,0,1)),DT[0:noj,0:noj] ).transpose((1,2,0)) - if timing: stop('splint+SlaKo+DH') - - if timing: start('k-points') - phase = phases[n] - hblock = outer(phase,ht.flatten()).reshape(nk,noi,noj) - sblock = outer(phase,st.flatten()).reshape(nk,noi,noj) - dhblock = outer(phase,-dht.flatten()).reshape(nk,noi,noj,3) - dsblock = outer(phase,-dst.flatten()).reshape(nk,noi,noj,3) - - H0[ :,a:b,c:d] += hblock - S[ :,a:b,c:d] += sblock - dH0[:,a:b,c:d,:] += dhblock - dS[ :,a:b,c:d,:] += dsblock - if timing: stop('k-points') - - if i!=j and ij_interact: - # construct the other derivatives wrt. atom j. - Rot = self.calc.el.Rot[n] - dht2 = dot( dht,Rot ) - dst2 = dot( dst,Rot ) - dh2block = outer(phase,dht2.flatten()).reshape(nk,noi,noj,3) - ds2block = outer(phase,dst2.flatten()).reshape(nk,noi,noj,3) - dH0[:,c:d,a:b,:] += dh2block.transpose((0,2,1,3)).conjugate() - dS[ :,c:d,a:b,:] += ds2block.transpose((0,2,1,3)).conjugate() - - if i!=j and ij_interact: - if timing: start('symm') - # Hermitian (and anti-Hermitian) conjugates; - # only if matrix block non-zero - # ( H(k) and S(k) can be (anti)symmetrized as a whole ) - # TODO: symmetrization should be done afterwards - H0[ :,c:d,a:b] = H0[ :,a:b,c:d].transpose((0,2,1)).conjugate() - S[ :,c:d,a:b] = S[ :,a:b,c:d].transpose((0,2,1)).conjugate() - if timing: stop('symm') - - if kpts is None: - self.H0, self.S, self.dH0, self.dS = H0, S, dH0, dS - - if self.first: - nonzero = sum( abs(S[0].flatten())>1E-15 ) - self.calc.out('Hamiltonian ~%.3f %% filled.' %(nonzero*100.0/norb**2) ) - self.first=False - - stop('matrix construction') - - return H0, S, dH0, dS - - - def get_cutoff(self): - """ Maximum cutoff. """ - return self.max_cut - - -def simple_table_notation(table): - a,b,i=table[2:].split('-') - return a[-2]+b[-2]+i[0] - - - -s3=np.sqrt(3.0) - -def slako_transformations(rhat,dist,noi,noj,h,s,dh,ds): - """ - Apply Slater-Koster transformation rules to orbitals iorbs and orbitals jorbs, - where rhat is vector i->j and table gives the values for given tabulated - matrix elements. Convention: orbital name starts with s,p,d,... - """ - l,m,n=rhat - ll,mm,nn=rhat**2 - dl=(np.array([1,0,0])-l*rhat)/dist - dm=(np.array([0,1,0])-m*rhat)/dist - dn=(np.array([0,0,1])-n*rhat)/dist - dll, dmm, dnn = 2*l*dl, 2*m*dm, 2*n*dn - - mat=np.zeros((9,9,14)) - ind=np.zeros((9,9,14),dtype=int) - der=np.zeros((9,9,14,3)) - cnt=np.zeros((9,9),dtype=int)+1 - cnt[1:,1:]=2 - cnt[4:,4:]=3 - - ht=np.zeros((noi,noj)) - st=np.zeros((noi,noj)) - dht=np.zeros((noi,noj,3)) - dst=np.zeros((noi,noj,3)) - mxorb=max(noi,noj) - - mat[0,0,0]=1 #ss - der[0,0,0]=0 - ind[0,0,0]=9 - - if mxorb>=2: #sp - mat[0,1,0]=l - der[0,1,0,:]=dl - ind[0,1,0]=8 - - mat[0,2,0]=m - der[0,2,0,:]=dm - ind[0,2,0]=8 - - mat[0,3,0]=n - der[0,3,0,:]=dn - ind[0,3,0]=8 - - if mxorb>=5: #sd - mat[0,4,0]=s3*l*m - der[0,4,0,:]=s3*(dl*m+l*dm) - ind[0,4,0]=7 - - mat[0,5,0]=s3*m*n - der[0,5,0,:]=s3*(dm*n+m*dn) - ind[0,5,0]=7 - - mat[0,6,0]=s3*n*l - der[0,6,0,:]=s3*(dn*l+n*dl) - ind[0,6,0]=7 - - mat[0,7,0]=0.5*s3*(ll-mm) - der[0,7,0,:]=0.5*s3*(dll-dmm) - ind[0,7,0]=7 - - mat[0,8,0]=nn-0.5*(ll+mm) - der[0,8,0,:]=dnn-0.5*(dll+dmm) - ind[0,8,0]=7 - - if mxorb>=2: #pp - mat[1,1,0:2]=[ll, 1-ll] - der[1,1,0:2,:]=[dll, -dll] - ind[1,1,0:2]=[5,6] - - mat[1,2,0:2]=[l*m, -l*m] - der[1,2,0:2,:]=[dl*m+l*dm, -(dl*m+l*dm)] - ind[1,2,0:2]=[5,6] - - mat[1,3,0:2]=[l*n, -l*n] - der[1,3,0:2,:]=[dl*n+l*dn, -(dl*n+l*dn)] - ind[1,3,0:2]=[5,6] - - if mxorb>=5: #pd - mat[1,4,0:2]=[s3*ll*m, m*(1-2*ll)] - der[1,4,0:2,:]=[s3*(dll*m+ll*dm), dm*(1-2*ll)+m*(-2*dll)] - ind[1,4,0:2]=[3,4] - - mat[1,5,0:2]=[s3*l*m*n, -2*l*m*n] - der[1,5,0:2,:]=[s3*(dl*m*n+l*dm*n+l*m*dn), -2*(dl*m*n+l*dm*n+l*m*dn)] - ind[1,5,0:2]=[3,4] - - mat[1,6,0:2]=[s3*ll*n, n*(1-2*ll)] - der[1,6,0:2,:]=[s3*(dll*n+ll*dn), dn*(1-2*ll)+n*(-2*dll)] - ind[1,6,0:2]=[3,4] - - mat[1,7,0:2]=[0.5*s3*l*(ll-mm), l*(1-ll+mm)] - der[1,7,0:2,:]=[0.5*s3*(dl*(ll-mm)+l*(dll-dmm)), dl*(1-ll+mm)+l*(-dll+dmm)] - ind[1,7,0:2]=[3,4] - - mat[1,8,0:2]=[l*(nn-0.5*(ll+mm)), -s3*l*nn] - der[1,8,0:2,:]=[dl*(nn-0.5*(ll+mm))+l*(dnn-0.5*(dll+dmm)), -s3*(dl*nn+l*dnn)] - ind[1,8,0:2]=[3,4] - - if mxorb>=2: - mat[2,2,0:2]=[mm, 1-mm] - der[2,2,0:2,:]=[dmm, -dmm] - ind[2,2,0:2]=[5,6] - - mat[2,3,0:2]=[m*n, -m*n] - der[2,3,0:2,:]=[dm*n+m*dn, -(dm*n+m*dn)] - ind[2,3,0:2]=[5,6] - - if mxorb>=5: - mat[2,4,0:2]=[s3*mm*l, l*(1-2*mm)] - der[2,4,0:2,:]=[s3*(dmm*l+mm*dl), dl*(1-2*mm)+l*(-2*dmm)] - ind[2,4,0:2]=[3,4] - - mat[2,5,0:2]=[s3*mm*n, n*(1-2*mm)] - der[2,5,0:2,:]=[s3*(dmm*n+mm*dn), dn*(1-2*mm)+n*(-2*dmm)] - ind[2,5,0:2]=[3,4] - - mat[2,6,0:2]=[s3*m*n*l, -2*m*n*l] - der[2,6,0:2,:]=[s3*(dm*n*l+m*dn*l+m*n*dl), -2*(dm*n*l+m*dn*l+m*n*dl)] - ind[2,6,0:2]=[3,4] - - mat[2,7,0:2]=[0.5*s3*m*(ll-mm), -m*(1+ll-mm)] - der[2,7,0:2,:]=[0.5*s3*(dm*(ll-mm)+m*(dll-dmm)), -(dm*(1+ll-mm)+m*(dll-dmm))] - ind[2,7,0:2]=[3,4] - - mat[2,8,0:2]=[m*(nn-0.5*(ll+mm)), -s3*m*nn] - der[2,8,0:2,:]=[dm*(nn-0.5*(ll+mm))+m*(dnn-0.5*(dll+dmm)), -s3*(dm*nn+m*dnn)] - ind[2,8,0:2]=[3,4] - - if mxorb>=2: - mat[3,3,0:2]=[nn, 1-nn] - der[3,3,0:2,:]=[dnn, -dnn] - ind[3,3,0:2]=[5,6] - - if mxorb>=5: - mat[3,4,0:2]=[s3*l*m*n, -2*m*n*l] - der[3,4,0:2,:]=[s3*(dl*m*n+l*dm*n+l*m*dn), -2*(dm*n*l+m*dn*l+m*n*dl)] - ind[3,4,0:2]=[3,4] - - mat[3,5,0:2]=[s3*nn*m, m*(1-2*nn)] - der[3,5,0:2,:]=[s3*(dnn*m+nn*dm), dm*(1-2*nn)+m*(-2*dnn)] - ind[3,5,0:2]=[3,4] - - mat[3,6,0:2]=[s3*nn*l, l*(1-2*nn)] - der[3,6,0:2,:]=[s3*(dnn*l+nn*dl), dl*(1-2*nn)+l*(-2*dnn)] - ind[3,6,0:2]=[3,4] - - mat[3,7,0:2]=[0.5*s3*n*(ll-mm), -n*(ll-mm)] - der[3,7,0:2,:]=[0.5*s3*(dn*(ll-mm)+n*(dll-dmm)), -(dn*(ll-mm)+n*(dll-dmm))] - ind[3,7,0:2]=[3,4] - - mat[3,8,0:2]=[n*(nn-0.5*(ll+mm)), s3*n*(ll+mm)] - der[3,8,0:2,:]=[dn*(nn-0.5*(ll+mm))+n*(dnn-0.5*(dll+dmm)), s3*(dn*(ll+mm)+n*(dll+dmm))] - ind[3,8,0:2]=[3,4] - - if mxorb>=5: - mat[4,4,0:3]=[3*ll*mm, ll+mm-4*ll*mm, nn+ll*mm] - der[4,4,0:3,:]=[3*(dll*mm+ll*dmm), dll+dmm-4*(dll*mm+ll*dmm), dnn+(dll*mm+ll*dmm)] - ind[4,4,0:3]=[0,1,2] - - mat[4,5,0:3]= [3*l*mm*n, l*n*(1-4*mm), l*n*(mm-1)] - der[4,5,0:3,:]= [3*(dl*mm*n+l*dmm*n+l*mm*dn), dl*n*(1-4*mm)+l*dn*(1-4*mm)+l*n*(-4*dmm), dl*n*(mm-1)+l*dn*(mm-1)+l*n*(dmm)] - ind[4,5,0:3]=[0,1,2] - - mat[4,6,0:3]=[3*ll*m*n, m*n*(1-4*ll), m*n*(ll-1)] - der[4,6,0:3,:]=[3*(dll*m*n+ll*dm*n+ll*m*dn), dm*n*(1-4*ll)+m*dn*(1-4*ll)+m*n*(-4*dll), dm*n*(ll-1)+m*dn*(ll-1)+m*n*(dll)] - ind[4,6,0:3]=[0,1,2] - - mat[4,7,0:3]=[1.5*l*m*(ll-mm), 2*l*m*(mm-ll), 0.5*l*m*(ll-mm)] - der[4,7,0:3,:]=[1.5*(dl*m*(ll-mm)+l*dm*(ll-mm)+l*m*(dll-dmm)),\ - 2*(dl*m*(mm-ll)+l*dm*(mm-ll)+l*m*(dmm-dll)),\ - 0.5*(dl*m*(ll-mm)+l*dm*(ll-mm)+l*m*(dll-dmm))] - ind[4,7,0:3]=[0,1,2] - - mat[4,8,0:3]=[s3*l*m*(nn-0.5*(ll+mm)), - 2*s3*l*m*nn, 0.5*s3*l*m*(1+nn)] - der[4,8,0:3,:]=[s3*( dl*m*(nn-0.5*(ll+mm))+l*dm*(nn-0.5*(ll+mm))+l*m*(dnn-0.5*(dll+dmm)) ),\ - -2*s3*(dl*m*nn+l*dm*nn+l*m*dnn),\ - 0.5*s3*( dl*m*(1+nn)+l*dm*(1+nn)+l*m*(dnn) )] - ind[4,8,0:3]=[0,1,2] - - mat[5,5,0:3]=[3*mm*nn, (mm+nn-4*mm*nn), (ll+mm*nn)] - der[5,5,0:3,:]=[3*(dmm*nn+mm*dnn), (dmm+dnn-4*(dmm*nn+mm*dnn)), (dll+dmm*nn+mm*dnn)] - ind[5,5,0:3]=[0,1,2] - - mat[5,6,0:3]=[3*m*nn*l, m*l*(1-4*nn), m*l*(nn-1)] - der[5,6,0:3,:]=[3*(dm*nn*l+m*dnn*l+m*nn*dl),\ - dm*l*(1-4*nn)+m*dl*(1-4*nn)+m*l*(-4*dnn),\ - dm*l*(nn-1)+m*dl*(nn-1)+m*l*(dnn)] - ind[5,6,0:3]=[0,1,2] - - mat[5,7,0:3]=[1.5*m*n*(ll-mm), - m*n*(1+2*(ll-mm)), m*n*(1+0.5*(ll-mm))] - der[5,7,0:3,:]=[1.5*( dm*n*(ll-mm)+m*dn*(ll-mm)+m*n*(dll-dmm) ),\ - - ( dm*n*(1+2*(ll-mm))+m*dn*(1+2*(ll-mm))+m*n*(2*dll-2*dmm) ),\ - dm*n*(1+0.5*(ll-mm))+m*dn*(1+0.5*(ll-mm))+m*n*(0.5*(dll-dmm))] - ind[5,7,0:3]=[0,1,2] - - mat[5,8,0:3]=[s3*m*n*(nn-0.5*(ll+mm)), s3*m*n*(ll+mm-nn), -0.5*s3*m*n*(ll+mm)] - der[5,8,0:3,:]=[s3*( dm*n*(nn-0.5*(ll+mm)) + m*dn*(nn-0.5*(ll+mm))+m*n*(dnn-0.5*(dll+dmm)) ),\ - s3*( dm*n*(ll+mm-nn)+m*dn*(ll+mm-nn)+m*n*(dll+dmm-dnn) ),\ - - 0.5*s3*( dm*n*(ll+mm)+m*dn*(ll+mm)+m*n*(dll+dmm) )] - ind[5,8,0:3]=[0,1,2] - - mat[6,6,0:3]=[3*nn*ll, (nn+ll-4*nn*ll), (mm+nn*ll)] - der[6,6,0:3,:]=[3*(dnn*ll+nn*dll), dnn+dll-4*(dnn*ll+nn*dll), (dmm+dnn*ll+nn*dll)] - ind[6,6,0:3]=[0,1,2] - - mat[6,7,0:3]=[1.5*n*l*(ll-mm), n*l*(1-2*(ll-mm)), - n*l*(1-0.5*(ll-mm))] - der[6,7,0:3,:]=[1.5*( dn*l*(ll-mm)+n*dl*(ll-mm)+n*l*(dll-dmm) ),\ - dn*l*(1-2*(ll-mm))+n*dl*(1-2*(ll-mm))+n*l*(-2*(dll-dmm)),\ - -( dn*l*(1-0.5*(ll-mm))+n*dl*(1-0.5*(ll-mm))+n*l*(-0.5*(dll-dmm)) )] - ind[6,7,0:3]=[0,1,2] - - mat[6,8,0:3]=[s3*l*n*(nn-0.5*(ll+mm)), s3*l*n*(ll+mm-nn), - 0.5*s3*l*n*(ll+mm)] - der[6,8,0:3,:]=[s3*( dl*n*(nn-0.5*(ll+mm))+l*dn*(nn-0.5*(ll+mm))+l*n*(dnn-0.5*(dll+dmm)) ),\ - s3*( dl*n*(ll+mm-nn)+l*dn*(ll+mm-nn)+l*n*(dll+dmm-dnn) ),\ - - 0.5*s3*( dl*n*(ll+mm)+l*dn*(ll+mm)+l*n*(dll+dmm) )] - ind[6,8,0:3]=[0,1,2] - - mat[7,7,0:3]=[0.75*(ll-mm)**2, (ll+mm-(ll-mm)**2), (nn+0.25*(ll-mm)**2)] - der[7,7,0:3,:]=[0.75*2*(ll-mm)*(dll-dmm), (dll+dmm-2*(ll-mm)*(dll-dmm)), (dnn+0.25*2*(ll-mm)*(dll-dmm))] - ind[7,7,0:3]=[0,1,2] - - mat[7,8,0:3]=[0.5*s3*(ll-mm)*(nn-0.5*(ll+mm)), s3*nn*(mm-ll), 0.25*s3*(1+nn)*(ll-mm)] - der[7,8,0:3,:]=[0.5*s3*( (dll-dmm)*(nn-0.5*(ll+mm))+(ll-mm)*(dnn-0.5*(dll+dmm)) ),\ - s3*( dnn*(mm-ll)+nn*(dmm-dll) ),\ - 0.25*s3*( dnn*(ll-mm)+(1+nn)*(dll-dmm) )] - ind[7,8,0:3]=[0,1,2] - - mat[8,8,0:3]=[(nn-0.5*(ll+mm))**2, 3*nn*(ll+mm), 0.75*(ll+mm)**2] - der[8,8,0:3,:]=[2*(nn-0.5*(ll+mm))*(dnn-0.5*(dll+dmm)),\ - 3*( dnn*(ll+mm)+nn*(dll+dmm) ),\ - 0.75*2*(ll+mm)*(dll+dmm)] - ind[8,8,0:3]=[0,1,2] - - # use the same rules for orbitals when they are reversed (pd ->dp)... - for a in range(9): - for b in range(a+1,9): - mat[b,a,:]=mat[a,b,:] - der[b,a,:,:]=der[a,b,:,:] - ind[b,a,:]=ind[a,b,:] - - # ...but use different indices from table - #pd 3:5-->10:12 - #sd 7->12 - #sp 8->13 - ind[1,0,0]=13 - ind[2,0,0]=13 - ind[3,0,0]=13 - ind[4,0,0]=12 - ind[5,0,0]=12 - ind[6,0,0]=12 - ind[7,0,0]=12 - ind[8,0,0]=12 - ind[4,1,0:2]=[10,11] - ind[5,1,0:2]=[10,11] - ind[6,1,0:2]=[10,11] - ind[7,1,0:2]=[10,11] - ind[8,1,0:2]=[10,11] - ind[4,2,0:2]=[10,11] - ind[5,2,0:2]=[10,11] - ind[6,2,0:2]=[10,11] - ind[7,2,0:2]=[10,11] - ind[8,2,0:2]=[10,11] - ind[4,3,0:2]=[10,11] - ind[5,3,0:2]=[10,11] - ind[6,3,0:2]=[10,11] - ind[7,3,0:2]=[10,11] - ind[8,3,0:2]=[10,11] - - for i in range(noi): - for j in range(noj): - ht[i,j]=sum( [mat[i,j,k]*h[ind[i,j,k]] for k in range(cnt[i,j])] ) - st[i,j]=sum( [mat[i,j,k]*s[ind[i,j,k]] for k in range(cnt[i,j])] ) - for a in range(3): - dht[i,j,a]=sum( [mat[i,j,k]*dh[ind[i,j,k],a]+der[i,j,k,a]*h[ind[i,j,k]] for k in range(cnt[i,j])] ) - dst[i,j,a]=sum( [mat[i,j,k]*ds[ind[i,j,k],a]+der[i,j,k,a]*s[ind[i,j,k]] for k in range(cnt[i,j])] ) - return ht, st, dht, dst - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/__init__.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/__init__.py deleted file mode 100644 index 3432cf3..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/__init__.py +++ /dev/null @@ -1,89 +0,0 @@ -""" -Input module. Contains functions to read element, Slater-Koster and repulsion -data. -""" - -def read_element(filename, symbol, format=None): - """ - Read element data from files. - - Parameters: - ----------- - fileobj: filename of file-object to read from - symbol: chemical symbol of the element - """ - - if format is None: - format = filetype(filename) - - if format == 'elm': - from hotbit.io.native import read_element_from_elm - return read_element_from_elm(filename, symbol) - - if format == 'skf': - from hotbit.io.dftb import read_element_from_skf - return read_element_from_skf(filename, symbol) - - raise RuntimeError('File format "'+format+'" not recognized!') - - - -def read_HS(filename, symboli, symbolj, format=None): - """ - Read Slater-Koster tables from files. - - Parameters: - ----------- - fileobj: filename of file-object to read from - symboli: chemical symbol of the first element - symbolj: chemical symbol of the second element - """ - - if format is None: - format = filetype(filename) - - if format == 'par': - from hotbit.io.native import read_HS_from_par - return read_HS_from_par(filename, symboli, symbolj) - - if format == 'skf': - from hotbit.io.dftb import read_HS_from_skf - return read_HS_from_skf(filename, symboli, symbolj) - - raise RuntimeError('File format "'+format+'" not recognized!') - - - -def read_repulsion(filename, format=None): - """ - Read Slater-Koster tables from files. - - Parameters: - ----------- - fileobj: filename of file-object to read from - """ - - if format is None: - format = filetype(filename) - - if format == 'par': - from hotbit.io.native import read_repulsion_from_par - return read_repulsion_from_par(filename) - - if format == 'skf': - from hotbit.io.dftb import read_repulsion_from_skf - return read_repulsion_from_skf(filename) - - raise RuntimeError('File format "'+format+'" not recognized!') - - - -def filetype(filename): - if filename.lower().endswith('.elm'): - return 'elm' - - if filename.lower().endswith('.par'): - return 'par' - - if filename.lower().endswith('.skf') or filename.lower.endswith('.spl'): - return 'skf' diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/dftb.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/dftb.py deleted file mode 100644 index 899ad3f..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/dftb.py +++ /dev/null @@ -1,192 +0,0 @@ -""" -DFTB file format. -See: http://www.dftb.org/ -""" -from math import log, pi, sqrt -from copy import copy - -import numpy as np - -from box.data import data as box_data - -from hotbit.io.fortran import fortran_readline - - - -def read_element_from_skf(fileobj, symbol): - """ - Read element data from DFTB-style .skf file. - - Parameters: - ----------- - fileobj: filename of file-object to read from - symbol: chemical symbol of the element - """ - - if isinstance(fileobj, str): - fileobj = open(fileobj) - - # First line contains grid spacing and number of grid points, ignore - fileobj.readline() - - # Self-energies, spin-polarization energies, Hubbard-U - eself = [ 0.0 ]*3 - U = [ 0.0 ]*3 - q = [ 0.0 ]*3 - eself[0], eself[1], eself[2], espin, \ - U[0], U[1], U[2], q[0], q[1], q[2] = fortran_readline(fileobj) - - # Initialize data from database - data = copy(box_data[symbol]) - - data['epsilon'] = { } - for orbital in data['valence_orbitals']: - if 's' in orbital: - data['epsilon'][orbital] = eself[2] - elif 'p' in orbital: - data['epsilon'][orbital] = eself[1] - elif 'd' in orbital: - data['epsilon'][orbital] = eself[0] - - # Apparently, only the last U is used - data['U'] = U[2] - data['FWHM'] = sqrt(8*log(2.0)/pi)/data['U'] - - energies=[] - for orbital in data['valence_orbitals']: - eps = data['epsilon'][orbital] - if 's' in orbital: n=1 - elif 'p' in orbital: n=3 - elif 'd' in orbital: n=5 - energies.extend( [eps]*n ) - data['onsite_energies'] = energies - data['nr_basis_orbitals'] = len(energies) - data['valence_energies'] = np.array(energies, dtype=float) - - data['comment'] = None - - # .skf files do not contain basis information - return data, None - - -def read_HS_from_skf(fileobj, symboli, symbolj): - """ - Read Hamitonian and overlap data from DFTB-style .skf file. - - Parameters: - ----------- - fileobj: filename of file-object to read from - symboli: chemical symbol of the first element - symbolj: chemical symbol of the second element - """ - - if isinstance(fileobj, str): - fileobj = open(fileobj) - - # Homoatomic interactions also contain element data - if symboli == symbolj: - # First line contains grid spacing and number of grid points - l = fortran_readline(fileobj) - dx = l[0] - n = l[1] - n = int(n) - - # Contains self-energies, spin-polarization energies, Hubbard-U, ... - l = fileobj.readline() - else: - # First line contains grid spacing and number of grid points - dx, n = fortran_readline(fileobj) - n = int(n) - - # The n information is sometimes wrong, better count while reading - #x = dx*np.arange(0, n) - - HS = [ ] - l = fileobj.readline() - while l and l.strip() != 'Spline': - if l.strip() == 'Spline': - if i != n-1: - raise RuntimeError('Spline keyword encountered reading tables ' - 'for %s-%s before reaching the end of the ' - 'HS table.' % ( symboli, symbolj )) - else: - HS += [ fortran_readline(l) ] - - l = fileobj.readline() - - if not l: - raise RuntimeError('Premature end-of-file: Keyword "Spline" not found ' - 'for %s-%s.' % ( symboli, symbolj )) - - HS = np.array(HS) - x = dx*np.arange(0, HS.shape[0]) - - #return x[0:HS.shape[0]], np.array(HS) - return x, np.array(HS) - - - -def read_repulsion_from_skf(fileobj, rep_x0=0.1, rep_dx=0.005): - """ - Read repulsion from DFTB-style .skf file. - The repulsion in the .skf-file consists of an exponential and a spline - part. Both will be converted to a single table. - - Parameters: - ----------- - fileobj: filename of file-object to read from - rep_x0: minimum value of the repulsion table - rep_dx: step size for discretization - """ - - if isinstance(fileobj, str): - fileobj = open(fileobj) - - l = fileobj.readline() - while l and l.strip() != 'Spline': - l = fileobj.readline() - - if not l: - raise RuntimeError('Could not find "Spline" keyword when reading ' - 'repulsion.') - - n, cutoff = fortran_readline(fileobj) - n = int(n) - - # Coefficients for the exponential - c1, c2, c3 = fortran_readline(fileobj) - - x1, x2, splc1, splc2, splc3, splc4 = fortran_readline(fileobj) - - x = np.linspace(rep_x0, cutoff, int((cutoff-rep_x0)/rep_dx)+1) - y = c3 + np.exp(c2-c1*x) - - i0 = np.searchsorted(x, x1)+1 - for j in range(n-1): - if j > 0: - last_x2 = x2 - x1, x2, splc1, splc2, splc3, splc4 = fortran_readline(fileobj) - assert x1 == last_x2 - i1 = np.searchsorted(x, x2)+1 - y[i0:i1] = \ - splc1 + \ - splc2 * (x[i0:i1]-x1) + \ - splc3 * (x[i0:i1]-x1)**2 + \ - splc4 * (x[i0:i1]-x1)**3 - i0 = i1 - - # The last entry is a fifth-order polynomial - last_x2 = x2 - x1, x2, splc1, splc2, splc3, splc4, splc5, splc6 = fortran_readline(fileobj) - assert x1 == last_x2 - - i1 = np.searchsorted(x, x2)+1 - y[i0:i1] = \ - splc1 + \ - splc2 * (x[i0:i1]-x1) + \ - splc3 * (x[i0:i1]-x1)**2 + \ - splc4 * (x[i0:i1]-x1)**3 + \ - splc5 * (x[i0:i1]-x1)**4 + \ - splc6 * (x[i0:i1]-x1)**5 - - return x, y diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/fortran.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/fortran.py deleted file mode 100644 index cc998b0..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/fortran.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Input of Fortran formatted text files. -""" - -def fortran_readline(f, dtype=float): - """ - Read a line from a fortran text file and convert to a list. - - In particular, statements like '5*20.0' are resolved to a list containing - 5 times the value 20.0. - """ - - if isinstance(f, str): - l = f - else: - l = f.readline() - s = l.replace('d', 'e').replace(',', ' ').split() - - r = [ ] - for e in s: - i = e.find('*') - - if i == -1: - r += [ dtype(e) ] - else: - n = int(e[:i]) - v = dtype(e[i+1:]) - - r += [ v ]*n - - return r diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/native.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/native.py deleted file mode 100644 index 1e3dd5a..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/io/native.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -Native Hotbit file format. -""" -from copy import copy - -import numpy as np - -from box import mix -from box.data import data as box_data -from box.interpolation import Function - - - -def read_element_from_elm(fileobj, symbol): - """ - Read element data from Hotbit-style .elm file. - - Parameters: - ----------- - fileobj: filename of file-object to read from - symbol: chemical symbol of the element - """ - - if isinstance(fileobj, str): - fileobj = open(fileobj) - - symb = mix.find_value(fileobj, 'symbol').strip() - assert symb == symbol - - data = copy(box_data[symbol]) - - data['U'] = float(mix.find_value(fileobj, 'U')) - data['FWHM'] = float(mix.find_value(fileobj, 'FWHM')) - data['epsilon'] = { } - for orbital in data['valence_orbitals']: - data['epsilon'][orbital] = float( - mix.find_value(fileobj, 'epsilon_%s' % orbital) - ) - data['comment'] = mix.find_value(fileobj, 'comment', - fmt='strings', - default=['no comment']) - - functions = _read_functions(fileobj, data['valence_orbitals']) - - energies=[] - for orbital in data['valence_orbitals']: - eps = data['epsilon'][orbital] - if 's' in orbital: n=1 - elif 'p' in orbital: n=3 - elif 'd' in orbital: n=5 - energies.extend( [eps]*n ) - data['onsite_energies'] = energies - data['nr_basis_orbitals'] = len(energies) - data['valence_energies'] = np.array(energies, dtype=float) - - # vdW correction - data['C6'] = mix.find_value(fileobj, 'C6', default=-1.0) - data['p'] = mix.find_value(fileobj, 'p', default=-1.0) - data['R0'] = mix.find_value(fileobj, 'R0', default=-1.0) - - return data, functions - - - -def _read_functions(fileobj, valence_orbitals): - """ - Read radial wave functions (R=u/r), self-consistent potentials, - confinements, etc. from given file. - """ - - default = np.array([[0,0],[1,0],[2,0],[3,0]]) - functions = { - 'unl': {}, - 'Rnl': {} - } - - for nl in valence_orbitals: - m = mix.find_value(fileobj, 'u_%s' % nl, fmt='matrix', default=default) - functions['unl'][nl]=Function('spline', m[:,0], m[:,1]) - functions['Rnl'][nl]=Function('spline', m[:,0], m[:,1]/m[:,0]) - - m = mix.find_value(fileobj, 'effective_potential', - fmt='matrix', default=default) - functions['effective_potential'] = Function('spline', m[:,0], m[:,1]) - m = mix.find_value(fileobj, 'confinement_potential', - fmt='matrix', default=default) - functions['confinement_potential'] = Function('spline', m[:,0], m[:,1]) - - return functions - - - -def read_HS_from_par(fileobj, symboli, symbolj): - """ - Read Hamiltonian and overlap data from Hotbit-style .par file. - - Parameters: - ----------- - fileobj: filename of file-object to read from - symboli: chemical symbol of the first element - symbolj: chemical symbol of the second element - """ - - if mix.find_value(fileobj, 'X_X_table', fmt='test'): - table = mix.find_value(fileobj, - 'X_X_table' % ( symboli, symbolj ), - fmt='matrix') - else: - table = mix.find_value(fileobj, - '%s_%s_table' % ( symboli, symbolj ), - fmt='matrix') - - return table[:, 0], table[:, 1:] - - - -def read_repulsion_from_par(fileobj): - """ - Read repulsion data from Hotbit-style .par file. - - Parameters: - ----------- - fileobj: filename of file-object to read from - """ - - try: - v = mix.find_value(fileobj, 'repulsion', fmt='matrix') - except: - v = np.array([[0,0],[1,0],[2,0],[3,0]]) - - return v[:, 0], v[:, 1] diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/neighbors.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/neighbors.py deleted file mode 100644 index 06eeb15..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/neighbors.py +++ /dev/null @@ -1,135 +0,0 @@ -""" -Construct neighbor lists and return distances and distance vectors. -""" - -# Copyright (C) 2010 NSC Jyvaskyla, Fh-IWM -# Please see the accompanying LICENSE file for further information. - -import numpy as np - -# diag_indices_from was introduced in numpy 1.4.0 -if hasattr(np, 'diag_indices_from'): - diag_indices_from = np.diag_indices_from -else: - def diag_indices_from(m): - i = [ ] - for n in m.shape: - i += [ np.arange(n, dtype=int) ] - return tuple(i) - - -def n_from_ranges(s, n, m=None): - r = [ ] - - if type(n) == int or type(n) == float: - n = [n]*3 - if m is not None: - if type(m) == int or type(m) == float: - m = [m]*3 - else: - m = [ i for i in n ] - n = [ -i for i in n ] - - for cn, cm, ( i1, i2 ) in zip(n, m, s): - if i1 == -np.Inf: - j1 = cn - else: - j1 = int(i1) - if i2 == np.Inf: - j2 = cm+1 - else: - j2 = int(i2)+1 - r += [ ( j1, j2 ) ] - - return r - - -def sappend(x, y): - if x is None: - return y - elif len(x) == 0: - return y - else: - return np.append(x, y, axis=0) - - -def get_neighbors(a, cutoff=None): - """ - Given a Hotbit atoms object, return a list of neighbors that are within a - certain cutoff. Neighbors are returned for each atom, along with the - distance and the normal vector pointing to the neighbor. - - Parameters: - ----------- - a: Hotbit atoms object - cutoff: Return neighbors up to this cutoff. If omitted, all neighbors are - returned. - - Return tuple: - ------------- - i: Indices of the primary atom - j: Indices of the neighboring atom - d: Distances - n: Normal vectors - """ - # FIXME!!! Brute force scan in the neighboring 5 cells in all directions. - # This might not be enough, i.e. for chiral nanotubes. Maybe the container - # itself should contain a function to return nearest neighbor periodic - # cells. - # For large systems, some kind of binning scheme should implemented. - sym_ranges = a.get_symmetry_operation_ranges() - if cutoff is None and not a.is_cluster(): - raise RuntimeError("Please specify a cutoff when searching for " - "neighbors in a periodic system.") - - if cutoff is None: - n1, n2, n3 = n_from_ranges(sym_ranges, np.Inf) - else: - n1, n2, n3 = n_from_ranges(sym_ranges, 5) - - nat = len(a) - r = a.get_positions() - - # Some reference coordinate, the origin should be fine - r0_v = np.zeros(3, dtype=float) - - jl = np.tile(np.arange(nat, dtype=int), (nat, 1)) - il = jl.transpose() - - i = None - j = None - d = None - n = None - - # Contribution of neighboring boxes - for x1 in range(*n1): - for x2 in range(*n2): - for x3 in range(*n3): - # construct a matrix with distances - r1 = a.transform(r0_v, [x1, x2, x3]) - T = a.rotation([x1, x2, x3]) - - rT = np.dot(r-r0_v, np.transpose(T)) - - dr = r.reshape(nat, 1, 3) - (r1+rT).reshape(1, nat, 3) - abs_dr = np.sqrt(np.sum(dr*dr, axis=2)) - if cutoff is None: - mask = np.ones([nat, nat], dtype=bool) - else: - mask = abs_dr < cutoff - - # Do not return self-interactions - if x1 == 0 and x2 == 0 and x3 == 0: - mask[diag_indices_from(mask)] = False - - if np.any(mask): - i = sappend(i, il[mask]) - j = sappend(j, jl[mask]) - - abs_dr = abs_dr[mask] - dr = dr[mask, :]/abs_dr.reshape(-1, 1) - - d = sappend(d, abs_dr) - n = sappend(n, dr) - - return i, j, d, n diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/occupations.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/occupations.py deleted file mode 100644 index c32fa26..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/occupations.py +++ /dev/null @@ -1,103 +0,0 @@ -import numpy as np -from scipy.optimize import brentq - -class Occupations: - def __init__(self,nel,width,wk): - ''' - Initialize parameters for occupations. - - @param nel: Number of electrons - @param width: Fermi-broadening - @param wk: k-point weights - ''' - self.nel=nel - self.width=width - self.wk=wk - self.nk=len(wk) - - - def get_mu(self): - """ Return the Fermi-level (or chemical potential). """ - return self.mu - - - def fermi(self,mu): - """ Occupy states with given chemical potential. - - Occupations are 0...2; without k-point weights - """ - args = (self.e-mu)/self.width - exps = np.exp(args) - return 2/(exps+1) - - - def fermi_function(self,e): - """ - Return Fermi function for given energy [0,1] - """ - arg = (e-self.mu)/self.width - return 1/(np.exp(arg)+1) - - - def root_function(self,mu): - """ This function is exactly zero when mu is right. """ - # w_k transpose(f_ka) = w_k f_ak -> transpose -> f_ka*w_k - f = self.fermi(mu) - kf = (self.wk * f.transpose()).transpose() - return kf.sum()-self.nel - - - def occupy(self,e): - ''' - Calculate occupation numbers with given Fermi-broadening. - - @param e: e[k,a] energy of k-point, state a - @param wk: wk[:] weights for k-points - @param width: The Fermi-broadening - ''' - self.e=e - eflat = e.flatten() - ind = np.argsort( eflat ) - e_sorted = eflat[ind] - n_sorted = (self.wk*np.ones_like(e).transpose()*2).transpose().flatten()[ind] - sum = n_sorted.cumsum() - ifermi = np.searchsorted(sum,self.nel) - - xtol = 1E-13 - - try: - # make the first guess (simple guess, assuming equal k-point weights) - elo = e_sorted[ifermi-1] - ehi = e_sorted[ifermi-1] - guess = e_sorted(ifermi) - dmu = np.max((self.width,guess-elo,ehi-guess)) - mu = brentq(self.root_function,guess-dmu,guess+dmu,xtol=xtol) - except: - # probably a bad guess - dmu = self.width - mu = brentq(self.root_function,e_sorted[0]-dmu,e_sorted[-1]+dmu,xtol=xtol) - - if np.abs( self.root_function(mu) )>1E-10: - raise RuntimeError('Fermi level could not be assigned reliably. Has the system fragmented?') - - f = self.fermi(mu) - self.mu, self.f = mu, f - return f - - - def plot(self): - import pylab as pl - for ik in range(self.nk): - pl.plot(self.e[ik,:],self.f[ik,:]) - pl.scatter(self.e[ik,:],self.f[ik,:]) - pl.title('occupations') - pl.xlabel('energy (Ha)') - pl.ylabel('occupation') - pl.show() - - - - - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/output.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/output.py deleted file mode 100644 index 5656034..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/output.py +++ /dev/null @@ -1,26 +0,0 @@ -import sys -class Output: - def __init__(self): - self.txt=None - - def __del__(self): - if self.txt.closed == False: - self.close_output() - - def set_text(self,txt): - """ Set the stream for text output. """ - if txt==None: - self.txt=sys.stdout - else: - self.txt=open(txt,'a') - - def close_output(self): - self.txt.flush() - if self.txt != sys.stdout: - self.txt.close() - - def get_output(self): - return self.txt - - def flush(self): - self.txt.flush() diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/pairpotential.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/pairpotential.py deleted file mode 100644 index a12366c..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/pairpotential.py +++ /dev/null @@ -1,190 +0,0 @@ -# Copyright (C) 2008 NSC Jyvaskyla -# Please see the accompanying LICENSE file for further information. - -import numpy as np -from ase.units import Hartree, Bohr -from weakref import proxy - -def ij2s(i,j): - return '%04i%04i' %(i,j) - - - -class PairPotential: - def __init__(self,calc): - self.calc=proxy(calc) - self.N=calc.el.get_N() - self.ex = False - self.comment = '' - self.atomv = {} - self.elemv = {} - self.rcut=0.0 - self.symbols = [s[0] for s in self.calc.el.get_property_lists(['s'])] - self.greet = False - - - def exists(self): - """ Return whether any potentials exist. """ - return self.ex - - - def greetings(self): - """ Return the repulsion documentations. """ - print>> self.calc.txt,'Pair potentials:\n'+self.comment - - - def add_pair_potential(self,i,j,v,eVA=True): - """ - Add pair interaction potential function for elements or atoms. - - parameters: - =========== - i,j: * atom indices, if integers (0,1,2,...) - * elements, if strings ('C','H',...) - v: Pair potential function. - Only one potential per element and atom pair allowed. - Syntax: v(r,der=0), v(r=None) returning the - interaction range in Bohr or Angstrom. - eVA: True for v using eV and Angstrom - False for v using Hartree and Bohr - """ - # construct a function that works in atomic units - if eVA: - def v2(r,der=0): - if r==None: - return v(None)/Bohr - if der==0: - return v(r/Bohr,der)/Hartree - elif der==1: - return v(r/Bohr,der)*Bohr/Hartree - else: - v2 = v - - if isinstance(i,int): - self.comment += ' Atom pair %i-%i\n' %(i,j) - self.atomv[ij2s(i,j)] = v2 - self.atomv[ij2s(j,i)] = v2 - else: - self.comment += ' Element pair %s-%s\n' %(i,j) - self.elemv[i+j]=v2 - self.elemv[j+i]=v2 - self.rcut = max(self.rcut, v2(None)) - self.ex = True - - - def _get_full_v(self,i,j): - """ Return the full interaction potential between atoms i and j.""" - ij = ij2s(i,j) - sij = self.symbols[i]+self.symbols[j] - - if ij in self.atomv and sij in self.elemv: - def v(r,der=0): - return self.atomv[ij](r,der) + self.elemv[sij](r,der) - elif ij in self.atomv: - def v(r,der=0): - return self.atomv[ij](r,der) - elif sij in self.elemv: - def v(r,der=0): - return self.elemv[sij](r,der) - else: - def v(r,der=0): - return 0.0 - return v - - - def get_energy(self): - """ Return the energy in pair potentials (in eV). """ - if not self.ex: - return 0.0 - self.calc.start_timing('e_pp') - if not self.greet: - self.greetings() - self.greet = True - - lst=self.calc.el.get_property_lists(['i','s']) - Rijn = self.calc.el.rijn - epp=0.0 - for i,si in lst: - for j,sj in lst[i:]: - for n,rijn in enumerate(Rijn[:,i,j]): - if i==j and n==0: continue - d = np.sqrt( rijn[0]**2+rijn[1]**2+rijn[2]**2 ) - if d>self.rcut: continue - v = self._get_full_v(i,j) - if i==j: - epp+=0.5*v(d) - else: - epp+=v(d) - self.calc.stop_timing('e_pp') - return epp*Hartree - - - def get_pair_energy(self,i,j): - """ - Return the pair repulsion energy of given atom pair (in Hartree) - - parameters: - =========== - i,j: atom indices - """ - Rijn = self.calc.el.rijn - epp=0.0 - for n,rijn in enumerate(Rijn[:,i,j]): - if i==j and n==0: continue - d = np.sqrt( rijn[0]**2+rijn[1]**2+rijn[2]**2 ) - if d>self.rcut: continue - v = self._get_full_v(i,j) - if i==j: - epp += 0.5*v(d) - else: - epp += v(d) - return epp - - - def get_forces(self): - """ - Return pair potential forces in atomic units. - - F_i = sum_(j,n) V'(rijn) rijn/dijn, with rijn = r_j^n -r_i and dijn=|rijn| - """ - f=np.zeros((self.N,3)) - if not self.exists: - return f - self.calc.start_timing('f_pp') - lst = self.calc.el.get_property_lists(['i','s']) - Rijn = self.calc.el.rijn - for i,si in lst: - for j,sj in lst: - V = self._get_full_v(i,j) - for n,rijn in enumerate(Rijn[:,i,j]): - if i==j and n==0: continue - dijn = np.sqrt( rijn[0]**2+rijn[1]**2+rijn[2]**2 ) - if dijn> self.txt, 'Using scalar relativistic corrections.' - print>>self.txt, 'max %i nodes, %i grid points' %(maxnodes,self.N) - self.xgrid=np.linspace(0,np.log(self.rmax/self.rmin),self.N) - self.rgrid=self.rmin*np.exp(self.xgrid) - self.grid=RadialGrid(self.rgrid) - self.timer.stop('init') - print>>self.txt, self.get_comment() - self.solved=False - - def __getstate__(self): - """ Return dictionary of all pickable items. """ - d=self.__dict__.copy() - for key in self.__dict__: - if callable(d[key]): - d.pop(key) - d.pop('out') - return d - - def set_output(self,txt): - """ Set output channel and give greetings. """ - if txt == '-': - self.txt = open(os.devnull,'w') - elif txt==None: - self.txt=sys.stdout - else: - self.txt=open(txt,'a') - print>>self.txt, '*******************************************' - print>>self.txt, 'Kohn-Sham all-electron calculation for %2s ' %self.symbol - print>>self.txt, '*******************************************' - - - def calculate_energies(self,echo=False): - """ - Calculate energy contributions. - """ - self.timer.start('energies') - self.bs_energy=0.0 - for n,l,nl in self.list_states(): - self.bs_energy+=self.occu[nl]*self.enl[nl] - - self.exc=array([self.xcf.exc(self.dens[i]) for i in xrange(self.N)]) - self.Hartree_energy=self.grid.integrate(self.Hartree*self.dens,use_dV=True)/2 - self.vxc_energy=self.grid.integrate(self.vxc*self.dens,use_dV=True) - self.exc_energy=self.grid.integrate(self.exc*self.dens,use_dV=True) - self.confinement_energy=self.grid.integrate(self.conf*self.dens,use_dV=True) - self.total_energy=self.bs_energy-self.Hartree_energy-self.vxc_energy+self.exc_energy - if echo: - print>>self.txt, '\n\nEnergetics:' - print>>self.txt, '-------------' - print>>self.txt, '\nsingle-particle energies' - print>>self.txt, '------------------------' - for n,l,nl in self.list_states(): - print>>self.txt, '%s, energy %.15f' %(nl,self.enl[nl]) - - print>>self.txt, '\nvalence orbital energies' - print>>self.txt, '--------------------------' - for nl in data[self.symbol]['valence_orbitals']: - print>>self.txt, '%s, energy %.15f' %(nl,self.enl[nl]) - - print>>self.txt, '\n' - print>>self.txt, 'total energies:' - print>>self.txt, '---------------' - print>>self.txt, 'sum of eigenvalues: %.15f' %self.bs_energy - print>>self.txt, 'Hartree energy: %.15f' %self.Hartree_energy - print>>self.txt, 'vxc correction: %.15f' %self.vxc_energy - print>>self.txt, 'exchange + corr energy: %.15f' %self.exc_energy - print>>self.txt, '----------------------------' - print>>self.txt, 'total energy: %.15f\n\n' %self.total_energy - self.timer.stop('energies') - - - def calculate_density(self): - """ Calculate the radial electron density.; sum_nl |Rnl(r)|**2/(4*pi) """ - self.timer.start('density') - dens=np.zeros_like(self.rgrid) - for n,l,nl in self.list_states(): - dens+=self.occu[nl]*self.unlg[nl]**2 - - nel=self.grid.integrate(dens) - if abs(nel-self.nel)>1E-10: - raise RuntimeError('Integrated density %.3g, number of electrons %.3g' %(nel,self.nel) ) - dens=dens/(4*np.pi*self.rgrid**2) - - self.timer.stop('density') - return dens - - - def calculate_Hartree_potential(self): - """ - Calculate Hartree potential. - - Everything is very sensitive to the way this is calculated. - If you can think of how to improve this, please tell me! - - """ - self.timer.start('Hartree') - dV=self.grid.get_dvolumes() - r, r0=self.rgrid, self.grid.get_r0grid() - N=self.N - n0=0.5*(self.dens[1:]+self.dens[:-1]) - n0*=self.nel/sum(n0*dV) - - lo, hi, Hartree=np.zeros(N), np.zeros(N), np.zeros(N) - lo[0]=0.0 - for i in range(1,N): - lo[i] = lo[i-1] + dV[i-1]*n0[i-1] - - hi[-1]=0.0 - for i in range(N-2,-1,-1): - hi[i] = hi[i+1] + n0[i]*dV[i]/r0[i] - - for i in range(N): - Hartree[i] = lo[i]/r[i] + hi[i] - self.Hartree=Hartree - self.timer.stop('Hartree') - - - def V_nuclear(self,r): - return -self.Z/r - - - def calculate_veff(self): - """ Calculate effective potential. """ - self.timer.start('veff') - self.vxc=array([self.xcf.vxc(self.dens[i]) for i in xrange(self.N)]) - self.timer.stop('veff') - return self.nucl + self.Hartree + self.vxc + self.conf - - - def guess_density(self): - """ Guess initial density. """ - r2=0.02*self.Z # radius at which density has dropped to half; improve this! - dens=np.exp( -self.rgrid/(r2/np.log(2)) ) - dens=dens/self.grid.integrate(dens,use_dV=True)*self.nel - #pl.plot(self.rgrid,dens) - return dens - - - def get_veff_and_dens(self): - """ Construct effective potential and electron density. If restart - file is given, try to read from there, otherwise make a guess. - """ - done = False - if self.restart is not None: - # use density and effective potential from another calculation - try: - from scipy.interpolate import splrep, splev - f = open(self.restart) - rgrid = pickle.load(f) - veff = pickle.load(f) - dens = pickle.load(f) - v = splrep(rgrid, veff) - d = splrep(rgrid, dens) - self.veff = array([splev(r,v) for r in self.rgrid]) - self.dens = array([splev(r,d) for r in self.rgrid]) - f.close() - done = True - except IOError: - print >> self.txt, "Could not open restart file, " \ - "starting from scratch." - if not done: - self.veff=self.nucl+self.conf - self.dens=self.guess_density() - - - def run(self): - """ - Solve the self-consistent potential. - """ - self.timer.start('solve ground state') - print>>self.txt, '\nStart iteration...' - self.enl={} - self.d_enl={} - for n,l,nl in self.list_states(): - self.enl[nl]=0.0 - self.d_enl[nl]=0.0 - - N=self.grid.get_N() - - # make confinement and nuclear potentials; intitial guess for veff - self.conf=array([self.confinement_potential(r) for r in self.rgrid]) - self.nucl=array([self.V_nuclear(r) for r in self.rgrid]) - self.get_veff_and_dens() - self.calculate_Hartree_potential() - #self.Hartree=np.zeros((N,)) - - for it in range(self.itmax): - self.veff=self.mix*self.calculate_veff()+(1-self.mix)*self.veff - if self.scalarrel: - veff = SplineFunction(self.rgrid, self.veff) - self.dveff = array([veff(r, der=1) for r in self.rgrid]) - d_enl_max, itmax=self.solve_eigenstates(it) - - dens0=self.dens.copy() - self.dens=self.calculate_density() - diff=self.grid.integrate(np.abs(self.dens-dens0),use_dV=True) - - if diff 5: - break - self.calculate_Hartree_potential() - if np.mod(it,10)==0: - print>>self.txt, 'iter %3i, dn=%.1e>%.1e, max %i sp-iter' %(it,diff,self.convergence['density'],itmax) - if it==self.itmax-1: - if self.timing: - self.timer.summary() - raise RuntimeError('Density not converged in %i iterations' %(it+1)) - self.txt.flush() - - self.calculate_energies(echo=True) - print>>self.txt, 'converged in %i iterations' %it - print>>self.txt, '%9.4f electrons, should be %9.4f' %(self.grid.integrate(self.dens,use_dV=True),self.nel) - for n,l,nl in self.list_states(): - self.Rnl_fct[nl]=Function('spline',self.rgrid,self.Rnlg[nl]) - self.unl_fct[nl]=Function('spline',self.rgrid,self.unlg[nl]) - self.timer.stop('solve ground state') - self.timer.summary() - self.txt.flush() - self.solved=True - if self.write != None: - f=open(self.write,'w') - pickle.dump(self.rgrid, f) - pickle.dump(self.veff, f) - pickle.dump(self.dens, f) - f.close() - - - def solve_eigenstates(self,iteration,itmax=100): - """ - Solve the eigenstates for given effective potential. - - u''(r) - 2*(v_eff(r)+l*(l+1)/(2r**2)-e)*u(r)=0 - ( u''(r) + c0(r)*u(r) = 0 ) - - r=r0*exp(x) --> (to get equally spaced integration mesh) - - u''(x) - u'(x) + c0(x(r))*u(r) = 0 - """ - self.timer.start('eigenstates') - - rgrid=self.rgrid - xgrid=self.xgrid - dx=xgrid[1]-xgrid[0] - N=self.N - c2=np.ones(N) - c1=-np.ones(N) - d_enl_max=0.0 - itmax=0 - - for n,l,nl in self.list_states(): - nodes_nl=n-l-1 - if iteration==0: - eps=-1.0*self.Z**2/n**2 - - else: - eps=self.enl[nl] - - if iteration<=3: - delta=0.5*self.Z**2/n**2 #previous!!!!!!!!!! - else: - delta=self.d_enl[nl] - - direction='none' - epsmax=self.veff[-1]-l*(l+1)/(2*self.rgrid[-1]**2) - it=0 - u=np.zeros(N) - hist=[] - - while True: - eps0=eps - c0, c1, c2 = self.construct_coefficients(l, eps) - - # boundary conditions for integration from analytic behaviour (unscaled) - # u(r)~r**(l+1) r->0 - # u(r)~exp( -sqrt(c0(r)) ) (set u[-1]=1 and use expansion to avoid overflows) - u[0:2]=rgrid[0:2]**(l+1) - - if not(c0[-2]<0 and c0[-1]<0): - pl.plot(c0) - pl.show() - - assert c0[-2]<0 and c0[-1]<0 - - u, nodes, A, ctp=shoot(u,dx,c2,c1,c0,N) - it+=1 - norm=self.grid.integrate(u**2) - u=u/sqrt(norm) - - if nodes>nodes_nl: - # decrease energy - if direction=='up': delta/=2 - eps-=delta - direction='down' - elif nodes0: - direction='up' - elif shift<0: - direction='down' - eps+=shift - if eps>epsmax: - eps=0.5*(epsmax+eps0) - hist.append(eps) - - if it>100: - print>>self.txt, 'Epsilon history for %s' %nl - for h in hist: - print h - print>>self.txt, 'nl=%s, eps=%f' %(nl,eps) - print>>self.txt, 'max epsilon',epsmax - raise RuntimeError('Eigensolver out of iterations. Atom not stable?') - - itmax=max(it,itmax) - self.unlg[nl]=u - self.Rnlg[nl]=self.unlg[nl]/self.rgrid - self.d_enl[nl]=abs(eps-self.enl[nl]) - d_enl_max=max(d_enl_max,self.d_enl[nl]) - self.enl[nl]=eps - if self.verbose: - print>>self.txt, '-- state %s, %i eigensolver iterations, e=%9.5f, de=%9.5f' %(nl,it,self.enl[nl],self.d_enl[nl]) - - assert nodes==nodes_nl - assert u[1]>0.0 - self.timer.stop('eigenstates') - return d_enl_max, itmax - - - def construct_coefficients(self, l, eps): - c = 137.036 - c2 = np.ones(self.N) - if self.scalarrel == False: - c0 = -2*( 0.5*l*(l+1)+self.rgrid**2*(self.veff-eps) ) - c1 = -np.ones(self.N) - else: - # from Paolo Giannozzi: Notes on pseudopotential generation - ScR_mass = array([1 + 0.5*(eps-V)/c**2 for V in self.veff]) - c0 = -l*(l+1) - 2*ScR_mass*self.rgrid**2*(self.veff-eps) - self.dveff*self.rgrid/(2*ScR_mass*c**2) - c1 = self.rgrid*self.dveff/(2*ScR_mass*c**2) - 1 - return c0, c1, c2 - - - def plot_Rnl(self,filename=None): - """ Plot radial wave functions with matplotlib. - - filename: output file name + extension (extension used in matplotlib) - """ - if pl==None: - raise AssertionError('pylab could not be imported') - rmax = data[self.symbol]['R_cov']/0.529177*3 - ri = np.where( self.rgrid=states subplots - - fig=pl.figure() - i=1 - # as a function of grid points - for n,l,nl in self.list_states(): - ax=pl.subplot(2*p,p,i) - pl.plot(self.Rnlg[nl]) - pl.yticks([],[]) - pl.xticks(size=5) - - # annotate - c = 'k' - if nl in self.valence: - c='r' - pl.text(0.5,0.4,r'$R_{%s}(r)$' %nl,transform=ax.transAxes,size=15,color=c) - if ax.is_first_col(): - pl.ylabel(r'$R_{nl}(r)$',size=8) - i+=1 - - # as a function of radius - i = p**2+1 - for n,l,nl in self.list_states(): - ax=pl.subplot(2*p,p,i) - pl.plot(self.rgrid[:ri],self.Rnlg[nl][:ri]) - pl.yticks([],[]) - pl.xticks(size=5) - if ax.is_last_row(): - pl.xlabel('r (Bohr)',size=8) - - c = 'k' - if nl in self.valence: - c='r' - pl.text(0.5,0.4,r'$R_{%s}(r)$' %nl,transform=ax.transAxes,size=15,color=c) - if ax.is_first_col(): - pl.ylabel(r'$R_{nl}(r)$',size=8) - i+=1 - - - file = '%s_KSAllElectron.pdf' %self.symbol - #pl.rc('figure.subplot',wspace=0.0,hspace=0.0) - fig.subplots_adjust(hspace=0.2,wspace=0.1) - s='' - if self.confinement!=None: - s='(confined)' - pl.figtext(0.4,0.95,r'$R_{nl}(r)$ for %s-%s %s' %(self.symbol,self.symbol,s)) - if filename is not None: - file = filename - pl.savefig(file) - - - def get_wf_range(self,nl,fractional_limit=1E-7): - """ Return the maximum r for which |R(r)|fractional_limit*wfmax: - return r - - - def list_states(self): - """ List all potential states {(n,l,'nl')}. """ - states=[] - for l in range(self.maxl+1): - for n in range(1,self.maxn+1): - nl=orbit_transform((n,l),string=True) - if nl in self.occu: - states.append((n,l,nl)) - return states - - - def get_energy(self): - return self.total_energy - - - def get_epsilon(self,nl): - """ get_eigenvalue('2p') or get_eigenvalue((2,1)) """ - nls=orbit_transform(nl,string=True) - if not self.solved: - raise AssertionError('run calculations first.') - return self.enl[nls] - - - def effective_potential(self,r,der=0): - """ Return effective potential at r or its derivatives. """ - if self.veff_fct==None: - self.veff_fct=Function('spline',self.rgrid,self.veff) - return self.veff_fct(r,der=der) - - - def get_radial_density(self): - return self.rgrid,self.dens - - - def Rnl(self,r,nl,der=0): - """ Rnl(r,'2p') or Rnl(r,(2,1))""" - nls=orbit_transform(nl,string=True) - return self.Rnl_fct[nls](r,der=der) - - - def unl(self,r,nl,der=0): - """ unl(r,'2p')=Rnl(r,'2p')/r or unl(r,(2,1))...""" - nls=orbit_transform(nl,string=True) - return self.unl_fct[nls](r,der=der) - - - def get_valence_orbitals(self): - """ Get list of valence orbitals, e.g. ['2s','2p'] """ - return self.valence - - - def get_symbol(self): - """ Return atom's chemical symbol. """ - return self.symbol - - - def get_comment(self): - """ One-line comment, e.g. 'H, charge=0, quadratic, r0=4' """ - comment='%s xc=%s charge=%.1f conf:%s' %(self.symbol,self.xc,float(self.charge),self.confinement_potential.get_comment()) - return comment - - - def get_valence_energies(self): - """ Return list of valence energies, e.g. ['2s','2p'] --> [-39.2134,-36.9412] """ - if not self.solved: - raise AssertionError('run calculations first.') - return [(nl,self.enl[nl]) for nl in self.valence] - - - def write_unl(self,filename,only_valence=True,step=20): - """ Append functions unl=Rnl*r, V_effective, V_confinement into file. - Only valence functions by default. - - Parameters: - ----------- - filename: output file name (e.g. XX.elm) - only_valence: output of only valence orbitals - step: step size for output grid - """ - if not self.solved: - raise AssertionError('run calculations first.') - if only_valence: - orbitals=self.valence - else: - orbitals=[nl for n,l,nl in self.list_states()] - o=open(filename,'a') - for nl in orbitals: - print>>o, '\n\nu_%s=' %nl - for r,u in zip(self.rgrid[::step],self.unlg[nl][::step]): - print>>o, r,u - - print>>o,'\n\nv_effective=' - for r,ve in zip(self.rgrid[::step],self.veff[::step]): - print>>o, r,ve - print>>o,'\n\nconfinement=' - for r,vc in zip(self.rgrid[::step],self.conf[::step]): - print>>o, r,vc - print>>o,'\n\n' - - -def shoot(u,dx,c2,c1,c0,N): - """ - Integrate diff equation - - 2 - d u du - --- c + -- c + u c = 0 - 2 2 dx 1 0 - dx - - in equispaced grid (spacing dx) using simple finite difference formulas - - u'(i)=(u(i+1)-u(i-1))/(2*dx) and - u''(i)=(u(i+1)-2*u(i)+u(i-1))/dx**2 - - u[0:2] *has already been set* according to boundary conditions. - - return u, number of nodes, the discontinuity of derivative at - classical turning point (ctp), and ctp - c0(r) is negative with large r, and turns positive at ctp. - """ - fp=c2/dx**2 + 0.5*c1/dx - fm=c2/dx**2 - 0.5*c1/dx - f0=c0-2*c2/dx**2 - - # backward integration down to classical turning point ctp - # (or one point beyond to get derivative) - # If no ctp, integrate half-way - u[-1]=1.0 - u[-2]=u[-1]*f0[-1]/fm[-1] - all_negative=np.all(c0<0) - for i in xrange(N-2,0,-1): - u[i-1]=(-fp[i]*u[i+1]-f0[i]*u[i])/fm[i] - if abs(u[i-1])>1E10: u[i-1:]*=1E-10 #numerical stability - if c0[i]>0: - ctp=i - break - if all_negative and i==N/2: - ctp=N/2 - break - - utp=u[ctp] - utp1=u[ctp+1] - dright=(u[ctp+1]-u[ctp-1])/(2*dx) - - for i in xrange(1,ctp+1): - u[i+1]=(-f0[i]*u[i]-fm[i]*u[i-1])/fp[i] - - dleft=(u[ctp+1]-u[ctp-1])/(2*dx) - scale=utp/u[ctp] - u[:ctp+1]*=scale - u[ctp+1]=utp1 #above overrode - dleft*=scale - u=u*np.sign(u[1]) - - nodes=sum( (u[0:ctp-1]*u[1:ctp])<0 ) - A=(dright-dleft)*utp - return u, nodes, A, ctp - - -class RadialGrid: - def __init__(self,grid): - """ - mode - ---- - - rmin rmax - r[0] r[1] r[2] ... r[N-1] grid - I----'----I----'----I----'----I----'----I----'----I----'----I - r0[0] r0[1] r0[2] ... r0[N-2] r0grid - dV[0] dV[1] dV[2] ... dV[N-2] dV - - dV[i] is volume element of shell between r[i] and r[i+1] - """ - - rmin, rmax=grid[0], grid[-1] - N=len(grid) - self.N=N - self.grid=grid - self.dr=self.grid[1:N]-self.grid[0:N-1] - self.r0=self.grid[0:N-1]+self.dr/2 - # first dV is sphere (treat separately), others are shells - self.dV=4*np.pi*self.r0**2*self.dr - self.dV*=(4*np.pi*rmax**3/3)/sum(self.dV) - - def get_grid(self): - """ Return the whole radial grid. """ - return self.grid - - def get_N(self): - """ Return the number of grid points. """ - return self.N - - def get_drgrid(self): - """ Return the grid spacings (array of length N-1). """ - return self.dr - - def get_r0grid(self): - """ Return the mid-points between grid spacings (array of length N-1). """ - return self.r0 - - def get_dvolumes(self): - """ Return dV(r)'s=4*pi*r**2*dr. """ - return self.dV - - def plot(self,screen=True): - rgrid=self.get_grid() - pl.scatter(range(len(rgrid)),rgrid) - if screen: pl.show() - - def integrate(self,f,use_dV=False): - """ - Integrate function f (given with N grid points). - int_rmin^rmax f*dr (use_dv=False) or int_rmin^rmax*f dV (use_dV=True) - """ - if use_dV: - return ((f[0:self.N-1]+f[1:self.N])*self.dV).sum()*0.5 - else: - return ((f[0:self.N-1]+f[1:self.N])*self.dr).sum()*0.5 - - - -class ConfinementPotential: - def __init__(self,mode,**kwargs): - self.mode=mode - if mode=='none': - self.f=self.none #lambda r:0.0 - self.comment='none' - elif mode=='quadratic': - self.r0=kwargs['r0'] - self.f=self.quadratic #lambda r:(r/self.r0)**2 - self.comment='quadratic r0=%.3f' %self.r0 - else: - raise NotImplementedError('implement new confinements') - - def get_comment(self): - return self.comment - - def none(self,r): - return 0.0 - - def quadratic(self,r): - return (r/self.r0)**2 - - def __call__(self,r): - return self.f(r) - - - - - -class XC_PW92: - def __init__(self): - """ The Perdew-Wang 1992 LDA exchange-correlation functional. """ - self.small=1E-90 - self.a1 = 0.21370 - self.c0 = 0.031091 - self.c1 = 0.046644 - self.b1 = 1.0/2.0/self.c0*np.exp(-self.c1/2.0/self.c0) - self.b2 = 2*self.c0*self.b1**2 - self.b3 = 1.6382 - self.b4 = 0.49294 - - def exc(self,n,der=0): - """ Exchange-correlation with electron density n. """ - if ntuples, e.g. (2,1)<->'2p'. """ - if string==True and type(nl)==type(''): - return nl #'2p'->'2p' - elif string==True: - return '%i%s' %(nl[0],angular_momenta[nl[1]]) #(2,1)->'2p' - elif string==False and type(nl)==type((2,1)): - return nl #(2,1)->(2,1) - elif string==False: - l=angular_momenta.index(nl[1]) - n=int(nl[0]) - return (n,l) # '2p'->(2,1) - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/configurations.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/configurations.py deleted file mode 100644 index b0a2278..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/configurations.py +++ /dev/null @@ -1,1072 +0,0 @@ -# Copyright (C) 2003 CAMP -# Please see the accompanying LICENSE file for further information. - -# Computer generated code: -# format: -# 'element': (atomic number, [(n, l, occ, energy), ...]) - -configurations = { - 'Ac': (89, - [(1, 0, 2, -3443.1103670000002), - (2, 0, 2, -592.62287800000001), - (2, 1, 6, -572.7627), - (3, 0, 2, -147.320716), - (3, 1, 6, -137.654394), - (3, 2, 10, -119.541743), - (4, 0, 2, -36.158259999999999), - (4, 1, 6, -31.761845999999998), - (4, 2, 10, -23.570609999999999), - (5, 0, 2, -7.7130780000000003), - (5, 1, 6, -6.0651099999999998), - (4, 3, 14, -12.278225000000001), - (5, 2, 10, -3.2227519999999998), - (6, 0, 2, -1.1969799999999999), - (6, 1, 6, -0.74452399999999996), - (6, 2, 1, -0.13778599999999999), - (7, 0, 2, -0.126551)]), - 'Ag': (47, - [(1, 0, 2, -900.32457799999997), - (2, 0, 2, -129.85980699999999), - (2, 1, 6, -120.91335100000001), - (3, 0, 2, -23.678436999999999), - (3, 1, 6, -20.067630000000001), - (3, 2, 10, -13.367803), - (4, 0, 2, -3.22309), - (4, 1, 6, -2.0866020000000001), - (4, 2, 10, -0.29870600000000003), - (5, 0, 1, -0.15740699999999999)]), - 'Al': (13, - [(1, 0, 2, -55.156044000000001), - (2, 0, 2, -3.9348269999999999), - (2, 1, 6, -2.5640179999999999), - (3, 0, 2, -0.286883), - (3, 1, 1, -0.102545)]), - 'Ar': (18, - [(1, 0, 2, -113.800134), - (2, 0, 2, -10.794172), - (2, 1, 6, -8.4434389999999997), - (3, 0, 2, -0.88338399999999995), - (3, 1, 6, -0.38233)]), - 'As': (33, - [(1, 0, 2, -423.336658), - (2, 0, 2, -53.093086), - (2, 1, 6, -47.527869000000003), - (3, 0, 2, -6.7307550000000003), - (3, 1, 6, -4.8517250000000001), - (3, 2, 10, -1.542767), - (4, 0, 2, -0.52366999999999997), - (4, 1, 3, -0.19749700000000001)]), - 'At': (85, - [(1, 0, 2, -3127.3902760000001), - (2, 0, 2, -531.81835000000001), - (2, 1, 6, -513.04424300000005), - (3, 0, 2, -129.03554199999999), - (3, 1, 6, -119.995013), - (3, 2, 10, -103.06037499999999), - (4, 0, 2, -29.809515000000001), - (4, 1, 6, -25.778264), - (4, 2, 10, -18.295162000000001), - (5, 0, 2, -5.4533829999999996), - (5, 1, 6, -4.0270609999999998), - (4, 3, 14, -8.0634829999999997), - (5, 2, 10, -1.6437580000000001), - (6, 0, 2, -0.56018900000000005), - (6, 1, 5, -0.25545299999999999)]), - 'Au': (79, - [(1, 0, 2, -2683.508245), - (2, 0, 2, -447.88897300000002), - (2, 1, 6, -430.72570100000002), - (3, 0, 2, -104.824516), - (3, 1, 6, -96.706999999999994), - (3, 2, 10, -81.511751000000004), - (4, 0, 2, -22.078357), - (4, 1, 6, -18.578652000000002), - (4, 2, 10, -12.131815), - (5, 0, 2, -3.1139359999999998), - (5, 1, 6, -2.0024950000000001), - (4, 3, 14, -3.4868239999999999), - (5, 2, 10, -0.30473800000000001), - (6, 0, 1, -0.16233400000000001)]), - 'B': (5, - [(1, 0, 2, -6.5643469999999997), - (2, 0, 2, -0.34470099999999998), - (2, 1, 1, -0.136603)]), - 'Ba': (56, - [(1, 0, 2, -1305.743258), - (2, 0, 2, -200.84444400000001), - (2, 1, 6, -189.59848299999999), - (3, 0, 2, -42.359434), - (3, 1, 6, -37.536931000000003), - (3, 2, 10, -28.528932999999999), - (4, 0, 2, -8.2570610000000002), - (4, 1, 6, -6.4976219999999998), - (4, 2, 10, -3.4324409999999999), - (5, 0, 2, -1.157159), - (5, 1, 6, -0.69860500000000003), - (6, 0, 2, -0.118967)]), - 'Be': (4, [(1, 0, 2, -3.856411), (2, 0, 2, -0.20574400000000001)]), - 'Bi': (83, - [(1, 0, 2, -2975.5509590000001), - (2, 0, 2, -502.95075800000001), - (2, 1, 6, -484.71635900000001), - (3, 0, 2, -120.613998), - (3, 1, 6, -111.883393), - (3, 2, 10, -95.532476000000003), - (4, 0, 2, -27.070340000000002), - (4, 1, 6, -23.218641000000002), - (4, 2, 10, -16.084817000000001), - (5, 0, 2, -4.6119339999999998), - (5, 1, 6, -3.2936369999999999), - (4, 3, 14, -6.3827439999999998), - (5, 2, 10, -1.139408), - (6, 0, 2, -0.42612899999999998), - (6, 1, 3, -0.180198)]), - 'Br': (35, - [(1, 0, 2, -480.18264299999998), - (2, 0, 2, -61.710022000000002), - (2, 1, 6, -55.677959999999999), - (3, 0, 2, -8.4090570000000007), - (3, 1, 6, -6.2988049999999998), - (3, 2, 10, -2.5221100000000001), - (4, 0, 2, -0.72006599999999998), - (4, 1, 5, -0.29533399999999999)]), - 'C': (6, - [(1, 0, 2, -9.9477180000000001), - (2, 0, 2, -0.50086600000000003), - (2, 1, 2, -0.199186)]), - 'Ca': (20, - [(1, 0, 2, -143.935181), - (2, 0, 2, -15.046905000000001), - (2, 1, 6, -12.285375999999999), - (3, 0, 2, -1.706331), - (3, 1, 6, -1.030572), - (4, 0, 2, -0.14141100000000001)]), - 'Cd': (48, - [(1, 0, 2, -941.47664599999996), - (2, 0, 2, -136.83249000000001), - (2, 1, 6, -127.63512), - (3, 0, 2, -25.379908), - (3, 1, 6, -21.637522000000001), - (3, 2, 10, -14.685252), - (4, 0, 2, -3.596069), - (4, 1, 6, -2.3952599999999999), - (4, 2, 10, -0.47053), - (5, 0, 2, -0.20422799999999999)]), - 'Ce': (58, - [(1, 0, 2, -1406.1482840000001), - (2, 0, 2, -218.684842), - (2, 1, 6, -206.92514800000001), - (3, 0, 2, -47.035283), - (3, 1, 6, -41.938282000000001), - (3, 2, 10, -32.412568999999998), - (4, 0, 2, -9.4327439999999996), - (4, 1, 6, -7.5321059999999997), - (4, 2, 10, -4.1925480000000004), - (5, 0, 2, -1.3697280000000001), - (5, 1, 6, -0.85011000000000003), - (4, 3, 1, -0.33744200000000002), - (5, 2, 1, -0.14055000000000001), - (6, 0, 2, -0.13397400000000001)]), - 'Cl': (17, - [(1, 0, 2, -100.369229), - (2, 0, 2, -9.1879930000000005), - (2, 1, 6, -7.0399820000000002), - (3, 0, 2, -0.75445799999999996), - (3, 1, 5, -0.32038)]), - 'Co': (27, - [(1, 0, 2, -275.61663900000002), - (2, 0, 2, -32.379758000000002), - (2, 1, 6, -28.152094999999999), - (3, 0, 2, -3.6518120000000001), - (3, 1, 6, -2.3882850000000002), - (3, 2, 7, -0.32236799999999999), - (4, 0, 2, -0.20449700000000001)]), - 'Cr': (24, - [(1, 0, 2, -213.881191), - (2, 0, 2, -24.113457), - (2, 1, 6, -20.526273), - (3, 0, 2, -2.6490849999999999), - (3, 1, 6, -1.6542300000000001), - (3, 2, 5, -0.11812300000000001), - (4, 0, 1, -0.150445)]), - 'Cs': (55, - [(1, 0, 2, -1256.738791), - (2, 0, 2, -191.98187300000001), - (2, 1, 6, -180.99534399999999), - (3, 0, 2, -39.851584000000003), - (3, 1, 6, -35.166423000000002), - (3, 2, 10, -26.418398), - (4, 0, 2, -7.4559660000000001), - (4, 1, 6, -5.7693260000000004), - (4, 2, 10, -2.8483860000000001), - (5, 0, 2, -0.91581900000000005), - (5, 1, 6, -0.50490299999999999), - (6, 0, 1, -0.078699000000000005)]), - 'Cu': (29, - [(1, 0, 2, -320.78852000000001), - (2, 0, 2, -38.141309999999997), - (2, 1, 6, -33.481247000000003), - (3, 0, 2, -4.0574529999999998), - (3, 1, 6, -2.6092439999999999), - (3, 2, 10, -0.20227200000000001), - (4, 0, 1, -0.17205599999999999)]), - 'Dy': (66, - [(1, 0, 2, -1843.229585), - (2, 0, 2, -295.34285599999998), - (2, 1, 6, -281.55853100000002), - (3, 0, 2, -65.299441999999999), - (3, 1, 6, -59.091931000000002), - (3, 2, 10, -47.486699999999999), - (4, 0, 2, -12.551251000000001), - (4, 1, 6, -10.094091000000001), - (4, 2, 10, -5.6863520000000003), - (5, 0, 2, -1.5479769999999999), - (5, 1, 6, -0.90349000000000002), - (4, 3, 10, -0.26530199999999998), - (6, 0, 2, -0.132769)]), - 'Er': (68, - [(1, 0, 2, -1961.799176), - (2, 0, 2, -316.310631), - (2, 1, 6, -302.01826999999997), - (3, 0, 2, -70.310141999999999), - (3, 1, 6, -63.818655), - (3, 2, 10, -51.682149000000003), - (4, 0, 2, -13.423546999999999), - (4, 1, 6, -10.819573999999999), - (4, 2, 10, -6.1274430000000004), - (5, 0, 2, -1.6160730000000001), - (5, 1, 6, -0.93520199999999998), - (4, 3, 12, -0.27857700000000002), - (6, 0, 2, -0.134905)]), - 'Eu': (63, - [(1, 0, 2, -1672.3093220000001), - (2, 0, 2, -265.19953400000003), - (2, 1, 6, -252.17669699999999), - (3, 0, 2, -58.068128000000002), - (3, 1, 6, -52.281987000000001), - (3, 2, 10, -41.465518000000003), - (4, 0, 2, -11.267747), - (4, 1, 6, -9.0254549999999991), - (4, 2, 10, -5.0324200000000001), - (5, 0, 2, -1.4440869999999999), - (5, 1, 6, -0.85357499999999997), - (4, 3, 7, -0.23277300000000001), - (6, 0, 2, -0.12942600000000001)]), - 'F': (9, - [(1, 0, 2, -24.189391000000001), - (2, 0, 2, -1.086859), - (2, 1, 5, -0.41560599999999998)]), - 'Fe': (26, - [(1, 0, 2, -254.225505), - (2, 0, 2, -29.564859999999999), - (2, 1, 6, -25.551766000000001), - (3, 0, 2, -3.3606210000000001), - (3, 1, 6, -2.1875230000000001), - (3, 2, 6, -0.29504900000000001), - (4, 0, 2, -0.19797799999999999)]), - 'Fr': (87, - [(1, 0, 2, -3283.2633989999999), - (2, 0, 2, -561.73045000000002), - (2, 1, 6, -542.41423999999995), - (3, 0, 2, -137.959632), - (3, 1, 6, -128.607136), - (3, 2, 10, -111.085223), - (4, 0, 2, -32.861013), - (4, 1, 6, -28.648130999999999), - (4, 2, 10, -20.812462), - (5, 0, 2, -6.5095159999999996), - (5, 1, 6, -4.9732799999999999), - (4, 3, 14, -10.050648000000001), - (5, 2, 10, -2.3609909999999998), - (6, 0, 2, -0.84184800000000004), - (6, 1, 6, -0.46619699999999997), - (7, 0, 1, -0.076175999999999994)]), - 'Ga': (31, - [(1, 0, 2, -370.17063899999999), - (2, 0, 2, -45.200868999999997), - (2, 1, 6, -40.093339), - (3, 0, 2, -5.2416450000000001), - (3, 1, 6, -3.5846659999999999), - (3, 2, 10, -0.73620399999999997), - (4, 0, 2, -0.32801900000000001), - (4, 1, 1, -0.101634)]), - 'Gd': (64, - [(1, 0, 2, -1728.6251950000001), - (2, 0, 2, -275.36313000000001), - (2, 1, 6, -262.081616), - (3, 0, 2, -60.764408000000003), - (3, 1, 6, -54.836922000000001), - (3, 2, 10, -43.754556000000001), - (4, 0, 2, -11.986485999999999), - (4, 1, 6, -9.6698660000000007), - (4, 2, 10, -5.5318350000000001), - (5, 0, 2, -1.6084769999999999), - (5, 1, 6, -0.97874899999999998), - (4, 3, 7, -0.489012), - (5, 2, 1, -0.12722), - (6, 0, 2, -0.143627)]), - 'Ge': (32, - [(1, 0, 2, -396.29299099999997), - (2, 0, 2, -49.055281999999998), - (2, 1, 6, -43.720129), - (3, 0, 2, -5.9614719999999997), - (3, 1, 6, -4.1948220000000003), - (3, 2, 10, -1.117316), - (4, 0, 2, -0.42652299999999999), - (4, 1, 2, -0.14988199999999999)]), - 'H': (1, [(1, 0, 1, -0.23347100000000001)]), - 'He': (2, [(1, 0, 2, -0.57042499999999996)]), - 'Hf': (72, - [(1, 0, 2, -2210.6519899999998), - (2, 0, 2, -361.00652700000001), - (2, 1, 6, -345.68702300000001), - (3, 0, 2, -81.522812000000002), - (3, 1, 6, -74.452656000000005), - (3, 2, 10, -61.231442999999999), - (4, 0, 2, -15.883625), - (4, 1, 6, -12.971211), - (4, 2, 10, -7.6766379999999996), - (5, 0, 2, -2.0498280000000002), - (5, 1, 6, -1.2464409999999999), - (4, 3, 14, -0.87157399999999996), - (5, 2, 2, -0.14380499999999999), - (6, 0, 2, -0.166465)]), - 'Hg': (80, - [(1, 0, 2, -2755.022637), - (2, 0, 2, -461.27864), - (2, 1, 6, -443.84867600000001), - (3, 0, 2, -108.597921), - (3, 1, 6, -100.328031), - (3, 2, 10, -84.845491999999993), - (4, 0, 2, -23.222920999999999), - (4, 1, 6, -19.636187), - (4, 2, 10, -13.019221), - (5, 0, 2, -3.423486), - (5, 1, 6, -2.2619750000000001), - (4, 3, 14, -4.1102910000000001), - (5, 2, 10, -0.45255200000000001), - (6, 0, 2, -0.20513700000000001)]), - 'Ho': (67, - [(1, 0, 2, -1902.0519079999999), - (2, 0, 2, -305.73929399999997), - (2, 1, 6, -291.70099399999998), - (3, 0, 2, -67.785492000000005), - (3, 1, 6, -61.436304), - (3, 2, 10, -49.565995999999998), - (4, 0, 2, -12.985498), - (4, 1, 6, -10.455303000000001), - (4, 2, 10, -5.9061950000000003), - (5, 0, 2, -1.5820879999999999), - (5, 1, 6, -0.91946300000000003), - (4, 3, 11, -0.272677), - (6, 0, 2, -0.13384499999999999)]), - 'I': (53, - [(1, 0, 2, -1161.787047), - (2, 0, 2, -175.073804), - (2, 1, 6, -164.60378800000001), - (3, 0, 2, -35.243350999999997), - (3, 1, 6, -30.831092000000002), - (3, 2, 10, -22.600693), - (4, 0, 2, -6.1158109999999999), - (4, 1, 6, -4.5725220000000002), - (4, 2, 10, -1.9381790000000001), - (5, 0, 2, -0.59633899999999995), - (5, 1, 5, -0.26790399999999998)]), - 'In': (49, - [(1, 0, 2, -983.64744499999995), - (2, 0, 2, -144.07835700000001), - (2, 1, 6, -134.62884500000001), - (3, 0, 2, -27.220600000000001), - (3, 1, 6, -23.345777999999999), - (3, 2, 10, -16.139823), - (4, 0, 2, -4.0626389999999999), - (4, 1, 6, -2.7958319999999999), - (4, 2, 10, -0.73048100000000005), - (5, 0, 2, -0.29049700000000001), - (5, 1, 1, -0.101782)]), - 'Ir': (77, - [(1, 0, 2, -2543.7613419999998), - (2, 0, 2, -422.159424), - (2, 1, 6, -405.52683400000001), - (3, 0, 2, -97.923080999999996), - (3, 1, 6, -90.108427000000006), - (3, 2, 10, -75.485027000000002), - (4, 0, 2, -20.29429), - (4, 1, 6, -16.966577999999998), - (4, 2, 10, -10.856593), - (5, 0, 2, -2.9091740000000001), - (5, 1, 6, -1.8833489999999999), - (4, 3, 14, -2.7383389999999999), - (5, 2, 7, -0.33518900000000001), - (6, 0, 2, -0.19551099999999999)]), - 'K': (19, - [(1, 0, 2, -128.41495699999999), - (2, 0, 2, -12.839001), - (2, 1, 6, -10.283851), - (3, 0, 2, -1.2818970000000001), - (3, 1, 6, -0.69377599999999995), - (4, 0, 1, -0.088815000000000005)]), - 'Kr': (36, - [(1, 0, 2, -509.98298899999998), - (2, 0, 2, -66.285953000000006), - (2, 1, 6, -60.017327999999999), - (3, 0, 2, -9.3151919999999997), - (3, 1, 6, -7.0866340000000001), - (3, 2, 10, -3.074109), - (4, 0, 2, -0.82057400000000003), - (4, 1, 6, -0.34633999999999998)]), - 'La': (57, - [(1, 0, 2, -1355.6224460000001), - (2, 0, 2, -209.83115100000001), - (2, 1, 6, -198.325243), - (3, 0, 2, -44.856282999999998), - (3, 1, 6, -39.895837999999998), - (3, 2, 10, -30.626695999999999), - (4, 0, 2, -9.0005430000000004), - (4, 1, 6, -7.1677239999999998), - (4, 2, 10, -3.9580099999999998), - (5, 0, 2, -1.3249359999999999), - (5, 1, 6, -0.82449799999999995), - (5, 2, 1, -0.14108499999999999), - (6, 0, 2, -0.13223299999999999)]), - 'Li': (3, [(1, 0, 2, -1.8785639999999999), (2, 0, 1, -0.10553999999999999)]), - 'Lu': (71, - [(1, 0, 2, -2146.8853509999999), - (2, 0, 2, -349.39049199999999), - (2, 1, 6, -334.33090199999998), - (3, 0, 2, -78.462397999999993), - (3, 1, 6, -71.538779000000005), - (3, 2, 10, -58.592981999999999), - (4, 0, 2, -15.08337), - (4, 1, 6, -12.250904), - (4, 2, 10, -7.1133639999999998), - (5, 0, 2, -1.8720859999999999), - (5, 1, 6, -1.111991), - (4, 3, 14, -0.56809600000000005), - (5, 2, 1, -0.103686), - (6, 0, 2, -0.155112)]), - 'Mg': (12, - [(1, 0, 2, -45.973166999999997), - (2, 0, 2, -2.9037459999999999), - (2, 1, 6, -1.7189700000000001), - (3, 0, 2, -0.175427)]), - 'Mn': (25, - [(1, 0, 2, -233.696912), - (2, 0, 2, -26.866645999999999), - (2, 1, 6, -23.066296999999999), - (3, 0, 2, -3.0766369999999998), - (3, 1, 6, -1.9914499999999999), - (3, 2, 5, -0.26654), - (4, 0, 2, -0.191136)]), - 'Mo': (42, - [(1, 0, 2, -709.23211900000001), - (2, 0, 2, -98.503637999999995), - (2, 1, 6, -90.791540999999995), - (3, 0, 2, -16.681545), - (3, 1, 6, -13.71481), - (3, 2, 10, -8.2577210000000001), - (4, 0, 2, -2.2348240000000001), - (4, 1, 6, -1.39005), - (4, 2, 5, -0.15334700000000001), - (5, 0, 1, -0.14788000000000001)]), - 'N': (7, - [(1, 0, 2, -14.011501000000001), - (2, 0, 2, -0.67615099999999995), - (2, 1, 3, -0.26629700000000001)]), - 'Na': (11, - [(1, 0, 2, -37.719974999999998), - (2, 0, 2, -2.0634009999999998), - (2, 1, 6, -1.0606359999999999), - (3, 0, 1, -0.10341500000000001)]), - 'Nb': (41, - [(1, 0, 2, -673.76252999999997), - (2, 0, 2, -92.740859999999998), - (2, 1, 6, -85.272175000000004), - (3, 0, 2, -15.393727), - (3, 1, 6, -12.552854999999999), - (3, 2, 10, -7.3398389999999996), - (4, 0, 2, -2.0366930000000001), - (4, 1, 6, -1.250049), - (4, 2, 4, -0.125252), - (5, 0, 1, -0.14427200000000001)]), - 'Nd': (60, - [(1, 0, 2, -1509.6989550000001), - (2, 0, 2, -236.613572), - (2, 1, 6, -224.35181600000001), - (3, 0, 2, -51.161262999999998), - (3, 1, 6, -45.791218999999998), - (3, 2, 10, -35.754514999999998), - (4, 0, 2, -10.000890999999999), - (4, 1, 6, -7.9678199999999997), - (4, 2, 10, -4.377027), - (5, 0, 2, -1.3349340000000001), - (5, 1, 6, -0.79850299999999996), - (4, 3, 4, -0.179508), - (6, 0, 2, -0.12579599999999999)]), - 'Ne': (10, - [(1, 0, 2, -30.305855000000001), - (2, 0, 2, -1.3228089999999999), - (2, 1, 6, -0.49803399999999998)]), - 'Ni': (28, - [(1, 0, 2, -297.87082400000003), - (2, 0, 2, -35.312111999999999), - (2, 1, 6, -30.868027000000001), - (3, 0, 2, -3.950717), - (3, 1, 6, -2.5941580000000002), - (3, 2, 8, -0.34869899999999998), - (4, 0, 2, -0.21076400000000001)]), - 'O': (8, - [(1, 0, 2, -18.758244999999999), - (2, 0, 2, -0.87136199999999997), - (2, 1, 4, -0.33838099999999999)]), - 'Os': (76, - [(1, 0, 2, -2475.238617), - (2, 0, 2, -409.52239600000001), - (2, 1, 6, -393.15408000000002), - (3, 0, 2, -94.501323999999997), - (3, 1, 6, -86.837046999999998), - (3, 2, 10, -72.497183000000007), - (4, 0, 2, -19.362527), - (4, 1, 6, -16.119671), - (4, 2, 10, -10.176081999999999), - (5, 0, 2, -2.7382930000000001), - (5, 1, 6, -1.757404), - (4, 3, 14, -2.3211750000000002), - (5, 2, 6, -0.29679100000000003), - (6, 0, 2, -0.19148899999999999)]), - 'P': (15, - [(1, 0, 2, -76.061897000000002), - (2, 0, 2, -6.3293460000000001), - (2, 1, 6, -4.5766169999999997), - (3, 0, 2, -0.51236400000000004), - (3, 1, 3, -0.20608000000000001)]), - 'Pa': (91, - [(1, 0, 2, -3606.3336290000002), - (2, 0, 2, -623.87043100000005), - (2, 1, 6, -603.47027800000001), - (3, 0, 2, -156.46674200000001), - (3, 1, 6, -146.48567800000001), - (3, 2, 10, -127.78116799999999), - (4, 0, 2, -39.064506999999999), - (4, 1, 6, -34.482930000000003), - (4, 2, 10, -25.933121), - (5, 0, 2, -8.4634630000000008), - (5, 1, 6, -6.7098209999999998), - (4, 3, 14, -14.105746999999999), - (5, 2, 10, -3.6599279999999998), - (6, 0, 2, -1.2872319999999999), - (6, 1, 6, -0.79975600000000002), - (5, 3, 2, -0.31681300000000001), - (6, 2, 1, -0.142481), - (7, 0, 2, -0.12965299999999999)]), - 'Pb': (82, - [(1, 0, 2, -2901.0780610000002), - (2, 0, 2, -488.84333500000002), - (2, 1, 6, -470.87778500000002), - (3, 0, 2, -116.52685200000001), - (3, 1, 6, -107.950391), - (3, 2, 10, -91.889923999999993), - (4, 0, 2, -25.753329999999998), - (4, 1, 6, -21.990563999999999), - (4, 2, 10, -15.030025999999999), - (5, 0, 2, -4.2067969999999999), - (5, 1, 6, -2.9416570000000002), - (4, 3, 14, -5.5925320000000003), - (5, 2, 10, -0.902393), - (6, 0, 2, -0.35718699999999998), - (6, 1, 2, -0.14183100000000001)]), - 'Pd': (46, - [(1, 0, 2, -860.13490899999999), - (2, 0, 2, -123.10507800000001), - (2, 1, 6, -114.408286), - (3, 0, 2, -22.060898000000002), - (3, 1, 6, -18.580798000000001), - (3, 2, 10, -12.132197), - (4, 0, 2, -2.889173), - (4, 1, 6, -1.815215), - (4, 2, 10, -0.160771)]), - 'Pm': (61, - [(1, 0, 2, -1562.980284), - (2, 0, 2, -245.97054800000001), - (2, 1, 6, -233.45511400000001), - (3, 0, 2, -53.429310999999998), - (3, 1, 6, -47.921132), - (3, 2, 10, -37.625433000000001), - (4, 0, 2, -10.422756), - (4, 1, 6, -8.3204949999999993), - (4, 2, 10, -4.5968220000000004), - (5, 0, 2, -1.3722650000000001), - (5, 1, 6, -0.81770200000000004), - (4, 3, 5, -0.200159), - (6, 0, 2, -0.127053)]), - 'Po': (84, - [(1, 0, 2, -3050.988417), - (2, 0, 2, -517.27584300000001), - (2, 1, 6, -498.77192000000002), - (3, 0, 2, -124.783683), - (3, 1, 6, -115.89838399999999), - (3, 2, 10, -99.256067999999999), - (4, 0, 2, -28.422540000000001), - (4, 1, 6, -24.481337), - (4, 2, 10, -17.173307000000001), - (5, 0, 2, -5.0274470000000004), - (5, 1, 6, -3.6553819999999999), - (4, 3, 14, -7.206499), - (5, 2, 10, -1.386458), - (6, 0, 2, -0.49352800000000002), - (6, 1, 4, -0.217889)]), - 'Pr': (59, - [(1, 0, 2, -1457.3380669999999), - (2, 0, 2, -227.42636300000001), - (2, 1, 6, -215.41831300000001), - (3, 0, 2, -48.924993999999998), - (3, 1, 6, -43.692548000000002), - (3, 2, 10, -33.913995999999997), - (4, 0, 2, -9.5774469999999994), - (4, 1, 6, -7.6131080000000004), - (4, 2, 10, -4.1542279999999998), - (5, 0, 2, -1.296106), - (5, 1, 6, -0.77804600000000002), - (4, 3, 3, -0.155138), - (6, 0, 2, -0.12446500000000001)]), - 'Pt': (78, - [(1, 0, 2, -2613.096532), - (2, 0, 2, -434.858003), - (2, 1, 6, -417.96053000000001), - (3, 0, 2, -101.274869), - (3, 1, 6, -93.309107999999995), - (3, 2, 10, -78.400271000000004), - (4, 0, 2, -21.110651000000001), - (4, 1, 6, -17.697296999999999), - (4, 2, 10, -11.419476), - (5, 0, 2, -2.950526), - (5, 1, 6, -1.8842559999999999), - (4, 3, 14, -3.038049), - (5, 2, 9, -0.27363399999999999), - (6, 0, 1, -0.16130800000000001)]), - 'Ra': (88, - [(1, 0, 2, -3362.7365629999999), - (2, 0, 2, -577.10120800000004), - (2, 1, 6, -557.51321399999995), - (3, 0, 2, -142.63242600000001), - (3, 1, 6, -133.12325000000001), - (3, 2, 10, -115.306476), - (4, 0, 2, -34.525627999999998), - (4, 1, 6, -30.221208000000001), - (4, 2, 10, -22.208124999999999), - (5, 0, 2, -7.1391369999999998), - (5, 1, 6, -5.5472029999999997), - (4, 3, 14, -11.181066), - (5, 2, 10, -2.8198530000000002), - (6, 0, 2, -1.05135), - (6, 1, 6, -0.63467399999999996), - (7, 0, 2, -0.113732)]), - 'Rb': (37, - [(1, 0, 2, -540.95711500000004), - (2, 0, 2, -71.291201999999998), - (2, 1, 6, -64.784678), - (3, 0, 2, -10.513861), - (3, 1, 6, -8.1654160000000005), - (3, 2, 10, -3.915508), - (4, 0, 2, -1.135051), - (4, 1, 6, -0.59216999999999997), - (5, 0, 1, -0.085375000000000006)]), - 'Re': (75, - [(1, 0, 2, -2407.6655719999999), - (2, 0, 2, -397.08770700000002), - (2, 1, 6, -380.98286899999999), - (3, 0, 2, -91.149192999999997), - (3, 1, 6, -83.634578000000005), - (3, 2, 10, -69.576759999999993), - (4, 0, 2, -18.454325000000001), - (4, 1, 6, -15.295495000000001), - (4, 2, 10, -9.5168160000000004), - (5, 0, 2, -2.567348), - (5, 1, 6, -1.631227), - (4, 3, 14, -1.9250799999999999), - (5, 2, 5, -0.25863900000000001), - (6, 0, 2, -0.186859)]), - 'Rh': (45, - [(1, 0, 2, -821.13677299999995), - (2, 0, 2, -116.80695), - (2, 1, 6, -108.357665), - (3, 0, 2, -20.765602999999999), - (3, 1, 6, -17.415299000000001), - (3, 2, 10, -11.21725), - (4, 0, 2, -2.8255050000000002), - (4, 1, 6, -1.8064560000000001), - (4, 2, 8, -0.239422), - (5, 0, 1, -0.15462400000000001)]), - 'Rn': (86, - [(1, 0, 2, -3204.756288), - (2, 0, 2, -546.57795999999996), - (2, 1, 6, -527.53302499999995), - (3, 0, 2, -133.36914400000001), - (3, 1, 6, -124.17286199999999), - (3, 2, 10, -106.94500600000001), - (4, 0, 2, -31.230803999999999), - (4, 1, 6, -27.108985000000001), - (4, 2, 10, -19.449994), - (5, 0, 2, -5.8896829999999998), - (5, 1, 6, -4.4087019999999999), - (4, 3, 14, -8.9533179999999994), - (5, 2, 10, -1.9113290000000001), - (6, 0, 2, -0.62656999999999996), - (6, 1, 6, -0.29318)]), - 'Ru': (44, - [(1, 0, 2, -782.91862100000003), - (2, 0, 2, -110.53605399999999), - (2, 1, 6, -102.33364899999999), - (3, 0, 2, -19.366692), - (3, 1, 6, -16.145216999999999), - (3, 2, 10, -10.195668), - (4, 0, 2, -2.6283629999999998), - (4, 1, 6, -1.6675489999999999), - (4, 2, 7, -0.21037500000000001), - (5, 0, 1, -0.152834)]), - 'S': (16, - [(1, 0, 2, -87.789936999999995), - (2, 0, 2, -7.6999399999999998), - (2, 1, 6, -5.7512569999999998), - (3, 0, 2, -0.63091200000000003), - (3, 1, 4, -0.26167600000000002)]), - 'Sb': (51, - [(1, 0, 2, -1070.8234950000001), - (2, 0, 2, -159.17174499999999), - (2, 1, 6, -149.214271), - (3, 0, 2, -31.098241999999999), - (3, 1, 6, -26.956184), - (3, 2, 10, -19.239895000000001), - (4, 0, 2, -5.0496400000000001), - (4, 1, 6, -3.646579), - (4, 2, 10, -1.2973380000000001), - (5, 0, 2, -0.44560499999999997), - (5, 1, 3, -0.18562300000000001)]), - 'Sc': (21, - [(1, 0, 2, -160.18410900000001), - (2, 0, 2, -17.206464), - (2, 1, 6, -14.240005999999999), - (3, 0, 2, -1.988378), - (3, 1, 6, -1.2331650000000001), - (3, 2, 1, -0.13108), - (4, 0, 2, -0.15647800000000001)]), - 'Se': (34, - [(1, 0, 2, -451.30025799999999), - (2, 0, 2, -57.311948000000001), - (2, 1, 6, -51.514387999999997), - (3, 0, 2, -7.547186), - (3, 1, 6, -5.5535170000000003), - (3, 2, 10, -2.0113919999999998), - (4, 0, 2, -0.62124800000000002), - (4, 1, 4, -0.245806)]), - 'Si': (14, - [(1, 0, 2, -65.184426000000002), - (2, 0, 2, -5.075056), - (2, 1, 6, -3.5149379999999999), - (3, 0, 2, -0.39813900000000002), - (3, 1, 2, -0.15329300000000001)]), - 'Sm': (62, - [(1, 0, 2, -1617.1834260000001), - (2, 0, 2, -255.49884599999999), - (2, 1, 6, -242.729726), - (3, 0, 2, -55.731133), - (3, 1, 6, -50.08426), - (3, 2, 10, -39.528655999999998), - (4, 0, 2, -10.844666999999999), - (4, 1, 6, -8.6726849999999995), - (4, 2, 10, -4.814978), - (5, 0, 2, -1.408552), - (5, 1, 6, -0.83598700000000004), - (4, 3, 6, -0.21776000000000001), - (6, 0, 2, -0.12825900000000001)]), - 'Sn': (50, - [(1, 0, 2, -1026.7621690000001), - (2, 0, 2, -151.523991), - (2, 1, 6, -141.82109299999999), - (3, 0, 2, -29.125969000000001), - (3, 1, 6, -25.117913000000001), - (3, 2, 10, -17.657276), - (4, 0, 2, -4.546335), - (4, 1, 6, -3.2119979999999999), - (4, 2, 10, -1.0049520000000001), - (5, 0, 2, -0.36934899999999998), - (5, 1, 2, -0.14445)]), - 'Sr': (38, - [(1, 0, 2, -572.87016900000003), - (2, 0, 2, -76.491822999999997), - (2, 1, 6, -69.745941000000002), - (3, 0, 2, -11.771585), - (3, 1, 6, -9.3018630000000009), - (3, 2, 10, -4.8134980000000001), - (4, 0, 2, -1.455317), - (4, 1, 6, -0.84448900000000005), - (5, 0, 2, -0.13179299999999999)]), - 'Ta': (73, - [(1, 0, 2, -2275.3713870000001), - (2, 0, 2, -372.82872400000002), - (2, 1, 6, -357.248334), - (3, 0, 2, -84.658467000000002), - (3, 1, 6, -77.440942000000007), - (3, 2, 10, -63.942520999999999), - (4, 0, 2, -16.713336999999999), - (4, 1, 6, -13.719810000000001), - (4, 2, 10, -8.2658480000000001), - (5, 0, 2, -2.2238069999999999), - (5, 1, 6, -1.37653), - (4, 3, 14, -1.1993469999999999), - (5, 2, 3, -0.18246399999999999), - (6, 0, 2, -0.174814)]), - 'Tb': (65, - [(1, 0, 2, -1785.331942), - (2, 0, 2, -285.121013), - (2, 1, 6, -271.59058499999998), - (3, 0, 2, -62.851562999999999), - (3, 1, 6, -56.785113000000003), - (3, 2, 10, -45.443863), - (4, 0, 2, -12.120486), - (4, 1, 6, -9.7356370000000005), - (4, 2, 10, -5.4676619999999998), - (5, 0, 2, -1.5136689999999999), - (5, 1, 6, -0.88722999999999996), - (4, 3, 9, -0.25631100000000001), - (6, 0, 2, -0.13167699999999999)]), - 'Tc': (43, - [(1, 0, 2, -745.74202400000001), - (2, 0, 2, -104.567508), - (2, 1, 6, -96.610209999999995), - (3, 0, 2, -18.135303), - (3, 1, 6, -15.041738), - (3, 2, 10, -9.3398599999999998), - (4, 0, 2, -2.5507119999999999), - (4, 1, 6, -1.64323), - (4, 2, 5, -0.270262), - (5, 0, 2, -0.18363599999999999)]), - 'Te': (52, - [(1, 0, 2, -1115.831819), - (2, 0, 2, -167.02177599999999), - (2, 1, 6, -156.808583), - (3, 0, 2, -33.137484999999998), - (3, 1, 6, -28.860685), - (3, 2, 10, -20.887801), - (4, 0, 2, -5.5728460000000002), - (4, 1, 6, -4.1000839999999998), - (4, 2, 10, -1.6083810000000001), - (5, 0, 2, -0.52099700000000004), - (5, 1, 4, -0.22659399999999999)]), - 'Th': (90, - [(1, 0, 2, -3524.4390520000002), - (2, 0, 2, -608.35095799999999), - (2, 1, 6, -588.21811200000002), - (3, 0, 2, -152.07974100000001), - (3, 1, 6, -142.25581), - (3, 2, 10, -123.846396), - (4, 0, 2, -37.814093999999997), - (4, 1, 6, -33.325251999999999), - (4, 2, 10, -24.955183999999999), - (5, 0, 2, -8.2870570000000008), - (5, 1, 6, -6.5828100000000003), - (4, 3, 14, -13.397389), - (5, 2, 10, -3.6257290000000002), - (6, 0, 2, -1.333769), - (6, 1, 6, -0.84692100000000003), - (6, 2, 2, -0.17289599999999999), - (7, 0, 2, -0.13587199999999999)]), - 'Ti': (22, - [(1, 0, 2, -177.27664300000001), - (2, 0, 2, -19.457901), - (2, 1, 6, -16.285339), - (3, 0, 2, -2.2580070000000001), - (3, 1, 6, -1.422947), - (3, 2, 2, -0.17000999999999999), - (4, 0, 2, -0.167106)]), - 'Tl': (81, - [(1, 0, 2, -2827.5694079999998), - (2, 0, 2, -474.95336800000001), - (2, 1, 6, -457.25597099999999), - (3, 0, 2, -112.52218000000001), - (3, 1, 6, -104.099296), - (3, 2, 10, -88.328299000000001), - (4, 0, 2, -24.471512000000001), - (4, 1, 6, -20.797077999999999), - (4, 2, 10, -14.008848), - (5, 0, 2, -3.811512), - (5, 1, 6, -2.5987300000000002), - (4, 3, 14, -4.8357469999999996), - (5, 2, 10, -0.67454400000000003), - (6, 0, 2, -0.28502), - (6, 1, 1, -0.101507)]), - 'Tm': (69, - [(1, 0, 2, -2022.4716080000001), - (2, 0, 2, -327.05712), - (2, 1, 6, -312.51060799999999), - (3, 0, 2, -72.873752999999994), - (3, 1, 6, -66.239338000000004), - (3, 2, 10, -53.835493999999997), - (4, 0, 2, -13.865665), - (4, 1, 6, -11.187151), - (4, 2, 10, -6.3503069999999999), - (5, 0, 2, -1.6499900000000001), - (5, 1, 6, -0.95074800000000004), - (4, 3, 13, -0.28311999999999998), - (6, 0, 2, -0.13595299999999999)]), - 'U': (92, - [(1, 0, 2, -3689.355141), - (2, 0, 2, -639.778728), - (2, 1, 6, -619.10855000000004), - (3, 0, 2, -161.11807300000001), - (3, 1, 6, -150.97898000000001), - (3, 2, 10, -131.97735800000001), - (4, 0, 2, -40.528084), - (4, 1, 6, -35.853321000000001), - (4, 2, 10, -27.123211999999999), - (5, 0, 2, -8.8240890000000007), - (5, 1, 6, -7.0180920000000002), - (4, 3, 14, -15.02746), - (5, 2, 10, -3.8661750000000001), - (6, 0, 2, -1.325976), - (6, 1, 6, -0.82253799999999999), - (5, 3, 3, -0.36654300000000001), - (6, 2, 1, -0.14319000000000001), - (7, 0, 2, -0.13094800000000001)]), - 'V': (23, - [(1, 0, 2, -195.22401400000001), - (2, 0, 2, -21.815346000000002), - (2, 1, 6, -18.435189000000001), - (3, 0, 2, -2.526904), - (3, 1, 6, -1.6105160000000001), - (3, 2, 3, -0.20463400000000001), - (4, 0, 2, -0.17596800000000001)]), - 'W': (74, - [(1, 0, 2, -2341.0428870000001), - (2, 0, 2, -384.856157), - (2, 1, 6, -369.01397300000002), - (3, 0, 2, -87.867791999999994), - (3, 1, 6, -80.502101999999994), - (3, 2, 10, -66.724787000000006), - (4, 0, 2, -17.570796999999999), - (4, 1, 6, -14.495101999999999), - (4, 2, 10, -8.8796929999999996), - (5, 0, 2, -2.3960180000000002), - (5, 1, 6, -1.5044569999999999), - (4, 3, 14, -1.550835), - (5, 2, 4, -0.22060299999999999), - (6, 0, 2, -0.18141299999999999)]), - 'Xe': (54, - [(1, 0, 2, -1208.688993), - (2, 0, 2, -183.327495), - (2, 1, 6, -172.599583), - (3, 0, 2, -37.415453999999997), - (3, 1, 6, -32.867041999999998), - (3, 2, 10, -24.378229999999999), - (4, 0, 2, -6.6783400000000004), - (4, 1, 6, -5.0638019999999999), - (4, 2, 10, -2.2866659999999999), - (5, 0, 2, -0.67208599999999996), - (5, 1, 6, -0.30983500000000003)]), - 'Y': (39, - [(1, 0, 2, -605.631981), - (2, 0, 2, -81.789102), - (2, 1, 6, -74.803201000000001), - (3, 0, 2, -12.992217), - (3, 1, 6, -10.399926000000001), - (3, 2, 10, -5.6714989999999998), - (4, 0, 2, -1.6971240000000001), - (4, 1, 6, -1.0244899999999999), - (4, 2, 1, -0.108691), - (5, 0, 2, -0.150727)]), - 'Yb': (70, - [(1, 0, 2, -2084.0693889999998), - (2, 0, 2, -337.97897599999999), - (2, 1, 6, -323.17821900000001), - (3, 0, 2, -75.47663), - (3, 1, 6, -68.698655000000002), - (3, 2, 10, -56.026314999999997), - (4, 0, 2, -14.312075999999999), - (4, 1, 6, -11.558246), - (4, 2, 10, -6.5749630000000003), - (5, 0, 2, -1.683886), - (5, 1, 6, -0.96613700000000002), - (4, 3, 14, -0.286408), - (6, 0, 2, -0.136989)]), - 'Zn': (30, - [(1, 0, 2, -344.96975600000002), - (2, 0, 2, -41.531323), - (2, 1, 6, -36.648764999999997), - (3, 0, 2, -4.5730409999999999), - (3, 1, 6, -3.0223629999999999), - (3, 2, 10, -0.39894400000000002), - (4, 0, 2, -0.22272500000000001)]), - 'Zr': (40, - [(1, 0, 2, -639.292236), - (2, 0, 2, -87.237061999999995), - (2, 1, 6, -80.010042999999996), - (3, 0, 2, -14.230432), - (3, 1, 6, -11.514415), - (3, 2, 10, -6.5446429999999998), - (4, 0, 2, -1.918971), - (4, 1, 6, -1.1865969999999999), - (4, 2, 2, -0.150673), - (5, 0, 2, -0.16239100000000001)])} - -# End of computer generated code: - - -class AtomicData: - def __init__(self, name, Z, mass, radius, configuration): - self.name = name - self.Z = Z - self.mass = mass - self.radius = radius - self.configuration = configuration - - -def GetOccupations(symbol): - Z = Ztable[symbol] - configuration = configurations[Z] - if configuration[0][0] == '[': - occupations = GetOccupations(configuration[0][1:-1]) - configuration = configuration[1:] - else: - occupations = [] - for s in configuration: - occupations.append((s[:2], int(s[3:]))) - return occupations - - -if __name__ == '__main__': - import pprint - path = '/scratch/jensj/dftdata/' - Ztable = {} - configurations = [['X', '']] - Z = 1 - for line in open(path + 'configurations'): - if len(line) > 1 and line[1].isdigit(): - line = line[:44].split() - symbol = line[1] - Ztable[symbol] = Z - configurations.append(line[2:]) - Z += 1 - - dftdata = {} - spdf = {'s': 0, 'p': 1, 'd': 2, 'f': 3} - for symbol, Z in Ztable.items(): - occupations = GetOccupations(symbol) - f = open(path + 'LDA/neutrals/%02d%s' % (Z, symbol), 'r') - for n in range(5): - f.readline() - epsilons = {} - for line in f: - state, eps = line.split() - epsilons[state] = float(eps) - nloe = [] - for state, occ in occupations: - n = int(state[0]) - l = spdf[state[1]] - eps = epsilons[state] - nloe.append((n, l, occ, eps)) - dftdata[symbol] = (Z, nloe) - print '# Computer generated code:' - print - print 'configurations = ', - pprint.pprint(dftdata) - print diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/fitting.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/fitting.py deleted file mode 100644 index ec13fc1..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/fitting.py +++ /dev/null @@ -1,820 +0,0 @@ -from hotbit import Element -from hotbit import Hotbit -import numpy as np -from ase.units import Bohr,Hartree -from hotbit import Atoms -from ase.io import read -from ase.io.trajectory import PickleTrajectory -from box import NullCalculator -from copy import copy -from sys import stdout -import os - - - - - -class RepulsiveFitting: - - def __init__(self,symbol1,symbol2,r_cut,s=None,k=3,txt=None,tol=0.005): - """ - Class for fitting the short-range repulsive potential. - - - Fitting uses eV and Angstrom also internally, only the - output file (.par) is in Hartrees and Bohrs. The weights - used in the methods append_* are the inverse of standard - deviations (weight=1/sigma). For more details of the - approach used here, look at Pekka Koskinen and Ville Makinen, - Computational Materials Science 47, 237 (2009), page 244. - - Parameters: - =========== - symbol1: chemical symbol for the first element - symbol2: chemical symbol for the second element - txt: output filename or None for stdout - r_cut: the repulsion cutoff - s: smoothing parameter. If None, use s = N - np.sqrt(2*N) - where N is the number of data points. - k: order of spline for V_rep'(R), cubic by default. - Uses smaller order if not enough points to fit V_rep'(R) - tol: tolerance for distances still considered the same - - - Usage: - ====== - 1. Initialize class - * rep = RepulsiveFitting('Au','Au',r_cut=3.3,s=100) - - 2. Collect data from structures. The data collected is points r_i - and V_rep'(r_i), that is, repulsive distance and the force. - Use the append_* methods. - * rep.append_dimer(weight=0.5,calc=calc0,R=2.49,comment='Au2') - * rep.append_energy_curve(weight=1.0,calc=calc0, - traj='dimer_curve.traj',label='DFT dimer',comment='dimer curve') - - 3. Given the set of points [r_i,V_rep'(r_i)], fit a spline with given order. - * fit() - Fitting will produce a spline-interpolated V_rep'(r), which is then integrated - to given spline-interpolated V_rep(r). - - 4. Output repulsion into a file and plot the repulsion - * rep.write_par('Au_Au_no_repulsion.par',filename='Au_Au_repulsion.par') - * rep.plot('AuAu_repulsion.pdf') - - """ - self.elm1=Element(symbol1) - self.elm2=Element(symbol2) - self.sym1=self.elm1.get_symbol() - self.sym2=self.elm2.get_symbol() - self.r_cut = r_cut - self.s = s - self.k = k - self.tol = tol - - self.r_dimer = None - self.deriv=[] - self.comments='' - self.scale=1.025 # scaling factor for scalable systems - self.structures = [] - self.v=None - - if txt==None: - self.txt=stdout - else: - self.txt=open(txt,'a') - print>>self.txt, 'Fitting repulsion curve between %s and %s' % (self.sym1, self.sym2) - self.colors = ['red','green','blue','cyan','yellow','orange','magenta','pink','black'] - self.colori = 0 - - - def __call__(self,r,der=0): - """ - Return repulsion or its derivative. - - This is the already fitted and integrated V_rep(R). - - parameters: - =========== - r: radius (Angstroms) - der: der=0 for V_rep(r) - der=1 for V_rep'(r) - """ - if self.v==None: - raise AssertionError('Repulsion is not yet fitted') - return self.v(r,der=der) - - - def plot(self, filename=None): - """ - Plot vrep and derivative together with fit info. - - parameters: - =========== - filename: graphics output file name - """ - try: - import pylab as pl - except: - raise AssertionError('pylab could not be imported') - r=np.linspace(0,self.r_cut) - v=[self(x,der=0) for x in r] - vp=[self(x,der=1) for x in r] - rmin=0.95*min([d[0] for d in self.deriv]) - rmax = 1.1*self.r_cut - - fig=pl.figure() - pl.subplots_adjust(wspace=0.25) - - # Vrep - pl.subplot(1,2,1) - pl.ylabel(r'$V_{rep}(r)$ (eV)') - pl.xlabel(r'$r$ ($\AA$)') - if self.r_dimer!=None: - pl.axvline(x=self.r_dimer,c='r',ls=':') - pl.axvline(x=self.r_cut,c='r',ls=':') - pl.plot(r,v) - pl.ylim(ymin=0,ymax=self(rmin)) - pl.xlim(xmin=rmin, xmax=self.r_cut) - - # Vrep' - pl.subplot(1,2,2) - pl.ylabel(r'$dV_{rep}(r)/dr$ (eV/$\AA$)') - pl.xlabel(r'$r$ ($\AA$)') - pl.plot(r,vp,label=r'$dV_{rep}(r)/dr$') - for s in self.deriv: - pl.scatter( [s[0]],[s[1]],s=100*s[2],c=s[3],label=s[4]) - pl.axvline(x=self.r_cut,c='r',ls=':') - if self.r_dimer!=None: - pl.axvline(x=self.r_dimer,c='r',ls=':') - - ymin = 0 - for point in self.deriv: - if rmin<=point[0]<=rmax: ymin = min(ymin,point[1]) - ymax = np.abs(ymin)*0.1 - pl.axhline(0,ls='--',c='k') - if self.r_dimer!=None: - pl.text(self.r_dimer, ymax, r'$r_{dimer}$') - pl.text(self.r_cut, ymax, r'$r_{cut}$') - pl.xlim(xmin=rmin, xmax=rmax) - pl.ylim(ymin=ymin, ymax=ymax) - #pl.subtitle('Fitting for %s and %s' % (self.sym1, self.sym2)) - pl.rc('font', size=10) - pl.rc('legend',fontsize=8) - pl.legend(loc=4) - file = '%s_%s_repulsion.pdf' % (self.sym1, self.sym2) - if filename!=None: - file=filename - pl.savefig(file) - pl.clf() - - - def add_comment(self,s=None): - """ - Append some comment for par-file. - - These comments will end up in Hotbit's output logfile each time - fitted repulsion is used in calculations. For this reason, - use as short and concise comments as possible. - - parameters: - =========== - s: comment as a string - """ - if s in [None, '']: - return - add='|' - if len(self.comments)==0: - add='' - self.comments+=add+s - - - def fit(self): - """ - Fit spline into {r, V_rep'(r)} -data points. - """ - from scipy.interpolate import splrep, splev - self.k = min(len(self.deriv),self.k) - - x = np.array([self.deriv[i][0] for i in range(len(self.deriv))]) - y = np.array([self.deriv[i][1] for i in range(len(self.deriv))]) - w = np.array([self.deriv[i][2] for i in range(len(self.deriv))]) - # sort values so that x is in ascending order - indices = x.argsort() - x, y, w = x[indices], y[indices], w[indices] - x, y, w = self._group_closeby_points(x,y,w) - # use only points that are closer than r_cut - indices = np.where(x < self.r_cut) - x, y, w = list(x[indices]), list(y[indices]), list(w[indices]) - # force the spline curve to go to zero at x=r_cut - x.append(self.r_cut) - y.append(0.0) - w.append(1E3*max(w)) - if self.s == None: - # from documentation of splrep in scipy.interpolate.fitpack - self.s = len(x) - np.sqrt(2*len(x)) - - print>>self.txt, "\nFitting spline for V_rep'(R) with parameters" - print>>self.txt, " k=%i, s=%0.4f, r_cut=%0.4f\n" %(self.k, self.s, self.r_cut) - tck = splrep(x, y, w, s=self.s, k=self.k) - - def dv_rep(r): - return splev(r, tck) - - v_rep = self._integrate_vrep(dv_rep, self.r_cut) - - def potential(r, der=0): - if der == 0: - return v_rep(r) - elif der == 1: - return dv_rep(r) - else: - raise NotImplementedError("Only 0th and 1st derivatives") - self.v = potential - - - def _group_closeby_points(self, x, y, w): - """ - If there are many y-values with almost the same x-values, - it is impossible to make spline fit to these points. - For these points the y will be the weighted average of - the y-points and the weight is the sum of the weights of - averaged y-points. - """ - accuracy = 4 # the number of decimals to maintain - pseudo_x = np.array(x*10**accuracy, dtype=int) - groups = np.zeros(len(x), dtype=int) - g = 0 - for i in range(1,len(pseudo_x)): - if pseudo_x[i] != pseudo_x[i-1]: - groups[i] = groups[i-1] + 1 - else: - groups[i] = groups[i-1] - new_x = [] - new_y = [] - new_w = [] - for g in range(max(groups)+1): - same = np.where(groups == g) - new_x.append(np.average(x[same])) - new_y.append(np.dot(y[same],w[same])/np.sum(w[same])) - new_w.append(np.sum(w[same])) - return np.array(new_x), np.array(new_y), np.array(new_w) - - - def write_par(self, inputpar, filename=None): - """ - Write the full par-file to file. - - parameters: - =========== - inputpar: the par-file where the repulsion is appended - filename: output file - """ - from time import asctime - import shutil - - if filename==None: - filename = 'repulsion_'+inputpar - - shutil.copy(inputpar, filename) - f = open(filename, 'a') - # add comments - print >> f, "repulsion_comment=" - print >> f, "%s\nparameters r_cut = %0.4f Ang, s = %0.4f, k = %3i" % (asctime(),self.r_cut, self.s, self.k) - if len(self.structures)>1: - print >> f, "The systems used to produce this fit:" - for data in self.structures: - print >> f, "%20s %3s" % (data['filename'], data['charge']) - if len(self.comments) > 0: - print >> f, self.comments - print >> f, '\n\nrepulsion=' - for r in np.linspace(0.1, self.r_cut, 100): - print >> f, r/Bohr, self(r)/Hartree - f.close() - - - def _integrate_vrep(self, dv_rep, r_cut, N=100): - """ - Integrate V'_rep(r) from r_cut to zero to get the V_rep(r) - """ - from box.interpolation import SplineFunction - from scipy.integrate import quadrature - r_g = np.linspace(r_cut, 0, N) - dr = r_g[1] - r_g[0] - v_rep = np.zeros(N) - for i in range(1,len(r_g)): - v_rep[i] = v_rep[i-1] - val, err = quadrature(dv_rep, r_g[i-1], r_g[i], tol=1.0e-12, maxiter=50) - v_rep[i] += val - # SplineFunction wants the x-values in ascending order - return SplineFunction(r_g[::-1], v_rep[::-1]) - - - def _set_calc(self,atoms,calc): - """ - Set calculator for given atoms. - """ - if type(atoms)==type(''): - a = read(atoms) - else: - a = atoms.copy() - c = copy(calc) - a.set_calculator(c) - return a,c - - - def _get_color(self,color): - """ Get next color in line if color==None """ - if color==None: - index = self.colori - self.colori +=1 - if self.colori == len(self.colors): self.colors=0 - return self.colors[index] - else: - return color - - # - # Fitting methods - # - def append_point(self,weight,R,dvrep,comment=None,label=None,color='g'): - """ - Add point to vrep'-fitting. - - parameters: - =========== - weight: fitting weight - R: radius (Angstroms) - vdrep: V_rep'(R) (eV/Angstroms) - comment: fitting comment for par file (replaced by label if None) - label: plotting label (replaced by comment if None) - """ - if comment==None: comment=label - if label==None: label=comment - self.deriv.append([R,dvrep,weight,color,label]) - if comment!='_nolegend_': - self.add_comment(comment) - - - def append_scalable_system(self,weight,calc,atoms,comment=None,label=None,color=None): - """ - Use scalable equilibrium system in repulsion fitting. - - Scalable means that atoms is an equilibrium system, which - has only given bond lengths R, and whose dimensions can be - scaled E_DFT(R), and, because of equilibrium, E_DFT'(R)=0. - Hence - - E_DFT'(R) = E_wr'(R) + N*V_rep'(R) = 0 - - ==> V_rep'(R) = -E_wr'(R)/N - - where E_wr = E_bs + E_coul is the DFTB energy without - repulsion. - - parameters: - =========== - weight: fitting weight - calc: Hotbit calculator (remember charge and k-points) - atoms: filename or ase.Atoms instance - comment: fitting comment for par file (replaced by label if None) - label: plotting label (replaced by comment if None) - color: plotting color - """ - atoms, calc = self._set_calc(atoms,calc) - if comment==None: comment=label - if label==None: label=comment - - e1 = atoms.get_potential_energy() - R, N = self._get_repulsion_distances(calc) - atoms.set_cell( atoms.get_cell()*self.scale, scale_atoms=True ) - e2 = atoms.get_potential_energy() - - dEwr=(e2-e1)/(self.scale*R-R) - color = self._get_color(color) - comment += ';w=%.1f' %weight - self.append_point(weight,R,-dEwr/N,comment,label,color) - print>>self.txt, '\nAdding a scalable system %s with %i bonds at R=%.4f.' %(atoms.get_name(),N,R) - - - def append_dimer(self,weight,calc,R,comment=None,label='dimer',color=None): - """ - Use dimer bond length in fitting. - - parameters: - =========== - weight: fitting weight - calc: Hotbit calculator used in calculation - (remember Gamma-point and charge) - R: dimer bond length (Angstroms) - comment: fitting comment for par-file (replaced by label if None) - label: plotting label (replaced by comment if None) - color: plotting color - """ - if comment==None: comment=label - self.r_dimer = R - atoms = Atoms([self.sym1,self.sym2],[(0,0,0),(R,0,0)],pbc=False) - atoms.center(vacuum=5) - color = self._get_color(color) - self.append_scalable_system(weight,calc,atoms,comment=comment,label=label,color=color) - - - def append_equilibrium_trajectory(self,weight,calc,traj,comment=None,label=None,color=None): - """ - Calculates the V'rep(r) from a given equilibrium trajectory. - - The trajectory is set of three (or more, albeit not necessary) frames - where atoms move near their equilibrium structure. To first approximation, - the energies of these frames ARE THE SAME. This method is then - equivalent to append_energy_curve method for given trajectory, with a flat - energy curve. - * Atoms should move as parallel to the fitted bonds as possible. - * Amplitude should be small enough (say, 0.01 Angstroms) - - - parameters: - =========== - weight: fitting weight - calc: Hotbit calculator (remember charge and k-points) - traj: filename for ASE trajectory (energies need not be defined) - comment: fitting comment for par-file (replaced by comment if None) - label: plotting label (replaced by comment if None) - color: plotting color - """ - traj1 = PickleTrajectory(traj) - atoms2 = traj1[0].copy() - calc2 = NullCalculator() - atoms2.set_calculator(calc2) - tmpfile = '_tmp.traj' - traj2 = PickleTrajectory(tmpfile,'w',atoms2) - for atoms1 in traj1: - atoms2.set_positions(atoms1.get_positions()) - atoms2.get_potential_energy() - traj2.write() - traj2.close() - - self.append_energy_curve(weight,calc,tmpfile,comment,label,color) - os.remove(tmpfile) - if os.path.isfile(tmpfile+'.bak'): - os.remove(tmpfile+'.bak') - - - def append_energy_curve(self,weight,calc,traj,comment=None,label=None,color=None): - """ - Calculates the V'rep(r) from a given ase-trajectory. - - The trajectory can be anything, as long as the ONLY missing energy - from DFTB calculation is N*V_rep(R). Hence - - E_DFT(R) = E_wr(R) + N*V_rep(R) - - E_DFT'(R) - E_wr'(R) - V_rep'(R) = ------------------ , - N - - where R is the nn. distance,N is the number of A-B pairs taken into account, - and E_wr(R) = E_bs(R) + E_coul(R) is the DFTB energy without repulsion. - At least 3 points in energy curve needed, preferably more. - - parameters: - =========== - weight: fitting weight - calc: Hotbit calculator (remember charge and k-points) - traj: filename for ASE trajectory, or PickleTrajectory - object - comment: fitting comment for par-file (replaced by comment if None) - label: plotting label (replaced by comment if None) - color: plotting color - """ - if comment==None: comment=label - if label==None: label=comment - - #if not ( isinstance(traj, type(PickleTrajectory)) or isinstance(traj, list) ): - if not ( isinstance(traj, type(PickleTrajectory)) or isinstance(traj, list) ): - print>>self.txt, "\nAppending energy curve data from %s..." %traj - traj = PickleTrajectory(traj) - else: - print>>self.txt, '\nAppending energy curve data...' - Edft, Ewr, N, R = [], [], [], [] - if len(traj)<3: - raise AssertionError('At least 3 points in energy curve required.') - for atoms in traj: - a, c = self._set_calc(atoms,calc) - e = a.get_potential_energy() - r, n = self._get_repulsion_distances(c) - if n>0 and r>self.txt, "Appended %i points around R=%.4f...%.4f" %(len(N),R.min(),R.max()) - - - def append_homogeneous_cluster(self,weight,calc,atoms,comment=None,label=None,color=None): - """ - Use homonuclear cluster in fitting, even with different bond lengths. - - Construct repulsive forces so that residual forces F_DFT-(F_wr+F_rep), - where F_DFT are DFT forces (zero if cluster in equilibrium), F_wr are - DFTB forces without repulsion, and F_rep are the repulsive forces. - That is, we minimize the function - - sum_i |F_DFT_i - F_WR_i - F_rep_i|^2 - - with respect a and b, where V_rep'(R) = a + b*(r-r_cut). Then, add fitting points - from rmin to rmax, where these values span all pair distances below r_cut - within the cluster. - - Only finite, non-periodic systems can be used. - - parameters: - =========== - weight: fitting weight - calc: Hotbit calculator (remember charge and no k-points) - atoms: filename or ASE.Atoms instance - comment: fitting comment for par-file (replaced by label if None) - label: plotting label (replaced by comment if None) - color: plotting color - """ - if comment==None: comment=label - if label==None: label=comment - if type(atoms)==type(''): - atoms = read(atoms) - - N = len(atoms) - try: - f_DFT = atoms.get_forces() - print>>self.txt, " Use forces" - except: - f_DFT = np.zeros((N,3)) - print>>self.txt, " No forces (equilibrium cluster)" - - atoms, calc = self._set_calc(atoms,calc) - print>>self.txt, "\nAppending homogeneous cluster %s..." % atoms.get_name() - - f_wr = atoms.get_forces() - distances = calc.rep.get_repulsion_distances(self.sym1,self.sym2,self.r_cut) - rmin, rmax = distances.min(), distances.max() - - def dvrep(r,p): - """ Auxiliary first-order polynomial for repulsion derivative """ - return p[0]+p[1]*(r-self.r_cut) - - - def to_minimize(p,atoms,fdft,fwr): - """ Function sum_I |F_DFT_I - F_TB_I|^2 to minimize. """ - N = len(atoms) - pos = atoms.get_positions() - resid = np.zeros((N,3)) - frep = np.zeros((N,3)) - for i in range(N): - for j in range(N): - if i==j: continue - rij = pos[j]-pos[i] - dij = np.linalg.norm(rij) - if dij>self.r_cut: - continue - else: - frep[i] += dvrep(dij,p)*rij/dij - resid = fdft - ( fwr + frep ) - return sum([ np.linalg.norm(resid[i])**2 for i in range(N) ]) - - from scipy.optimize import fmin - p = fmin( to_minimize,[-1.0,5.0],args=(atoms,f_DFT,f_wr),xtol=1E-5,ftol=1E-5 ) - print>>self.txt, ' Cluster: V_rep(R)=%.6f + %.6f (r-%.2f)' %(p[0],p[1],self.r_cut) - - color = self._get_color(color) - np = 6 - rlist = np.linspace(rmin,rmax,np) - for i,r in enumerate(rlist): - if i==0: - com = comment - com += ';w=%.1f' %weight - else: - label = '_nolegend_' - com = None - self.append_point(weight/np.sqrt(np), r, dvrep(r,p), com, label, color) - - - def _get_repulsion_distances(self,calc): - """ - Return distances below r_cut for given system in calculator. - - return: - ======= - R: the mean repulsion distance - N: number of bonds - """ - distances = calc.rep.get_repulsion_distances(self.sym1,self.sym2,self.r_cut) - if len(distances)==0: - return 0.0,distances - R = distances.mean() - rmin, rmax = distances.min(), distances.max() - if rmax - rmin > self.tol: - atoms = calc.get_atoms() - raise AssertionError('Bond lengths in %s are not the same, they vary between %.6f ... %.6f' %(atoms.get_name(),rmin,rmax) ) - N = len(distances) - return R,N - - - def write_fitting_data(self, filename): - import pickle - f = open(filename,'w') - pickle.dump(self.deriv, f) - pickle.dump(self.structures, f) - pickle.dump(self.comments, f) - f.close() - - - def load_fitting_data(self, filename): - import pickle - f = open(filename,'r') - self.deriv = pickle.load(f) - self.structures = pickle.load(f) - self.comments = pickle.load(f) - f.close() - - - def _get_trajs_for_fitting(self): - return self.structures - - - -class ParametrizationTest: - """ - A tool to examine how well your parametrization agrees with - given ase-trajectories. - - trajectories: list of trajectories you want to compare - charges: the charges of the systems in trajectories - """ - - def __init__(self, rf, pars): - from copy import copy - from hotbit import Hotbit - self.pars = pars - self.trajectories = [] - self.calculators = [] - for data in rf._get_trajs_for_fitting(): - filename = data['filename'] - del data['filename'] - c = Hotbit() - for key, value in data.iteritems(): - c.__dict__[key] = data[key] - self.trajectories.append(filename) - self.calculators.append(c) - self.points = [] - self.ref_points = [] - self.colors = ['cyan','red','orange','#8DEE1E','magenta','green','black'] - - def norm_to_isolated_atoms(self, atoms): - """ - Return the constant that can be used to calculate - the binding energy of the system. - """ - delta_E = 0 - for atom in atoms: - delta_E -= self.E_free[atom.symbol] - return delta_E - - - def get_isolated_energies(self, trajs, par): - """ - Return the energies of an isolated atoms. - """ - elements = [] - energies = {} - for t in trajs: - traj = PickleTrajectory(t) - for atom in traj[0]: - if not atom.symbol in elements: - elements.append(atom.symbol) - el1, el2 = par.split("_")[0:2] - for el in elements: - ss = "%s%s" % (el, el) - if el1 == el2 and el1 == el: - tables = {ss:par, 'rest':'default'} - calc = Hotbit(SCC=True, tables=tables) - else: - calc = Hotbit(SCC=True) - atoms = Atoms(ss, ((0,0,0),(200,0,0))) - atoms.center(vacuum=100) - atoms.set_calculator(calc) - energies[el] = atoms.get_potential_energy() / 2 - return energies - - - def compare(self): - """ - Make a comparison for all the systems. - """ - for i_par in range(len(self.pars)): - self.compare_with_par(i_par) - - - def compare_with_par(self, i_par): - """ - Make a comparison to all trajectories with given parameter-file. - The i_par is the index to the self.pars. - """ - - import pylab as pl - - par = self.pars[i_par] - self.E_free = self.get_isolated_energies(self.trajectories, par) - temp = par.split('_') - symbols = "%s%s" % (temp[0],temp[1]) - tables = {symbols:par, 'rest':'default'} - for i_traj, calc in zip(range(len(self.trajectories)), self.calculators): - pl.figure(i_traj) - pl.title(self.trajectories[i_traj]) - if i_par == 0: - self.plot_ref(i_traj) - self.compare_trajectory(i_traj, calc, tables, i_par) - - - def compare_trajectory(self, i_traj, calc, tables, i_par): - """ - Calculate the energies for the frames in the trajectory - and plot them. - """ - frames = [] - energies = [] - trajectory = PickleTrajectory(self.trajectories[i_traj]) - for i, image in enumerate(trajectory): - e_tb = None - try: - atoms = Atoms(image) - c = copy(calc) - c.tables = tables - atoms.set_calculator(c) - e_tb = atoms.get_potential_energy() - except Exception, ex: - print>>self.txt, ex - if e_tb != None: - energies.append(e_tb) - frames.append(i) - delta_E = self.norm_to_isolated_atoms(trajectory[0]) - for i in range(len(energies)): - energies[i] += delta_E - self.plot(frames, energies, i_traj, tables, i_par) - - - def plot_ref(self, i_traj): - """ - Plot the energies of a given trajectory as a function - of the frame number. - """ - - import pylab as pl - - e_dft = [] - traj = PickleTrajectory(self.trajectories[i_traj]) - for image in traj: - e_dft.append(image.get_total_energy()) - pl.plot(e_dft, c='blue', label='DFT-energies') - - - def plot(self, frames, points, i_traj, tables, i_par): - import pylab as pl - par = self.pars[i_par] - color = self.colors[i_par % len(self.colors)] - pl.plot(frames, points, c=color, label='TB-%s' % par) - pl.xlabel('frame #') - pl.ylabel('Energy (eV)') - pl.legend() - - - def run(self): - """ - Make all the comparisons with given trajectories and parameter - files and show the results. - """ - import pylab as pl - self.compare() - pl.show() - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/slako.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/slako.py deleted file mode 100644 index 9b5f11e..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/slako.py +++ /dev/null @@ -1,486 +0,0 @@ -import numpy as np -import sys -from box.timing import Timer -from util import tail_smoothening -from time import asctime -import math -sin=math.sin -cos=math.cos -tan=math.tan -arccos=math.acos -sqrt=math.sqrt -pi=math.pi -zeros=np.zeros - -class SlaterKosterTable: - def __init__(self,ela,elb,txt=None,timing=False): - """ Construct Slater-Koster table for given elements. - - parameters: - ----------- - ela: element objects (KSAllElectron or Element) - elb: element objects (KSAllElectron or Element) - txt: output file object or file name - timing: output of timing summary after calculation - """ - self.ela=ela - self.elb=elb - self.timing=timing - if txt==None: - self.txt=sys.stdout - else: - if type(txt)==type(''): - self.txt=open(txt,'a') - else: - self.txt=txt - self.comment=self.ela.get_comment() - if ela.get_symbol()!=elb.get_symbol(): - self.nel=2 - self.pairs=[(ela,elb),(elb,ela)] - self.elements=[ela,elb] - self.comment+='\n'+self.elb.get_comment() - else: - self.nel=1 - self.pairs=[(ela,elb)] - self.elements=[ela] - self.timer=Timer('SlaterKosterTable',txt=self.txt,enabled=timing) - - print>>self.txt, '\n\n\n\n' - print>>self.txt, '************************************************' - print>>self.txt, 'Slater-Koster table construction for %2s and %2s' %(ela.get_symbol(),elb.get_symbol()) - print>>self.txt, '************************************************' - - def __del__(self): - self.timer.summary() - - - def get_table(self): - """ Return tables. """ - return self.Rgrid, self.tables - - - def smooth_tails(self): - """ Smooth the behaviour of tables near cutoff. """ - for p in range(self.nel): - for i in range(20): - self.tables[p][:,i]=tail_smoothening(self.Rgrid,self.tables[p][:,i]) - - - def write(self,filename=None): - """ Use symbol1_symbol2.par as default. """ - self.smooth_tails() - if filename==None: fn='%s_%s.par' %(self.ela.get_symbol(),self.elb.get_symbol()) - else: fn=filename - f=open(fn,'w') - print>>f, 'slako_comment=' - print>>f, self.get_comment(), '\n\n' - for p,(e1,e2) in enumerate(self.pairs): - print>>f, '%s_%s_table=' %(e1.get_symbol(),e2.get_symbol()) - for i,R in enumerate(self.Rgrid): - print>>f, '%.6e' %R, - for t in xrange(20): - x=self.tables[p][i,t] - if abs(x)<1E-90: - print>>f, '0.', - else: - print>>f, '%.6e' %x, - print>>f - print>>f, '\n\n' - f.close() - - - def plot(self,filename=None): - """ Plot the Slater-Koster table with matplotlib. - - parameters: - =========== - filename: for graphics file - """ - try: - import pylab as pl - except: - raise AssertionError('pylab could not be imported') - fig=pl.figure() - fig.subplots_adjust(hspace=0.0001,wspace=0.0001) - mx=max(1,self.tables[0].max()) - if self.nel==2: - mx=max(mx,self.tables[1].max()) - for i in xrange(10): - name=integrals[i] - ax=pl.subplot(5,2,i+1) - for p,(e1,e2) in enumerate(self.pairs): - s1, s2=e1.get_symbol(), e2.get_symbol() - if p==0: - s='-' - lw = 1 - alpha = 1.0 - else: - s='--' - lw = 4 - alpha = 0.2 - if np.all(abs(self.tables[p][:,i])<1E-10): - ax.text(0.03,0.02+p*0.15,'No %s integrals for <%s|%s>' %(name,s1,s2),transform=ax.transAxes,size=10) - if not ax.is_last_row(): - pl.xticks([],[]) - if not ax.is_first_col(): - pl.yticks([],[]) - - else: - pl.plot(self.Rgrid,self.tables[p][:,i],c='r',ls=s,lw=lw,alpha=alpha) - pl.plot(self.Rgrid,self.tables[p][:,i+10],c='b',ls=s,lw=lw,alpha=alpha) - pl.axhline(0,c='k',ls='--') - pl.title(name,position=(0.9,0.8)) - if ax.is_last_row(): - pl.xlabel('r (Bohr)') - else: - pl.xticks([],[]) - if not ax.is_first_col(): - pl.yticks([],[]) - pl.ylim(-mx,mx) - pl.xlim(0) - - pl.figtext(0.3,0.95,'H',color='r',size=20) - pl.figtext(0.34,0.95,'S',color='b',size=20) - pl.figtext(0.38,0.95,' Slater-Koster tables',size=20) - e1, e2 = self.ela.get_symbol(),self.elb.get_symbol() - pl.figtext(0.3,0.92,'(thin solid: <%s|%s>, wide dashed: <%s|%s>)' %(e1,e2,e2,e1),size=10) - - file = '%s_%s_slako.pdf' %(e1,e2) - if filename!=None: - file = filename - pl.savefig(file) - - - def get_comment(self): - """ Get comments concerning parametrization. """ - return self.comment - - - def set_comment(self,comment): - """ Add optional one-liner comment for documenting the parametrization. """ - self.comment+='\n'+comment - - - def get_range(self,fractional_limit): - """ Define ranges for the atoms: largest r such that Rnl(r)>self.txt, 'wf range for %s=%10.5f' %(el.get_symbol(),r) - wf_range=max(r,wf_range) - if wf_range>20: - raise AssertionError('Wave function range >20 Bohr. Decrease wflimit?') - return wf_range - self.timer.stop('define ranges') - - - def run(self,R1,R2,N,ntheta=150,nr=50,wflimit=1E-7): - """ Calculate the Slater-Koster table. - - parameters: - ------------ - R1, R2, N: make table from R1 to R2 with N points - ntheta: number of angular divisions in polar grid. (more dense towards bonding region) - nr: number of radial divisions in polar grid. (more dense towards origins) - with p=q=2 (powers in polar grid) ntheta~3*nr is optimum (with fixed grid size) - with ntheta=150, nr=50 you get~1E-4 accuracy for H-elements - (beyond that, gain is slow with increasing grid size) - wflimit: use max range for wfs such that at R(rmax)~1E-3') - self.timer.start('calculate tables') - self.wf_range=self.get_range(wflimit) - Rgrid=np.linspace(R1,R2,N) - self.N=N - self.Rgrid=Rgrid - self.dH=0.0 - self.Hmax=0.0 - if self.nel==1: self.tables=[np.zeros((N,20))] - else: self.tables=[np.zeros((N,20)),np.zeros((N,20))] - - print>>self.txt, 'Start making table...' - for Ri,R in enumerate(Rgrid): - if R>2*self.wf_range: - break - grid, areas = self.make_grid(R,nt=ntheta,nr=nr) - if Ri==N-1 or np.mod(Ri,N/10)==0: - print>>self.txt, 'R=%8.2f, %i grid points ...' %(R,len(grid)) - for p,(e1,e2) in enumerate(self.pairs): - selected=select_integrals(e1,e2) - if Ri==0: - print>>self.txt, 'R=%8.2f %s-%s, %i grid points, ' %(R,e1.get_symbol(),e2.get_symbol(),len(grid)), - print>>self.txt, 'integrals:', - for s in selected: print>>self.txt, s[0], - print>>self.txt - - S,H,H2=self.calculate_mels(selected,e1,e2,R,grid,areas) - self.Hmax=max(self.Hmax,max(abs(H))) - self.dH=max(self.dH,max(abs(H-H2))) - self.tables[p][Ri,:10]=H - self.tables[p][Ri,10:]=S - - print>>self.txt, 'Maximum value for H=%.2g' %self.Hmax - print>>self.txt, 'Maximum error for H=%.2g' %self.dH - print>>self.txt, ' Relative error=%.2g %%' %(self.dH/self.Hmax*100) - self.timer.stop('calculate tables') - self.comment+='\n'+asctime() - self.txt.flush() - - - - - def calculate_mels(self,selected,e1,e2,R,grid,area): - """ - Perform integration for selected H and S integrals. - - parameters: - ----------- - selected: list of [('dds','3d','4d'),(...)] - e1: element - R: e1 is at origin, e2 at z=R - grid: list of grid points on (d,z)-plane - area: d-z areas of the grid points. - - return: - ------- - List of H,S and H2 for selected integrals. H2 is calculated using different - technique and can be used for error estimation. - - S: simply R1*R2*angle-part - H: operate (derivate) R2 - H2: operate with full h2 and hence use eigenvalue of |R2> with full Veff2 - - = (operate with h1 on left) - = - = e1*S + - -> H and H2 can be compared and error estimated - """ - self.timer.start('calculate_mels') - Sl, Hl, H2l=np.zeros(10), np.zeros(10), np.zeros(10) - - # common for all integrals (not wf-dependent parts) - self.timer.start('prelude') - N=len(grid) - gphi, radii, v1, v2=zeros((N,10)), zeros((N,2)), zeros(N), zeros(N) - for i,(d,z) in enumerate(grid): - r1, r2=sqrt(d**2+z**2), sqrt(d**2+(R-z)**2) - t1, t2=arccos(z/r1), arccos((z-R)/r2) - radii[i,:]=[r1,r2] - gphi[i,:]=g(t1,t2) - v1[i]=e1.effective_potential(r1)-e1.confinement_potential(r1) - v2[i]=e2.effective_potential(r2)-e2.confinement_potential(r2) - self.timer.stop('prelude') - - # calculate all selected integrals - for integral,nl1,nl2 in selected: - index=integrals.index(integral) - S, H, H2=0.0, 0.0, 0.0 - l2=angular_momentum[nl2[1]] - for i,dA in enumerate(area): - r1, r2=radii[i,:] - d, z=grid[i] - aux=gphi[i,index]*dA*d - - Rnl1, Rnl2, ddunl2=e1.Rnl(r1,nl1), e2.Rnl(r2,nl2), e2.unl(r2,nl2,der=2) - - S+= Rnl1*Rnl2*aux - H+= Rnl1*( -0.5*ddunl2/r2 + (v1[i]+v2[i]+l2*(l2+1)/(2*r2**2))*Rnl2 )*aux - H2+= Rnl1*Rnl2*aux*( v2[i]-e1.confinement_potential(r1) ) - H2+=e1.get_epsilon(nl1)*S - Sl[index]=S - Hl[index]=H - H2l[index]=H2 - - self.timer.stop('calculate_mels') - return Sl, Hl, H2l - - - def make_grid(self,Rz,nt,nr,p=2,q=2,view=False): - """ - Construct a double-polar grid. - - Parameters: - ----------- - Rz: element 1 is at origin, element 2 at z=Rz - nt: number of theta grid points - nr: number of radial grid points - p: power describing the angular distribution of grid points (larger puts more weight - towards theta=0) - q: power describing the radial disribution of grid points (larger puts more weight - towards centers) - view: view the distribution of grid points with pylab. - - Plane at R/2 divides two polar grids. - - - ^ (z-axis) - |--------_____ phi_j - | / ----__ * - | / \ / * - | / \ / X * X=coordinates of the center of area element(z,d), - | / \ \-----* phi_(j+1) area=(r_(i+1)**2-r_i**2)*(phi_(j+1)-phi_j)/2 - | / \ r_i r_(i+1) - | / \ - | / | - *2------------------------| polar centered on atom 2 - | \ | - | \ / 1 - | \ / / \ - |-------------------------- z=h -line ordering of sector slice / \ - | / \ points: / \ - | / \ / \ - | / | / 0 4 - *1------------------------|---> polar centered on atom 1 2 / - | \ | (r_perpendicular (xy-plane) = 'd-axis') \ / - | \ / \ / - | \ / 3 - | \ / - | \ / - | \ / - | \ ___ --- - |--------- - - """ - self.timer.start('make grid') - rmin, rmax=(1E-7, self.wf_range) - max_range=self.wf_range - h=Rz/2 - T=np.linspace(0,1,nt)**p*np.pi - R=rmin+np.linspace(0,1,nr)**q*(rmax-rmin) - - grid=[] - area=[] - # first calculate grid for polar centered on atom 1: - # the z=h-like starts cutting full elements starting from point (1) - for j in xrange(nt-1): - for i in xrange(nr-1): - # corners of area element - d1,z1=R[i+1]*sin(T[j]),R[i+1]*cos(T[j]) - d2,z2=R[i]*sin(T[j]),R[i]*cos(T[j]) - d3,z3=R[i]*sin(T[j+1]),R[i]*cos(T[j+1]) - d4,z4=R[i+1]*sin(T[j+1]),R[i+1]*cos(T[j+1]) - A0=(R[i+1]**2-R[i]**2)*(T[j+1]-T[j])/2 - - if z1<=h: - # area fully inside region - r0=0.5*(R[i]+R[i+1]) - t0=0.5*(T[j]+T[j+1]) - A=A0 - elif z1>h and z2<=h and z4<=h: - # corner 1 outside region - Th=np.arccos(h/R[i+1]) - r0=0.5*(R[i]+R[i+1]) - t0=0.5*(Th+T[j+1]) - A=A0 - A-=0.5*R[i+1]**2*(Th-T[j])-0.5*h**2*(tan(Th)-tan(T[j])) - elif z1>h and z2>h and z3<=h and z4<=h: - # corners 1 and 2 outside region - Th1=np.arccos(h/R[i]) - Th2=np.arccos(h/R[i+1]) - r0=0.5*(R[i]+R[i+1]) - t0=0.5*(Th2+T[j+1]) - A=A0 - A-=A0*(Th1-T[j])/(T[j+1]-T[j]) - A-=0.5*R[i+1]**2*(Th2-Th1)-0.5*h**2*(tan(Th2)-tan(Th1)) - elif z1>h and z2>h and z4>h and z3<=h: - # only corner 3 inside region - Th=np.arccos(h/R[i]) - r0=0.5*(R[i]+h/cos(T[j+1])) - t0=0.5*(Th+T[j+1]) - A=0.5*h**2*(tan(T[j+1])-tan(Th)) - 0.5*R[i]**2*(T[j+1]-Th) - elif z1>h and z4>h and z2<=h and z3<=h: - # corners 1 and 4 outside region - r0=0.5*(R[i]+h/cos(T[j+1])) - t0=0.5*(T[j]+T[j+1]) - A=0.5*h**2*(tan(T[j+1])-tan(T[j])) - 0.5*R[i]**2*(T[j+1]-T[j]) - elif z3>h: - A=-1 - else: - raise RuntimeError('Illegal coordinates.') - d,z=(r0*sin(t0),r0*cos(t0)) - if A>0 and sqrt(d**2+z**2) '2s' & '3d' - """ - nl1=None - for nl in val1: - if nl[1]==integral[0]: nl1=nl - nl2=None - for nl in val2: - if nl[1]==integral[1]: nl2=nl - return nl1,nl2 - - -def select_integrals(e1,e2): - """ Return list of integrals (integral,nl1,nl2) to be done for element pair e1,e2. """ - selected=[] - val1, val2 = e1.get_valence_orbitals(), e2.get_valence_orbitals() - for ii,integral in enumerate(integrals): - nl1, nl2=select_orbitals(val1,val2,integral) - if nl1==None or nl2==None: - continue - else: - selected.append( (integral,nl1,nl2) ) - return selected - - - -def g(t1,t2): - """ - Return the angle-dependent part of the two-center - integral (it) with t1=theta_1 (atom at origin) - and t2=theta2 (atom at z=Rz). These dependencies - come after integrating analytically over phi. - """ - c1, c2, s1, s2=cos(t1), cos(t2), sin(t1), sin(t2) - return np.array([5.0/8*(3*c1**2-1)*(3*c2**2-1),\ - 15.0/4*s1*c1*s2*c2,\ - 15.0/16*s1**2*s2**2,\ - sqrt(15.0)/4*c1*(3*c2**2-1),\ - sqrt(45.0)/4*s1*s2*c2,\ - 3.0/2*c1*c2,\ - 3.0/4*s1*s2,\ - sqrt(5.0)/4*(3*c2**2-1),\ - sqrt(3.0)/2*c2,\ - 0.5]) - - -if __name__=='__main__': - print select_orbital2(['2s','2p'],['4s','3d'],'sss') - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/util.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/util.py deleted file mode 100644 index 0ebaeb1..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/parametrization/util.py +++ /dev/null @@ -1,293 +0,0 @@ -from hotbit.parametrization import KSAllElectron -import numpy as np -from box import mix -from box.interpolation import Function - -integrals =['dds','ddp','ddd','pds','pdp','pps','ppp','sds','sps','sss'] - -def plot_table(parfile,screen=False,s1=None,s2=None,der=0): - """ Plot table. """ - import pylab as pl - if s1==None or s2==None: - s1,s2=parfile.split('.')[0].split('_') - if s1==s2: - nel=1 - pairs=[(s1,s2)] - else: - nel=2 - pairs=[(s1,s2),(s2,s1)] - - pl.rc('figure.subplot',wspace=0.0001) - pl.rc('figure.subplot',hspace=0.0001) - rgrid, tables=read_table(parfile,s1,s2) - mx=max( tables[0].flatten() ) - - for i in range(10): - name=integrals[i] - ax=pl.subplot(5,2,i+1) - for p,(e1,e2) in enumerate(pairs): - if p==1: s='--' - else: s='-' - if der==0: - grid=rgrid - H=tables[p][:,i] - S=tables[p][:,i+10] - elif der==1: - grid=np.linspace(rgrid[0],rgrid[-1],3*len(rgrid)) - hf=Function('spline',rgrid,tables[p][:,i]) - sf=Function('spline',rgrid,tables[p][:,i+10]) - H=np.array([hf(r,der=1) for r in grid]) - S=np.array([sf(r,der=1) for r in grid]) - pl.plot(grid,H,c='r',ls=s,label='%s%s: H' %(e1,e2)) - pl.plot(grid,S,c='b',ls=s,label='%s%s: S' %(e1,e2)) - pl.axhline(c='k',ls='--') - pl.title(name,position=(0.9,0.8)) - if ax.is_last_row(): - pl.xlabel('r (Bohr)') - else: - pl.xticks([],[]) - if not ax.is_first_col(): - pl.yticks([],[]) - pl.ylim(-mx,mx) - pl.xlim(0) - pl.legend(loc='upper left') - if screen: - pl.show() - else: - name='%s_%s_par.png' %(s1,s2) - if der==1: - name='der_'+name - pl.savefig(name) - - -def compare_tables(parfile1,parfile2,s1=None,s2=None,screen=False): - """ Plot table. """ - import pylab as pl - if s1==None or s2==None: - s1,s2=parfile1.split('.')[0].split('_') - if s1==s2: - nel=1 - pairs=[(s1,s2)] - else: - nel=2 - pairs=[(s1,s2),(s2,s1)] - - pl.rc('figure.subplot',wspace=0.0001) - pl.rc('figure.subplot',hspace=0.0001) - rgrid1, tables1=read_table(parfile1,s1,s2) - rgrid2, tables2=read_table(parfile2,s1,s2) - mx=max( tables1[0].flatten() )*0.5 - - for i in range(10): - name=integrals[i] - ax=pl.subplot(5,2,i+1) - for p,(e1,e2) in enumerate(pairs): - if p==1: s='--' - else: s='-' - # first table - pl.plot(rgrid1,tables1[p][:,i],lw=5,c='r',alpha=0.3,ls=s,label='%s%s: H' %(e1,e2)) - pl.plot(rgrid1,tables1[p][:,i+10],lw=5,alpha=0.3,c='b',ls=s,label='%s%s: S' %(e1,e2)) - - # second table - pl.plot(rgrid2,tables2[p][:,i],lw=2,c='r',ls=s,label='%s%s: H' %(e1,e2)) - pl.plot(rgrid2,tables2[p][:,i+10],lw=2,c='b',ls=s,label='%s%s: S' %(e1,e2)) - pl.axhline(c='k',ls='--') - pl.title(name,position=(0.9,0.8)) - if ax.is_last_row(): - pl.xlabel('r (Bohr)') - else: - pl.xticks([],[]) - if not ax.is_first_col(): - pl.yticks([],[]) - pl.ylim(-mx,mx) - pl.xlim(0) - #pl.legend(loc='upper left') - if screen: - pl.show() - else: - pl.savefig('%s_%s_comparison.png' %(s1,s2)) - pl.close() - - -def read_table(parfile,s1,s2): - """ Read parameter table from file parfile for elements with symbols s1 and s2. - - return list of tables [s1_s2_table,s2_s1_table] (or only other if s1==s2) - """ - f=open(parfile) - nel=[1,2][s1==s2] - tab=mix.find_value(parfile,'%s_%s_table' %(s1,s2),fmt='matrix') - rgrid=tab[:,0] - table=[tab[:,1:]] - if s1!=s2: - tab=mix.find_value(parfile,'%s_%s_table' %(s2,s1),fmt='matrix') - table.append(tab[:,1:]) - f.close() - return rgrid, table - - -def tail_smoothening(x,y): - """ For given grid-function y(x), make smooth tail. - - Aim is to get (e.g. for Slater-Koster tables and repulsions) smoothly - behaving energies and forces near cutoff region. - - Make is such that y and y' go smoothly exactly to zero at last point. - Method: take largest neighboring points y_k and y_(k+1) (k=0): - break - if m==9: - raise RuntimeError('Problems with function smoothening; need for new algorithm?') - return y - -def IP_EA(symb,remove_orb,add_orb,remove,add,add_args={}): - """ Return ionization potential and electron affinity for given atom, - and the valence energies of neutral atom. - - parameters: - ----------- - symb: element symbol - remove_orb: orbital from where to remove atoms (e.g. '2p') - add_orb: orbital from where to add atoms (e.g. '2p') - remove: how many electrons to remove - add: how many electrons to add - (remove and add can be different from 1.0 if DFT should not - be stable to e.g. adding one full electron) - - Fit second order curve for 3 points and return IP and EA for full - electron adding and removal. - """ - #from box.data import atom_occupations - atom = KSAllElectron(symb, txt='-', **add_args) - - # add electrons -> negative ion - #occu=atom_occupations[symb].copy() - w = 'negative.atom' - occu_add = atom.occu.copy() - occu_add[add_orb] += add - ea = KSAllElectron(symb, configuration=occu_add, restart=w, write=w, - **add_args) - ea.run() - - # neutral atom - w = 'neutral.atom' - neutral = KSAllElectron(symb, restart=w, write=w, **add_args) - neutral.run() - valence_energies = neutral.get_valence_energies() - - # remove electrons -> positive ion - #occu=atom_occupations[symb].copy() - w = 'positive.atom' - occu_remove = atom.occu.copy() - occu_remove[remove_orb] -= remove - ip = KSAllElectron(symb, configuration=occu_remove, restart=w, write=w, - **add_args) - ip.run() - - e0 = neutral.get_energy() - en = ea.get_energy()-e0 - ep = ip.get_energy()-e0 - # e(x)=e0+c1*x+c2*x**2 =energy as a function of additional electrons - c2 = (en+ep*add/remove)/(add*(remove+add)) - c1 = (c2*remove**2-ep)/remove - IP = -c1+c2 - EA = -(c1+c2) - return IP, EA, neutral - - -def ionization_potential(symb,remove,electrons=1.0): - """ Return ionization potential of given atom. - - parameters: - ----------- - symb: element symbol - remove: orbital from where electron is removed (e.g. '2p') - electrons: how many electrons to remove. Can be fractional number - if DFT should not be stable. IP is scaled by - electrons^-1 in the end to extrapolate to electrons=1. - - """ - from box.data import atom_occupations - occu=atom_occupations[symb].copy() - # neutral atom - atom=KSAllElectron(symb) - atom.run() - e0=atom.get_energy() - # negative ion - occu[remove]-=electrons - ion=KSAllElectron(symb,occu=occu) - ion.run() - e1=ion.get_energy() - return (e1-e0)/electrons - -def electron_affinity(symb,add,electrons=1.0): - """ Return electron affinity of given atom. - - parameters: - ----------- - symb: element symbol - add: orbital where electron is added (e.g. '2p') - electrons: how many electrons are added. Can be fractional number - if DFT should not be stable. EA is scaled by - electrons^-1 in the end to extrapolate to electrons=1. - """ - from box.data import atom_occupations - occu=atom_occupations[symb].copy() - # neutral atom - atom=KSAllElectron(symb) - atom.run() - e0=atom.get_energy() - # positive ion - occu[add]+=electrons - ion=KSAllElectron(symb,occu=occu) - ion.run() - e1=ion.get_energy() - return (e0-e1)/electrons - - - - -if __name__=='__main__': - #plot_table('Au_Au.par',s1='Au',s2='Au',screen=True,der=0) - #compare_tables('Au_Au.par','Au_Au_NR.par',s1='Au',s2='Au',screen=False) - - x=np.array([1,2,3,4,5,6,7,8,9,10]) - y=np.array([100,70,30,10,5,2,0.5,0.1,0.05,0.0001]) - pl.plot(x,y) - y=tail_smoothening(x,y) - pl.plot(x,y) - pl.show() diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/repulsion.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/repulsion.py deleted file mode 100644 index 3c2d02d..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/repulsion.py +++ /dev/null @@ -1,213 +0,0 @@ -# Copyright (C) 2008 NSC Jyvaskyla -# Please see the accompanying LICENSE file for further information. - -import numpy as np -from ase.units import Bohr,Hartree -from box import mix -from box.interpolation import Function -from hotbit.io import read_repulsion -import os -import ase -from weakref import proxy -find=mix.find_value -vec=np.array -norm=np.linalg.norm -sqrt=np.sqrt - -class Repulsion: - def __init__(self,calc): - self.calc=proxy(calc) - - # read repulsions - self.vrep={} - present=calc.el.get_present() - self.files=self.calc.ia.get_files() - self.rmax=0.0 - for si in present: - for sj in present: - self.vrep[si+sj]=RepulsivePotential(self.files[si+sj]) - self.rmax = max( self.rmax, self.vrep[si+sj].get_r_cut() ) - self.N=calc.el.get_N() - - def __del__(self): - pass - - def greetings(self): - """ Return the repulsion documentations. """ - txt='Repulsions:\n' - for i,s1 in enumerate(self.calc.el.present): - for s2 in self.calc.el.present[i:]: - file = self.files[s1+s2] - if file==None: - txt+=' %s%s: None\n' %(s1,s2) - else: - txt+=' %s%s in %s\n' %(s1,s2,file) - doc=mix.find_value(file,'repulsion_comment',fmt='strings',default=['no repulsion doc']) - for line in doc: - txt+=' *'+line.lstrip()+'\n' - return txt - - - def get_repulsion_distances(self,ela,elb,r_cut): - """ - Return distances below r_cut for given elements. - - Intended use for repulsion fitting. Go through all - periodic images, if any (of course). - - parameters: - =========== - ela: chemical symbol a - elb: chemical symbol b - r_cut: repulsion cutoff (Angstrom) - - return: - ======= - d: numpy array of distances (in Angstroms) below r_cut - """ - lst = self.calc.el.get_property_lists(['i','s']) - Rijn = self.calc.el.rijn - r_cut /= Bohr - - dlist=[] - for i,si in lst: - for j,sj in lst[i:]: - if not ((si==ela and sj==elb) or (sj==ela and si==elb)) : - continue - for n,rijn in enumerate(Rijn[:,i,j]): - if i==j and n==0: continue - d = np.sqrt( rijn[0]**2+rijn[1]**2+rijn[2]**2 ) - if d<=r_cut: - dlist.append(d) - return np.array(dlist)*Bohr - - - - def get_repulsive_energy(self): - """ Return the repulsive energy (in eV). """ - self.calc.start_timing('e_rep') - - # TODO: be more selective with n (for efficiency) - lst=self.calc.el.get_property_lists(['i','s']) - Rijn = self.calc.el.rijn - erep=0.0 - for i,si in lst: - for j,sj in lst[i:]: - for n,rijn in enumerate(Rijn[:,i,j]): - if i==j and n==0: continue - d = np.sqrt( rijn[0]**2+rijn[1]**2+rijn[2]**2 ) - if d>self.rmax: continue - # TODO: remove following assert - assert(d>1E-10) - if i==j: - erep+=0.5*self.vrep[si+sj](d) - else: - erep+=self.vrep[si+sj](d) - self.calc.stop_timing('e_rep') - return erep*Hartree - - - def get_pair_repulsive_energy(self,i,j): - """ - Return the repulsive energy of given atom pair. - - parameters: - =========== - i,j: atom indices - """ - si = self.calc.el.symbols[i] - sj = self.calc.el.symbols[j] - Rijn = self.calc.el.rijn - erep=0.0 - for n,rijn in enumerate(Rijn[:,i,j]): - if i==j and n==0: continue - d = np.sqrt( rijn[0]**2+rijn[1]**2+rijn[2]**2 ) - if d>self.rmax: continue - if i==j: - erep += 0.5*self.vrep[si+sj](d) - else: - erep += self.vrep[si+sj](d) - return erep - - - def get_repulsive_forces(self): - """ - Return repulsive forces. - - F_i = sum_(j,n) V'(rijn) rijn/dijn, with rijn = r_j^n -r_i and dijn=|rijn| - """ - self.calc.start_timing('f_rep') - f=np.zeros((self.N,3)) - lst = self.calc.el.get_property_lists(['i','s']) - Rijn = self.calc.el.rijn - for i,si in lst: - for j,sj in lst: - V = self.vrep[si+sj] - for n,rijn in enumerate(Rijn[:,i,j]): - if i==j and n==0: continue - dijn = sqrt( rijn[0]**2+rijn[1]**2+rijn[2]**2 ) - if dijn1E-6: - eval,efunc = eigh(S) - evmin = eval.min() - if evmin<0: - raise AssertionError('Eigenfunction norm from LAPACK %.4f. Minimum eigenvalue of S is %.4f - overlap matrix is not positive definite.' %(maxdev,evmin)) - else: - raise AssertionError('Eigenfunction norm from LAPACK %.4f, but overlap matrix still appears positive definite.' %(maxdev)) - self.calc.stop_timing('Check norm (remove?)') - - - if False: - #raise NotImplementedError('Not checked for complex stuff') - # using numpy lapack_lite - e, wf = eig(H,S) - e = e.real - order = e.argsort() - e = e[order] - for i in range(self.norb): - wf[:,i]=wf[order,i] - for i in range(self.norb): #normalize properly - wf[i]=wf[i]/np.sqrt( np.abs(np.dot(wf[i],np.dot(S,wf[:].conj()))) ) - - return e,wf - -### - -def get_HS_shape(H, S): - """ - Return the number of k-points and the number of orbitals given a - Hamiltonian and an overlap matrix. - """ - nk = H.shape[0] - norb = H.shape[1] - assert H.shape[2] == norb - assert S.shape[0] == nk - assert S.shape[1] == norb - assert S.shape[2] == norb - - return nk, norb diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/states.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/states.py deleted file mode 100644 index e427350..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/states.py +++ /dev/null @@ -1,372 +0,0 @@ -# Please see the accompanying LICENSE file for further information. - -from solver import Solver -from weakref import proxy -from electrostatics import Electrostatics -from occupations import Occupations -import numpy as np -from box import mix -from auxil import k_to_kappa_points -from box.mix import divisors -pi=np.pi - - -# -# Constructing the density matrix, and the energy -# weighted density matrix from eigenvectors, eigenvalues -# and occupations. -# - -def compute_rho(wf, occ): - nk, n, m = wf.shape - nk2, k = occ.shape - - assert n == m - assert n == k - assert nk == nk2 - - rho = np.zeros(wf.shape, dtype=wf.dtype) - for k in range(nk): - rho[k,:,:] = np.dot( - wf[k,:,:].transpose(), - occ[k,:].reshape(n,-1) * wf[k,:,:].conj() - ) - return rho - - -def compute_rhoe(wf, occ, e): - nk, n, m = wf.shape - nk2, k = occ.shape - - assert n == m - assert n == k - assert nk == nk2 - - rhoe = np.zeros(wf.shape, dtype=wf.dtype) - for k in range(nk): - rhoe[k,:,:] = np.dot( - wf[k,:,:].transpose(), - e[k,:].reshape(n,-1)*occ[k,:].reshape(n,-1) * wf[k,:,:].conj() - ) - return rhoe - - -# -# States class -# - -class States: - - def __init__(self,calc): - self.es = Electrostatics(calc, - charge_density = calc.get('charge_density'), - solver = calc.get('coulomb_solver')) - self.solver=Solver(calc) - self.calc=proxy(calc) - self.nat=len(calc.el) - self.norb=calc.el.get_nr_orbitals() - self.prev_dq=[None,None] - self.count=0 - self.first_solve = True - self.SCC=calc.get('SCC') - self.rho=None - self.rhoe0=None - self.nk=None - - - def setup_k_sampling(self,kpts,physical=True,rs='kappa'): - ''' - Setup the k-point sampling and their weights. - - @param kpts: 3-tuple: number of k-points in different directions - list of 3-tuples: k-points given explicitly - @param physical: No meaning for infinite periodicities. For physically - periodic systems only certain number of k-points are allowed. - (like wedge of angle 2*pi/N, only number of k-points that - divides N, is physically allowed). If physical=False, - allow interpolation of this k-sampling. - rs: use 'kappa'- or 'k'-point sampling - ''' - if kpts!=(1,1,1) and self.calc.get('width')<1E-10: - raise AssertionError('With k-point sampling width must be>0!') - - M = self.calc.el.get_number_of_transformations() - if isinstance(kpts,tuple): - table = self.calc.el.atoms.container.get_table() - # set up equal-weighted and spaced k-point mesh - if 0 in kpts: - raise AssertionError('Each direction must have at least one k-point! (Gamma-point)') - - kl=[] - for i in range(3): - if M[i]==np.Inf: - # arbitrary sampling is allowed - spacing = 2*pi/kpts[i] - kl.append( np.linspace(-pi+spacing/2,pi-spacing/2,kpts[i]) ) - else: - # TODO: choose the closest number of k-points if - # sampling should be physical - # first calculate possible numer of k-points, then - # select the ones closest to the desired one - # nks = M/divisors(M) - # nk1 = nks[abs(nks-nk).argmin()] - # discrete, well-defined sampling; any k-point is not allowed - if kpts[i] not in mix.divisors(M[i]) and physical: - print 'Allowed k-points for direction',i,'are',mix.divisors(M[i]) - raise Warning('Non-physical k-point sampling! ') - else: - kl.append( np.linspace(0,2*pi-2*pi/kpts[i],kpts[i]) ) - - k=[] - wk=[] - kpt_indices = [] - nk0 = np.prod(kpts) - for a in range(kpts[0]): - for b in range(kpts[1]): - for c in range(kpts[2]): - newk = np.array([kl[0][a], kl[1][b], kl[2][c]]) - newind = (a,b,c) - one_equivalent = False - for i in range(3): - if 'equivalent' in table[i]: - if one_equivalent: - raise NotImplementedError('Surprising type of new symmetry; reconsider implementation.') - one_equivalent = True - n = table[i]['equivalent'] # symmetry op i is equivalent to tuple n - assert n[i]==0 - newk[i] = newk[i] + 1.0*np.dot(n,newk)/M[i] - - - inv_exists = False - # if newk's inverse exists, increase its weight by default - for ik, oldk in enumerate(k): - if np.linalg.norm(oldk+newk)<1E-10: - inv_exists = True - wk[ik]+=1.0/nk0 - # newk's inverse does not exist; make new k-point - if not inv_exists: - k.append( newk ) - wk.append( 1.0/nk0 ) - kpt_indices.append( newind ) - nk=len(k) - k=np.array(k) - wk=np.array(wk) - else: - # work with a given set of k-points - nk=len(kpts) - if rs=='k': - k = k_to_kappa_points(kpts,self.calc.el.atoms) - else: - k=np.array(kpts) - wk=np.ones(nk)/nk - kl=None - - # now sampling is set up. Check consistency. - pbc = self.calc.el.get_pbc() - self.kpt_indices = np.array(kpt_indices) - for i in range(3): - for kp in k: - if kp[i]>1E-10 and not pbc[i]: - raise AssertionError('Do not set (non-zero) k-points in non-periodic direction!') - - return nk, k, kl, wk - - - def guess_dq(self): - n=len(self.calc.el) - if not self.SCC: - return np.zeros((n,)) - if self.count==0: - return np.zeros((n,)) - float(self.calc.get('charge'))/n - elif self.count==1: # use previous charges - return self.prev_dq[0] - else: # linear extrapolation - return self.prev_dq[0] + (self.prev_dq[0]-self.prev_dq[1]) - - - def solve(self): - if self.nk==None: - physical = self.calc.get('physical_k') - self.nk, self.k, self.kl, self.wk = self.setup_k_sampling( self.calc.get('kpts'),physical=physical,rs=self.calc.get('rs') ) - width=self.calc.get('width') - self.occu = Occupations(self.calc.el.get_number_of_electrons(),width,self.wk) - self.calc.start_timing('solve') - - # TODO: enable fixed dq-calculations in SCC (for band-structures) - dq=self.guess_dq() - if self.first_solve: - self.calc.memory_estimate() - self.first_solve = False - self.H0, self.S, self.dH0, self.dS = self.calc.ia.get_matrices() - - if self.SCC: - self.es.construct_Gamma_matrix(self.calc.el.atoms) - self.e, self.wf = self.solver.get_states(self.calc,dq,self.H0,self.S) - - self.check_mulliken_charges() - self.large_update() - self.count+=1 - self.calc.stop_timing('solve') - - - - def check_mulliken_charges(self): - """ Check that the Mulliken populations are physically - reasonable. """ - dQ = self.mulliken() - if self.calc.verbose_SCC: - print>> self.calc.get_output(), "Mulliken populations: min=%0.3f, max=%0.3f" % (np.min(dQ),np.max(dQ)) - Z = self.calc.el.get_atomic_numbers() - for dq, z in zip(dQ, Z): - if dq < -z or dq > z: - for dq, z in zip(dQ, Z): - print >> self.calc.get_output(), "Z=%i dq=%0.3f excess charge=%0.3f" % (z, dq, -dq) - raise Exception("The Mulliken charges are insane!") - - - def update(self,e,wf): - """ Update all essential stuff from given wave functions. """ - self.calc.start_timing('update') - self.e=e - self.wf=wf - self.f=self.occu.occupy(e) - self.calc.start_timing('rho') - self.rho = compute_rho(self.wf,self.f) - - self.calc.stop_timing('rho') - if self.SCC: - self.dq = self.mulliken() - self.es.set_dq(self.dq) - self.calc.stop_timing('update') - - - def large_update(self): - """ Update stuff from eigenstates needed later for forces etc. """ - self.calc.start_timing('final update') - self.Swf = None - self.dH = np.zeros_like(self.dH0) - if self.SCC: - self.prev_dq=[self.dq, self.prev_dq[0]] - # TODO: do k-sum with numpy - for ik in range(self.nk): - for a in range(3): - self.dH[ik,:,:,a] = self.dH0[ik,:,:,a] + self.es.get_h1()*self.dS[ik,:,:,a] - else: - self.dH = self.dH0 - - # density matrix weighted by eigenenergies - self.rhoe = compute_rhoe(self.wf,self.f,self.e) - self.calc.stop_timing('final update') - - - def get_dq(self): - return self.dq.copy() - - - def get_eigenvalues(self): - return self.e.copy() - - - def get_band_energies(self, kpts): - """ - Return the eigenvalue spectrum for a set of explicitly given k-points. - """ - H0, S, dH0, dS = self.calc.ia.get_matrices(kpts) - e, wf = self.solver.get_eigenvalues_and_wavefunctions(H0, S) - return e - - - def get_occupations(self): - return self.f.copy() - - - def get_homo(self,occu=0.99): - """ Return highest *largely* occupied orbital (>occu) - - 0<=occu<=2. Recommended use only for molecules. - """ - for i in range(self.norb)[::-1]: - if np.any( self.f[:,i]>occu ): return i - - - def get_lumo(self,occu=1.01): - """ Return lowest *largely* unuccopied orbital (1E-5: - raise RuntimeError('Mulliken charges (%.4f) do not add up to total charge (%.4f)!' %(q,c)) - return dq - - - def get_band_structure_energy(self): - ''' - Return band structure energy. - - ebs = sum_k w_k ( sum_ij rho_ij * H0_ji ) - = sum_k w_k ( sum_i [sum_j rho_ij * H0^T_ij] ) - ''' - self.calc.start_timing('e_bs') - ebs = 0.0 - for ik in xrange(self.nk): - diagonal = ( self.rho[ik]*self.H0[ik].transpose() ).sum(axis=1) - ebs += self.wk[ik] * diagonal.sum() - assert ebs.imag<1E-13 - self.calc.stop_timing('e_bs') - return ebs.real - - - def get_band_structure_forces(self): - ''' - Return band structure forces. - - F_I = - sum_k w_k Trace_I [ dH(k)*rho(k) - dS(k)*rhoe(k) + c.c ] - = - sum_k w_k sum_(i in I) diag_i(k) + c.c., - - where diag_i(k) = [dH(k)*rho(k) - dS(k)*rhoe(k)]_ii - = sum_j [dH(k)_ij*rho(k)_ji - dS(k)_ij*rhoe(k)_ji] - = sum_j [dH(k)_ij*rho(k)^T_ij - dS(k)_ij*rhoe(k)^T_ij] - ''' - self.calc.start_timing('f_bs') - diag = np.zeros((self.norb,3),complex) - - for a in range(3): - for ik in range(self.nk): - diag_k = ( self.dH[ik,:,:,a]*self.rho[ik].transpose() \ - - self.dS[ik,:,:,a]*self.rhoe[ik].transpose() ).sum(axis=1) - diag[:,a] = diag[:,a] - self.wk[ik] * diag_k - - f=[] - for o1, no in self.calc.el.get_property_lists(['o1','no']): - f.append( 2*diag[o1:o1+no,:].sum(axis=0).real ) - - self.calc.stop_timing('f_bs') - return f - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/Au2.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/Au2.py deleted file mode 100644 index 3e9cd0b..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/Au2.py +++ /dev/null @@ -1,9 +0,0 @@ -from ase import * -from hotbit import Hotbit -from hotbit.test.misc import default_param - -calc=Hotbit(SCC=True,txt='test.cal',**default_param) -Au2=Atoms('Au2',positions=[(0,0,0),(1.6,1.2,0.2)],cell=(10,10,10),pbc=False) -Au2.center(vacuum=10) -Au2.set_calculator(calc) -print Au2.get_potential_energy() diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/Au_chain.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/Au_chain.py deleted file mode 100644 index 554269d..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/Au_chain.py +++ /dev/null @@ -1,25 +0,0 @@ -from ase import * -from hotbit import * -from box.md import check_energy_conservation - -M=7 -atoms = Atoms('Au2',[(5,0,0),(5,2.5,0.3)],container='Wedge') -atoms.set_container(M=M,height=5.0) -calc=Hotbit(SCC=False,txt='-',kpts=(M,1,1)) -atoms.set_calculator(calc) -e1 = atoms.get_potential_energy() - -whole = atoms.extended_copy((M,1,1)) -calc=Hotbit(SCC=False,txt='-') -whole.set_calculator(calc) -e2 = whole.get_potential_energy() - -assert abs(M*e1-e2)<1E-10 - - -assert check_energy_conservation(atoms,dt=2.5*units.fs,steps=50,tol=0.01,plot=False) - -#dyn = VelocityVerlet(atoms,2.5*fs) -#traj = PickleTrajectory('koe.traj','w',atoms) -#dyn.attach(traj.write) -#dyn.run(100) \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/C6H6_cell_game.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/C6H6_cell_game.py deleted file mode 100644 index 0339155..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/C6H6_cell_game.py +++ /dev/null @@ -1,30 +0,0 @@ -from ase import * -from ase import Atoms as ase_Atoms -from hotbit import * -from hotbit.atoms import Atoms -from box.md import check_energy_conservation -from hotbit.test.misc import default_param - -SCC=True -cut=3.0 -atoms = Atoms('CH',[(1.42,0,0),(2.42,0,0)],container='Wedge') -atoms.set_container(M=6,height=10) - -calc = Hotbit(SCC=SCC,txt='tmp.cal',kpts=(6,1,1),gamma_cut=cut,**default_param) -atoms.set_calculator(calc) -e1 = atoms.get_potential_energy() - - -aux = atoms.extended_copy((3,1,1)) -atoms2 = Atoms(container='Wedge') -atoms2 += aux[0] -atoms2 += aux[-1] -atoms2.set_container(M=6,height=10) - -#view(atoms2) -calc = Hotbit(SCC=SCC,txt='tmp.cal',kpts=(6,1,1),gamma_cut=cut,**default_param) -atoms2.set_calculator(calc) -e2 = atoms.get_potential_energy() - -assert abs(e1-e2)<1E-5 - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/C6H6_wedge.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/C6H6_wedge.py deleted file mode 100644 index caf241d..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/C6H6_wedge.py +++ /dev/null @@ -1,39 +0,0 @@ -from ase import * -from ase import Atoms as ase_Atoms -from hotbit import * -from hotbit.atoms import Atoms -from box.md import check_energy_conservation -from hotbit.test.misc import default_param - - -# check that C1H1-presentation of C6H6 goes right -SCC=True -cut=3.0 -atoms = Atoms('CH',[(1.42,0,0),(2.0,1.0,0.2)],container='Wedge') -atoms.set_container(M=6,height=10) - -calc = Hotbit(SCC=SCC,txt='tmp.cal',kpts=(6,1,1),gamma_cut=cut,**default_param) -atoms.set_calculator(calc) -e1 = atoms.get_potential_energy() - -atoms6 = ase_Atoms(pbc=False) -atoms6 += atoms.extended_copy([(i-2,0,0) for i in range(6)]) -#view(atoms) -calc = Hotbit(SCC=SCC,txt='tmp.cal',gamma_cut=cut,**default_param) -atoms6.set_calculator(calc) -e6 = atoms6.get_potential_energy() - -assert abs(6*e1-e6)<1E-5 - - -# -# energy conservation -# -atoms = Atoms('CH',[(1.42,0,0),(2.0,0.5,0.3)],container='Wedge') -atoms.set_container(M=6,height=10) -calc = Hotbit(SCC=SCC,txt='tmp.cal',kpts=(6,1,1),gamma_cut=cut,**default_param) -atoms.set_calculator(calc) - -atoms.rattle(0.1) -assert check_energy_conservation(atoms,dt=0.2*units.fs,steps=30,tol=0.01,plot=False) - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/CNT5_0_SCC.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/CNT5_0_SCC.py deleted file mode 100644 index d8ab90f..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/CNT5_0_SCC.py +++ /dev/null @@ -1,44 +0,0 @@ -from ase import * -from hotbit import * -from hotbit.atoms import Atoms -from box.systems import nanotube -from box.md import check_energy_conservation - -nkpts=10 -SCC=True -cut=5.0 -# check that SCC works for chiral atoms - -# energy of normal infinite (5,0) -straight = nanotube('C',1.42,5,0) -straight.set_pbc((False,False,True)) -for i in range(len(straight)): - if straight[i].z<1.0: - r=sqrt(straight[i].x**2+straight[i].y**2) - c=(1+r)/r - x,y,z = c*straight[i].x,c*straight[i].y,straight[i].z - straight+=Atom('H',(x,y,z)) -#view(straight) -calc = Hotbit(SCC=SCC,txt='chiral.cal',kpts=(1,1,nkpts),gamma_cut=cut) -straight.set_calculator(calc) -e1 = straight.get_potential_energy() - - - -# same thing, but calculate by twisting 2*pi/5 while translating -height = straight.get_cell()[2,2] -chiral = Atoms(container='Chiral') -chiral += straight -chiral.set_container(height=height,angle=2*pi/5) -calc = Hotbit(SCC=SCC,txt='chiral.cal',kpts=(1,1,nkpts),gamma_cut=cut) -chiral.set_calculator(calc) -view(chiral) -e2 = chiral.get_potential_energy() -assert abs(e1-e2)<1E-6 - - -# check the energy conservation for the chiral situation -chiral.rattle(0.1) -calc = Hotbit(SCC=SCC,txt='chiral.cal',width=0.1,kpts=(1,1,1),gamma_cut=cut) #,verbose_SCC=True) -chiral.set_calculator(calc) -assert check_energy_conservation(chiral,dt=0.5*fs,steps=50,tol=0.02,plot=True) \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/CNT5_0_chiral.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/CNT5_0_chiral.py deleted file mode 100644 index cef2c3e..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/CNT5_0_chiral.py +++ /dev/null @@ -1,34 +0,0 @@ -from ase import * -from hotbit import * -from math import pi -from hotbit.atoms import Atoms -from box.systems import nanotube -from box.md import check_energy_conservation - -nkpts=10 - -# energy of normal infinite (5,0) -straight = nanotube(5,0,1.42) -calc = Hotbit(SCC=False,txt='chiral.cal',kpts=(1,1,nkpts)) -straight.set_calculator(calc) -e1 = straight.get_potential_energy() -#view(straight) - - -# same thing, but calculate by twisting 2*pi/5 while translating -height = straight.get_cell()[2,2] -chiral = Atoms(container='Chiral') -chiral += straight -chiral.set_container(height=height,angle=2*pi/5) -calc = Hotbit(SCC=False,txt='chiral.cal',kpts=(1,1,nkpts)) -chiral.set_calculator(calc) -e2 = chiral.get_potential_energy() -assert abs(e1-e2)<1E-6 - - -# check the energy conservation for the chiral situation -#chiral.rattle(0.1) -#calc = Hotbit(SCC=False,txt='chiral.cal',kpts=(1,1,1)) -#chiral.set_calculator(calc) -#conv = check_energy_conservation(chiral,dt=0.5*fs,steps=50,tol=0.01,plot=False) -#assert conv \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/__init__.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/__init__.py deleted file mode 100644 index 8d1c8b6..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/atom_dimer.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/atom_dimer.py deleted file mode 100644 index 205a196..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/atom_dimer.py +++ /dev/null @@ -1,45 +0,0 @@ -from ase import * -from numpy import random, pi -from box import Atoms -from box import mix -from hotbit import Hotbit -#from hotbit import Calculator0 -from ase.units import Bohr, Hartree -from hotbit.test.misc import default_param - -# C-non-SCC -calc=Hotbit(SCC=False,txt='test.cal',**default_param) -C=Atoms('C',positions=[(0,0,0)],cell=(10,10,10),pbc=False) -C.center(vacuum=100) -C.set_calculator(calc) -e=C.get_potential_energy() -if abs(e)>1E-6: - raise RuntimeError('energy %f, should be %f' %(e,0.0)) - -# C, SCC -calc=Hotbit(SCC=True,txt='test.cal',**default_param) -C=Atoms('C',positions=[(0,0,0)],cell=(10,10,10),pbc=False) -C.center(vacuum=100) -C.set_calculator(calc) -e=C.get_potential_energy() -if abs(e)>1E-6: - raise RuntimeError('energy %f, should be %f' %(e,0.0)) - - -# rotate Au-dimer -#calc0=Calculator0(SCC=True,txt='test.cal',**default_param) -calc=Hotbit(SCC=True,txt='test.cal',**default_param) -Au2=Atoms('Au2',positions=[(0,0,0),(2.6,0,0)],cell=(10,10,10),pbc=False) -Au2.center(vacuum=10) -#Au2.set_calculator(calc0) -e=-152.981553763-(-149.76607940880001) - -for i in range(10): - Au2.set_calculator(calc) - vector=mix.random_direction(vector=True) - Au2.rotate(vector*random.rand()*2*pi) - Au2.center(vacuum=10) - e2=Au2.get_potential_energy() - if abs(e-e2)>1E-4: - raise RuntimeError('energy for Au2 %f, should be %f (while rotating)' %(e2,e)) - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/copy_calculator.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/copy_calculator.py deleted file mode 100644 index a39888f..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/copy_calculator.py +++ /dev/null @@ -1,50 +0,0 @@ -from ase import * -from hotbit import Hotbit -import numpy as np -import os -from copy import copy - -dir = os.environ['HOTBIT_DIR']+'/param/' - -atoms = Atoms('CH2',((0,0,0),(1,0,0),(-1,0,0))) -atoms.center(vacuum=5) -calc = Hotbit(charge=-2, txt='-', - elements={'H':dir + 'H.elm', 'C':dir+'C.elm'}, - tables = {'HH':dir+'H_H.par', 'CC':dir+'C_C.par', 'CH':dir+'C_H.par'}, - SCC=False, - width=0.04, - mixer='pulay') -calc2 = copy(calc) -calc2.set_text("-") -atoms.set_calculator(calc) -e1 = atoms.get_potential_energy() - -atoms = Atoms('CH2',((0,0,0),(1,0,0),(-1,0,0))) -atoms.center(vacuum=5) -atoms.set_calculator(calc2) -e2 = atoms.get_potential_energy() - -if abs(e1-e2) > 1e-7: - raise RuntimeError("The original and copied calculator doesn't give same results!") - -atoms = Atoms('CH2',((0,0,0),(1,0,0),(-1,0,0)),pbc=[1,1,1]) -atoms.center(vacuum=5) -calc = Hotbit(charge=0, txt='-', - elements={'H':dir + 'H.elm', 'C':dir+'C.elm'}, - tables = {'HH':dir+'H_H.par', 'CC':dir+'C_C.par', 'CH':dir+'C_H.par'}, - SCC=False, - width=0.04, - mixer='pulay') -calc2 = copy(calc) -calc2.set_text("-") -atoms.set_calculator(calc) -e1 = atoms.get_potential_energy() - -atoms = Atoms('CH2',((0,0,0),(1,0,0),(-1,0,0)),pbc=[1,1,1]) -atoms.center(vacuum=5) -atoms.set_calculator(calc2) -e2 = atoms.get_potential_energy() - -if abs(e1-e2) > 1e-7: - raise RuntimeError("The original and copied calculator doesn't give same results!") - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/dftb_io.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/dftb_io.py deleted file mode 100644 index f00e7dd..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/dftb_io.py +++ /dev/null @@ -1,62 +0,0 @@ -""" -Test the DFTB file format reader. -""" - -import numpy as np - -import ase -from ase.units import Hartree -from hotbit import Hotbit - -### - - -dir1 = '/Users/pas/Sourcen/hotbit/param/' -#dir2 = '/Users/pas/Sourcen/hotbit/param/' -dir2 = '/Users/pas/Sourcen/mdcore/data/slater_koster_tables/Frauenheim/download-2009-10-23/mio-0-1/' - -### - -a = ase.molecule('C6H6') -a.center(vacuum=6.0) - -c = Hotbit( - elements = { - 'H': dir2 + 'H-H.skf', - 'C': dir2 + 'C-C.skf' - }, - tables = { - 'HH': dir2 + 'H-H.skf', - 'CH': dir2 + 'C-H.skf', - 'CC': dir2 + 'C-C.skf' - }, - SCC = False - ) -a.set_calculator(c) - -ase.FIRE(a).run(fmax=0.01) - -ase.write('C6H6.cfg', a) - -### - -for i in c.el.get_present(): - el = c.el.get_element(i) - sym = el.get_symbol() - orbs = el.get_valence_orbitals() - for orb in orbs: - print sym, orb, el.get_epsilon(orb), el.get_epsilon(orb)*Hartree - -x = np.linspace(1.0, 12.0, 1000) - -y, dy = c.ia.h['CC'](x) -d = np.transpose(np.append(x.reshape(1, -1), y, axis=0)) -np.savetxt('CC_H.out', d) - -y, dy = c.ia.s['CC'](x) -d = np.transpose(np.append(x.reshape(1, -1), y, axis=0)) -np.savetxt('CC_S.out', d) - -y = c.rep.vrep['CC'](x) -d = np.transpose([x, y]) -np.savetxt('CC_rep.out', d) diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/external_field.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/external_field.py deleted file mode 100644 index ff4795f..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/external_field.py +++ /dev/null @@ -1,14 +0,0 @@ -from ase import * -from hotbit import * - -atoms = Atoms('H2',[(0,0,0),(1,0,0)]) -calc = Hotbit(SCC=True,txt='external.cal') -atoms.set_calculator(calc) - -def phi(r,t): - return 0.78*r[0] - -calc.env.add_phi(phi) -#print calc.get_dq(atoms) -calc.solve_ground_state(atoms) -assert calc.get_dq()[1]>0.99 diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/forces.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/forces.py deleted file mode 100644 index 847104f..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/forces.py +++ /dev/null @@ -1,45 +0,0 @@ -from hotbit import Hotbit -from ase import * -from hotbit.test.misc import default_param -from hotbit.test.misc import molecule -from numpy import * -from box.md import microcanonical, energy_conservation -from ase.units import fs -import sys - -from box.fd_forces import check_forces - -systems=[ - 'AuC', - 'H2COH' - ] - -#default_param['convergence']=1E-5 -#default_param['Anderson_memory']=3 -default_param['width']=0.1 - -for charge_density in [ None, 'Gaussian', 'Slater' ]: - for system in systems: - if charge_density is None: - print ' ... forces for %s, no SCC' %system - calc=Hotbit(verbose=True,SCC=False,txt='forces.cal',**default_param) - else: - print ' ... forces for %s, SCC, charge density = %s' % \ - ( system, charge_density ) - calc=Hotbit(verbose=True,SCC=True,charge_density=charge_density, - txt='forces.cal',**default_param) - atoms=molecule(system) - #view(atoms) - atoms.center(vacuum=5) - atoms[0].x+=0.1 - atoms=Atoms(atoms) - atoms.set_calculator(calc) - sys.stdout.flush() - rec, de, du=energy_conservation(atoms,dt=0.2,steps=100) - assert de/du<0.011 - - - - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/graphene.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/graphene.py deleted file mode 100644 index 2d4095a..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/graphene.py +++ /dev/null @@ -1,29 +0,0 @@ -from ase import * -from hotbit import * -from box.md import check_energy_conservation -from box.systems import graphene -from numpy import * -from hotbit.test.misc import default_param - -R=1.416552 -nkpts = 10 - -# graphene's cohesion energy -atoms=graphene(2,2,R) -atoms=Atoms('C2',[(0,0,0),(2*cos(pi/6)*R,R,0)],pbc=(True,True,False),\ - cell=array([[2*cos(pi/6)*R,0,0],[R*cos(pi/6),R*1.5,0],[0,0,5]]) ) - -calc=Hotbit(SCC=False,txt='graphene.cal',kpts=(nkpts,nkpts,1),**default_param) -atoms.set_calculator(calc) -coh = atoms.get_potential_energy()/2 -assert abs(-9.626283-coh)<1E-6 - - - -# energy conservation -atoms[0].z+=0.1 -calc=Hotbit(SCC=False,txt='graphene.cal',kpts=(3,3,1),**default_param) -atoms.set_calculator(calc) -assert check_energy_conservation(atoms,dt=0.5*units.fs,steps=30,tol=1E-2,plot=False) - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/hydrocarbon-test.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/hydrocarbon-test.py deleted file mode 100644 index 80c08a7..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/hydrocarbon-test.py +++ /dev/null @@ -1,326 +0,0 @@ -from ase import * -from hotbit import Hotbit -import numpy as np -import sys - -""" -This is a test script that gives insight how good are -the parametrizations for H-H, C-C and C-H. Reference -values are taken from - - D. Porezag et al., Physical Review B, volume 51, number 19, 1995 - -Same molecules are optimized using the default parametrizations -and the quantities are compared to the reference values. -""" - - -porezag_data = { - 'H2':{'HH':0.765}, - 'CH':{'CH':1.138}, - 'CH2':{'CH':1.134, 'HCH':98.6}, - 'CH3':{'CH':1.114, 'HCH':116.8}, - 'CH4':{'CH':1.116}, - 'C2H2':{'CC':1.206, 'CH':1.099}, - 'C2H4':{'CC':1.321, 'CH':1.113, 'CCH':116.3}, - 'C2H6':{'CC':1.503, 'CH':1.119, 'HCH':108.0}, - 'C3H4':{'C1C2':1.318, 'C2C3':1.509, 'C1H':1.109, 'HC1C2':148.4}, - 'C3H6':{'CC':1.503, 'CH':1.114}, - 'C4H10':{'C1C2':1.511, 'C2C3':1.520}, - 'C6H6':{'CC':1.389, 'CH':1.114} - } - -reference_data = { - 'H2':{'HH':0.765}, - 'CH':{'CH':1.152}, - 'CH2':{'CH':1.135, 'HCH':99.1}, - 'CH3':{'CH':1.093, 'HCH':120}, - 'CH4':{'CH':1.101}, - 'C2H2':{'CC':1.212, 'CH':1.078}, - 'C2H4':{'CC':1.331, 'CH':1.098, 'CCH':116.4}, - 'C2H6':{'CC':1.513, 'CH':1.105, 'HCH':107.2}, - 'C3H4':{'C1C2':1.305, 'C2C3':1.510, 'C1H':1.091, 'HC1C2':149.5}, - 'C3H6':{'CC':1.504, 'CH':1.095}, - 'C4H10':{'C1C2':1.517, 'C2C3':1.532}, - 'C6H6':{'CC':1.396, 'CH':1.095} - } - -def length(atoms, a, b): - return np.linalg.norm(atoms.positions[a] - atoms.positions[b]) - - -def angle(atoms, a, b, c, unit='deg'): - """ Return the angle a-b-c. """ - vec1 = atoms.positions[b] - atoms.positions[a] - vec2 = atoms.positions[b] - atoms.positions[c] - angle = np.arccos(np.dot(vec1, vec2)/(np.linalg.norm(vec1)*np.linalg.norm(vec2)))*180/np.pi - if unit == 'deg': - k = 1. - elif unit == 'rad': - k = 180/np.pi - return k*angle - - -def optimize(atoms, fmax=0.01): - atoms.center(vacuum=6) - atoms.rattle() - if atoms.get_calculator() == None: - atoms.set_calculator(Hotbit()) - dyn = QuasiNewton(atoms, maxstep=0.01) - dyn.run(fmax=fmax) - - -def H2(data): - name = 'H2' - data[name] = {} - atoms = Atoms('H2',((0, 0, 0), - (0.76, 0, 0))) - optimize(atoms) - - data[name]['HH'] = length(atoms, 0, 1) - - -def CH(data): - name = 'CH' - data[name] = {} - atoms = Atoms('CH',((0, 0, 0), - (1.1, 0, 0))) - optimize(atoms) - - data[name]['CH'] = length(atoms, 0, 1) - - -def CH2(data): - name = 'CH2' - data[name] = {} - atoms = Atoms('CH2', - ((7.348, 5.390, 5.640), - (6.288, 5.745, 5.850), - (8.038, 6.169, 6.098))) - optimize(atoms) - - data[name]['CH'] = length(atoms, 0, 1) - data[name]['HCH'] = angle(atoms, 1,0,2) - - -def CH3(data): - name = 'CH3' - data[name] = {} - a = 1.1 - atoms = Atoms('CH3', - ((6.550, 6.952, 6.000), - (7.650, 6.952, 5.999), - (6.001, 7.904, 5.999), - (6.001, 6.000, 5.999))) - optimize(atoms) - - data[name]['CH'] = length(atoms, 0, 1) - data[name]['HCH'] = angle(atoms, 1, 0, 2) - - -def CH4(data): - name = 'CH4' - data[name] = {} - atoms = Atoms('CH4', - ((6.459, 6.786, 6.250), - (6.422, 6.706, 7.388), - (7.547, 6.808, 5.905), - (5.935, 7.745, 5.918), - (5.931, 5.886, 5.787))) - optimize(atoms) - data[name]['CH'] = length(atoms, 0, 1) - - -def C2H2(data): - name = 'C2H2' - data[name] = {} - atoms = Atoms('C2H2', - ((7.226, 5.993, 6.042), - (8.382, 5.973, 6.040), - (6.157, 6.012, 6.045), - (9.451, 5.954, 6.037))) - optimize(atoms) - - data[name]['CC'] = length(atoms, 0, 1) - data[name]['CH'] = length(atoms, 0, 2) - - -def C2H4(data): - name = 'C2H4' - data[name] = {} - atoms = Atoms('C2H4', - ((6.469, 6.865, 6.009), - (7.736, 6.864, 5.992), - (5.902, 7.807, 6.017), - (5.903, 5.922, 6.017), - (8.303, 7.807, 5.984), - (8.302, 5.921, 5.984))) - optimize(atoms) - - data[name]['CC'] = length(atoms, 0, 1) - data[name]['CH'] = length(atoms, 0, 2) - data[name]['CCH'] = angle(atoms, 1, 0, 2) - - -def C2H6(data): - name = 'C2H6' - data[name] = {} - atoms = Atoms('C2H6', - ((6.434, 6.752, 6.343), - (6.433, 6.751, 7.856), - (7.506, 6.751, 5.987), - (5.898, 7.680, 5.985), - (5.898, 5.823, 5.987), - (7.505, 6.751, 8.214), - (5.896, 7.679, 8.213), - (5.897, 5.822, 8.212))) - optimize(atoms) - - - data[name]['CC'] = length(atoms, 0, 1) - data[name]['CH'] = length(atoms, 0, 3) - data[name]['HCH'] = angle(atoms, 5, 1, 6) - - -def C3H4(data): - name = 'C3H4' - a=1.2 - data[name] = {} - atoms = Atoms('C3H4', - ((6.722, 6.495, 6.659), - (7.979, 6.359, 6.670), - (7.498, 7.780, 6.624), - (5.748, 6.021, 6.667), - (8.828, 5.687, 6.693), - (7.555, 8.386, 7.548), - (7.565, 8.327, 5.665))) - optimize(atoms) - - data[name]['C1C2'] = length(atoms, 0, 1) - data[name]['C2C3'] = length(atoms, 0, 2) - data[name]['C1H'] = length(atoms, 0, 3) - data[name]['HC1C2'] = angle(atoms, 3,0,1) - - -def C3H6(data): - name = 'C3H6' - data[name] = {} - atoms = Atoms('C3H6', - ((6.283, 6.485, 6.760), - (7.603, 6.293, 6.078), - (7.037, 7.670, 6.239), - (6.267, 6.352, 7.851), - (8.457, 6.032, 6.721), - (7.518, 8.317, 6.988), - (5.388, 6.181, 6.197), - (7.579, 5.865, 5.065), - (6.639, 8.150, 5.333))) - optimize(atoms) - - data[name]['CC'] = length(atoms, 0, 1) - data[name]['CH'] = length(atoms, 0, 3) - - -def C4H10(data): - name = 'C4H10' - data[name] = {} - atoms = Atoms('C4H10', - ((7.350, 7.576, 7.578), - (8.621, 6.992, 7.003), - (9.880, 7.612, 7.587), - (11.151, 7.021, 7.018), - (7.340, 8.686, 7.372), - (7.338, 7.376, 8.689), - (8.630, 5.900, 7.232), - (8.619, 7.183, 5.903), - (9.874, 8.703, 7.348), - (9.880, 7.432, 8.689), - (11.155, 5.912, 7.227), - (11.168, 7.219, 5.907), - (6.478, 7.068, 7.072), - (12.023, 7.526, 7.527))) - optimize(atoms) - - data[name]['C1C2'] = length(atoms, 0, 1) - data[name]['C2C3'] = length(atoms, 1, 2) - - -def C6H6(data): - name = 'C6H6' - data[name] = {} - a=1.2 - b=2.1 - atoms = Atoms('C6H6', - ((9.444, 7.815, 6.065), - (8.770, 8.981, 6.062), - (7.423, 8.981, 6.061), - (6.750, 7.814, 6.063), - (7.424, 6.648, 6.062), - (8.771, 6.649, 6.063), - (10.533, 7.816, 6.069), - (9.314, 9.925, 6.059), - (6.879, 9.923, 6.057), - (5.661, 7.814, 6.066), - (6.879, 5.705, 6.063), - (9.316, 5.706, 6.063))) - optimize(atoms) - - data[name]['CC'] = length(atoms, 0, 1) - data[name]['CH'] = length(atoms, 0, 6) - - -def geometry_test(data): - C3H4(data) - H2(data) - CH(data) - CH2(data) - CH3(data) - CH4(data) - C2H2(data) - C2H4(data) - C2H6(data) - C3H6(data) - C4H10(data) - C6H6(data) - - -order = ['H2','CH','CH2','CH3','CH4','C2H2','C2H4','C2H6','C3H4','C3H6','C4H10','C6H6'] - - -def print_results(data): - rel_error_current = 0.0 - rel_error_porezag = 0.0 - print "" - print "Current: value of the quantity calculated with default parameters." - print "Porezag: values reported in Phys. Rev. B, volume 51, number 19, 1995" - print "LSD: DFT_LSD values obtained from the same paper." - print "d: the relative error of the previous value compared to" - print " the LSD value (d=(x - x_LSD)/x_LSD)." - print "" - print "The two-atom variables are bond lengths (in Angtroms) and" - print "three-atom variables angles (in degrees)." - print "" - print "%9s %9s %9s %9s %9s %9s %9s" % ('Molecule', 'Variable', 'LSD', 'Current', 'd', 'Porezag', 'd') - N = 0 - for n, k in enumerate(order): - for i, kv in enumerate(data[k].items()): - N += 1 - key, value = kv - if i == 0: - molecule = k - else: - molecule = '' - d = value/reference_data[k][key]-1 - rel_error_current += d**2 - print "%9s %9s %9.3f %9.3f %9.3f" % (molecule, key, reference_data[k][key], value, d), - d = porezag_data[k][key]/reference_data[k][key]-1 - rel_error_porezag += d**2 - print "%9.3f %9.3f" % (porezag_data[k][key], d), - print '' - print " The RMS of relative errors: %0.3f %0.3f" % (np.sqrt(rel_error_current/N), np.sqrt(rel_error_porezag/N)) - - -if __name__ == '__main__': - data = {} - geometry_test(data) - print_results(data) diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/linear_response.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/linear_response.py deleted file mode 100644 index 6e7f1f8..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/linear_response.py +++ /dev/null @@ -1,26 +0,0 @@ -from ase import * -from hotbit import Hotbit -from hotbit.analysis import LinearResponse -from ase.data.molecules import molecule -from hotbit.test.misc import default_param - -atoms=Atoms('Na3',[(1.6964999745231999,0,0),(-1.6964999745231999,0,0),(0,2.9384240999630005,0)]) -atoms.center(vacuum=5) - -default_param['width'] = 0.0136 - -calc=Hotbit(SCC=True,charge=1,txt='linear_response.cal',**default_param) -atoms.set_calculator() -calc.solve_ground_state(atoms) - -lr=LinearResponse(calc,energy_cut=2000,txt='linear_response.txt') -lr.run() -lr.plot_spectrum('Na3+_lr.png',width=0.08) - -el = [1.81951,1.81951,7.43599,7.43599] -fl = [0.43036,0.43036,4.27744,4.27744] - -for i in range(4): - e,f = lr.get_excitation(i) - assert abs(e-el[i])<1E-4 and abs(f-fl[i])<1E-4 - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/madelung_constants.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/madelung_constants.py deleted file mode 100644 index 306120b..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/madelung_constants.py +++ /dev/null @@ -1,102 +0,0 @@ -#! /usr/bin/env python - -from math import sqrt - -import numpy as np - -from ase import Atoms -from ase.io import write -from ase.lattice.compounds import CsCl, NaCl, ZnS - -from hotbit.atoms import Atoms as HotbitAtoms -from hotbit.coulomb import EwaldSum, MultipoleExpansion - -### - -L_MAX = 8 -K = 5 - -Q = 1.0 -a0 = 1.0 - -debug = False - -### - -# FIXME!!! Look for more digits -M_NaCl = 1.747565 -M_CsCl = 1.762675 -M_ZnS = 1.638055 - -systems = [ -# ( "NaCl", M_NaCl, 0.5, -# NaCl(['Na', 'Cl'], -# latticeconstant = a0, -# size = [1, 1, 1]) ), - ( "CsCl", M_CsCl, sqrt(3.0)/2, - CsCl(['Cs', 'Cl'], - latticeconstant = a0, - size = [1, 1, 1]) ), -# ( "ZnS", M_ZnS, sqrt(3.0)/4, -# ZnS(['Zn', 'S'], -# latticeconstant = a0, -# size = [1, 1, 1]) ), -# Some tests with extended unit cells, not necessary -# ( "large NaCl", M_NaCl, 0.5, -# NaCl(['Na', 'Cl'], -# latticeconstant = a0, -# size = [4, 4, 4]) ), -# ( "large CsCl", M_CsCl, sqrt(3.0)/2, -# CsCl(['Cs', 'Cl'], -# latticeconstant = a0, -# size = [4, 4, 4]) ), -# ( "large ZnS", M_ZnS, sqrt(3.0)/4, -# ZnS(['Zn', 'S'], -# latticeconstant = a0, -# size = [4, 4, 4]) ) - ] - -solvers = [ - MultipoleExpansion(L_MAX, 3, K), -# MultipoleExpansion(L_MAX, 4, K), - EwaldSum(12, 0.001) -] - -if debug: - print "%20s %8s %8s (%8s)" % ( "compound", "M", "ref.", "error" ) - print "%20s %8s %8s %10s" % ( "-------------------", - "--------", "--------", "----------" ) - -for sol in solvers: - if debug: - print "=== %s ===" % sol.__class__ - for name, target_M, nnd, a in systems: - syms = a.get_chemical_symbols() - - #a.set_charges([ (Q if sym == syms[0] else -Q) for sym in syms ]) - # to work with older versions - a.set_charges([ (-Q,Q)[sym==syms[0]] for sym in syms ]) - - a.translate([0.25*a0,0.25*a0,0.25*a0]) - if debug: - write("%s.cfg" % name, a) - - ha = HotbitAtoms(a, container='Bravais') - - sol.update(ha, ha.get_charges()) - - phi = sol.get_potential() - e = np.sum(a.get_charges()*phi)/2 - M = -2*e*a0*nnd/(len(a)) - err = abs(M-target_M) - - if debug: - print "%20s %8.6f %8.6f (%8.6e)" % ( name, M, target_M, err ) - - assert err < 1e-3 - - - -if debug: - for sol in solvers: - sol.timer.summary() diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/mio.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/mio.py deleted file mode 100644 index c007ba0..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/mio.py +++ /dev/null @@ -1,211 +0,0 @@ -""" -Test the mio parametrization of Frauenheim and co-workers. -""" - -import os -import glob - -import numpy as np - -from ase import read, FIRE, QuasiNewton, molecule -from hotbit import Hotbit, database_from_path - -### - -FMAX = 0.005 -OPT = FIRE - -debug = False - -### - -# From Elstner et al., Phys. Rev. B 58, 7260 -noscc_db = { - 'C=O': 1.296, - 'C-N': 1.296, - 'N-H': 1.003, - 'C-H': 1.130, - 'OCN': 127.0 - } - -scc_db = { - 'C=O': 1.224, - 'C-N': 1.382, - 'N-H': 0.996, - 'C-H': 1.131, - 'OCN': 125.5 - } - -db1 = { - False: noscc_db, - True: scc_db - } - -# From Kruger et al., J. Chem. Phys. 122, 114110 -db2 = { - 'H2': { - 'H-H': ( ( 0, 1 ), 0.750 ) - }, - 'C2H2': { - 'C-H': ( ( 1, 2 ), 1.075 ), - 'C-C': ( ( 0, 1 ), 1.203 ) - }, - 'C2H4': { - 'C-H': ( ( 0, 2 ), 1.094 ), - 'C-C': ( ( 0, 1 ), 1.328 ) - }, - 'C2H6': { - 'C-H': ( ( 0, 3 ), 1.098 ), - 'C-C': ( ( 0, 1 ), 1.501 ) - }, - 'HCN': { - 'C-H': ( ( 0, 2 ), 1.078 ), - 'C-N': ( ( 0, 1 ), 1.141 ) - }, - 'NH3': { - 'N-H': ( ( 0, 1 ), 1.021 ) - }, - 'CH4': { - 'C-H': ( ( 0, 1 ), 1.089 ) - }, - 'CO': { - # This differs from the paper, but I believe it's a typo - # paper says: 1.200 - 'C-O': ( ( 0, 1 ), 1.100 ) - }, - 'H2CO': { - 'C-H': ( ( 1, 2 ), 1.143 ), - 'C-O': ( ( 0, 1 ), 1.183 ) - }, - 'CH3OH': { - 'O-H': ( ( 1, 3 ), 0.980 ), - 'C-O': ( ( 0, 1 ), 1.422 ) - }, - 'H2O': { - 'O-H': ( ( 0, 1 ), 0.968 ) - }, - 'N2': { - # This differs from the paper, but I believe it's a typo - # paper says: 1.200 - 'N-N': ( ( 0, 1 ), 1.113 ) - }, - 'N2H4': { - 'N-H': ( ( 0, 2 ), 1.037 ), - # This differs from the paper, and I don't know why - # paper says: 1.442 - 'N-N': ( ( 0, 1 ), 1.407 ) - }, - 'H2O2': { - 'O-H': ( ( 0, 2 ), 0.991 ), - 'O-O': ( ( 0, 1 ), 1.453 ) - }, - 'CO2': { - 'C-O': ( ( 0, 1 ), 1.165 ) - } - } - - -def check_q(db, name, value): - refvalue = db[name] - if debug: - print '%10s %10.3f %10.3f' % ( name, value, refvalue ) - #assert abs(value-refvalue) < 1e-3 - - -def check_db(db, params): - if debug: - print "%10s %10s %10s ( %10s )" \ - % ( "bond", "value", "reference", "error" ) - for mol, values in db.iteritems(): - #if mol == 'H2O': - if 1: - if debug: - print mol - - a = molecule(mol) - a.center(vacuum=10.0) - a.set_pbc(False) - - #print a.get_chemical_symbols() - - calc = Hotbit( - charge_density = 'Slater', - SCC = True, - width = 1e-6, - txt = 'mio.out', - **params) - a.set_calculator(calc) - - #calc.ia.plot_table('H', 'H') - #calc.rep.get_repulsion('H', 'H').plot() - - OPT(a, logfile='opt.log').run(fmax=FMAX) - - #print a.get_charges() - - for name, ( ( i1, i2 ), refvalue ) in values.iteritems(): - value = a.get_distance(i1, i2) - if debug: - print '%10s %10.3f %10.3f ( %10.3f )' % \ - ( name, value, refvalue, abs(value-refvalue) ) - assert abs(value-refvalue) < 0.01 - - #e = [ ] - #for x in np.linspace(0.70, 0.80, 1000): - # a.set_distance(0, 1, x) - # e += [ ( x, a.get_potential_energy() ) ] - #np.savetxt('e.out', e) - -### - -params = database_from_path(os.getenv('MIO_0_1')) - -### - -if debug: - for SCC in [ False, True ]: - if SCC: - print "--- SCC ---" - else: - print "--- no SCC ---" - - calc = Hotbit( - charge_density = 'Slater', - SCC = SCC, - verbose = True, - verbose_SCC = True, - mixer = { - 'name': 'anderson', - 'convergence': 1e-6, - 'mixing_constant': 0.01 }, - maxiter = 1000, - txt = 'mio.out', - **params) - - a = read('formamide.xyz') - a.center(vacuum=10.0) - a.set_pbc(False) - a.set_calculator(calc) - - OPT(a, logfile='opt.log').run(fmax=FMAX) - - iO = 0 - iC = 1 - iN = 2 - iHC = 3 - iHN = 4 - - assert a[iO].get_symbol() == 'O' - assert a[iC].get_symbol() == 'C' - assert a[iN].get_symbol() == 'N' - assert a[iHC].get_symbol() == 'H' - assert a[iHN].get_symbol() == 'H' - - check_q(db1[SCC], 'C=O', a.get_distance(iC, iO)) - check_q(db1[SCC], 'C-N', a.get_distance(iC, iN)) - check_q(db1[SCC], 'N-H', a.get_distance(iN, iHN)) - check_q(db1[SCC], 'C-H', a.get_distance(iC, iHC)) - -### - -check_db(db2, params) diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/misc.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/misc.py deleted file mode 100644 index 9f28af3..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/misc.py +++ /dev/null @@ -1,17 +0,0 @@ -import os -from ase.data.molecules import molecule as ase_molecule -from ase import * -from hotbit import fixpar - -ddir = fixpar+'/' - -default_elements={'C':ddir+'C.elm','Au':ddir+'Au.elm','H':ddir+'H.elm','N':ddir+'N.elm','Na':ddir+'Na.elm','O':ddir+'O.elm'} -default_tables={'AuAu':ddir+'Au_Au.par','CC':ddir+'C_C.par','HH':ddir+'H_H.par','NN':ddir+'N_N.par','CH':ddir+'C_H.par','CN':ddir+'C_N.par','NH':ddir+'N_H.par','NaNa':ddir+'Na_Na.par','OH':ddir+'O_H.par','OO':ddir+'O_O.par','CO':ddir+'C_O.par','AuC':ddir+'Au_C.par'} -default_param={'elements':default_elements,'tables':default_tables,'mixer':{'name':'Anderson','memory':3,'mixing_constant':0.2,'convergence':1E-7},'maxiter':1000,'width':0.02} - - -def molecule(name): - if name=='AuC': - return Atoms('AuC',[(0,0,0),(1.85,0,0)]) - else: - return ase_molecule(name) diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/mulliken.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/mulliken.py deleted file mode 100644 index d24d499..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/mulliken.py +++ /dev/null @@ -1,323 +0,0 @@ -from ase import * -try: - from pylab import * -except: - pass -from ase import Atoms as ase_Atoms -from hotbit import * -from hotbit.atoms import Atoms -from hotbit.test.misc import default_param -from numpy import * -from box.systems import graphene -from ase.data.molecules import molecule - -eps = 1E-6 - -if True: - atoms = graphene(2,2,1.42) - calc = Hotbit(SCC=False,kpts=(4,4,1),txt='-',**default_param) - atoms.set_calculator(calc) - atoms.get_potential_energy() - - # compare to Fig.4 of Koskinen & Makinen, CMS 47, 237 (2009) - if False: - w=0.2 - x,y = calc.get_covalent_energy('default',width=w,window=(-20,15)) - plot(x,y,label='total') - axhline(0) - x,y = calc.get_covalent_energy('angmom',i=0,j=0,width=w,window=(-20,15)) - plot(x,y,label='ss') - x,y = calc.get_covalent_energy('angmom',i=0,j=1,width=w,window=(-20,15)) - plot(x,y,label='sp') - x,y = calc.get_covalent_energy('angmom',i=1,j=1,width=w,window=(-20,15)) - plot(x,y,label='pp') - legend() - show() - - - x0,y0 = calc.get_covalent_energy('default') - x1,y1 = calc.get_covalent_energy('angmom',i=0,j=0) - x2,y2 = calc.get_covalent_energy('angmom',i=0,j=1) - x3,y3 = calc.get_covalent_energy('angmom',i=1,j=1) - assert abs(y0.sum()-(y1+y2+y3).sum())>> Mayer bond-order seems not be valid with CH-modeling - # -->>> related to orbitals overlapping with themselves???? - # - # THIS COULD BE INVESTIGATED MORE (9.4 2010) - # - # FIXME - # - # using CH to model benzene - a = Atoms('CH',[(1.395,0,0),(2.482,0,0)],container='Wedge') - a.container.set(M=6,height=3) - #view(a) - c = a.extended_copy(((-2,3),1,1)) - #view(c) - calc = Hotbit(SCC=True,kpts=(1,1,1),txt='-',**default_param) - a.set_calculator(calc) - e6 = a.get_potential_energy()*6 - - MCC = calc.get_mayer_bond_order(0,1) - MCH = calc.get_mayer_bond_order(0,0) - MHH = calc.get_mayer_bond_order(1,1) - print MCC, MCH, MHH - - # Using the full benzene - atoms = a.extended_copy(((-2,3),1,1)) - calc = Hotbit(SCC=True,txt='-',**default_param) - atoms.set_calculator(calc) - atoms.translate(-atoms.get_center_of_mass()) - e = atoms.get_potential_energy() - assert abs(e-e6)= 0 and f2 >= 0 and f3 >= 0: -# h += (-1.0)**(m-n-s)/(factorial(f1)*factorial(s)*factorial(f2)*fact#orial(f3)) * (cos(b/2))**(2*l+n-m-2*s) * (sin(b/2))**(m-n+2*s) -# -# return cexp(-1j*m*a) * cexp(-1j*n*g) * h * factorial(l+n)*factorial(l-n) -### - -### - -ANGLE = 10*pi/180 - -NRUNS = 10 -NAT = 20 -SX, SY, SZ = 10.0, 10.0, 10.0 -CHARGE = 1.0 -L_MAX = 5 - -TOL_MOM = 1e-6 -TOL_PHI = 1e-4 -TOL_PHI2 = 1e-4 -TOL_ROT = 1e-9 - -debug = False - -### - -for run in range(NRUNS): - r0 = np.array( [ SX/2, SY/2, SZ/2 ] ) - r0c = np.array( [ SX, SY, SZ ] ) - - # Random atoms and charges (charges between -1 and 1) - a = [ ] - for i in range(8): - a += [ ase.Atoms( - "%iH" % NAT, - positions = np.random.random([NAT,3])*SX, - charges = (2*np.random.random([NAT])-1)*CHARGE, - cell = [ SX, SY, SZ ] - ) ] - - # Compute moments - M = [ ] - for i in range(8): - M += [ get_moments(a[i].get_positions(), a[i].get_charges(), L_MAX, r0) ] - - # Construct a composite atoms object - # and compute the corresponding multipole - # expansion - b = ase.Atoms(cell=[ 2*SX, 2*SY, 2*SZ ]) - Mc0_l, Mc_L = zero_moments(L_MAX) - for i, ( ca, ( M0_l, M_L ) ) in enumerate(zip(a, M)): - x = i % 2 - y = (i/2) % 2 - z = (i/4) % 2 - - dr = np.array([x*SX, y*SY, z*SZ]) - - ca.translate(dr) - b += ca - - dr = np.array([(2*x-1)*SX/2, (2*y-1)*SY/2, (2*z-1)*SZ/2]) - - multipole_to_multipole(dr, L_MAX, M0_l, M_L, Mc0_l, Mc_L) - - # Compute the multipole moment directly - Md0_l, Md_L = get_moments(b.get_positions(), b.get_charges(), L_MAX, r0c) - - err_mom1 = np.max(np.abs(Mc0_l-Md0_l)) - err_mom2 = np.max(np.abs(Mc_L-Md_L)) - - if debug: - print "err_mom1 = ", err_mom1 - print "err_mom2 = ", err_mom2 - - assert err_mom1 < TOL_MOM and err_mom2 < TOL_MOM - - # Now that we have verified that the moments are okay, - # lets compute the field somewhere randomly. - x, y, z = np.random.random_integers(-3,3,3) - while abs(x) != 3 and abs(y) != 3 and abs(z) != 3: - x, y, z = np.random.random_integers(-3,3,3) - - r0tar = ( np.array([x, y, z]) + np.random.random(3) ) * np.array([2*SX, 2*SY, 2*SZ]) - - L0_l, L_L = multipole_to_local(r0tar - r0c, L_MAX, Mc0_l, Mc_L) - - phi = 0.0 - E = np.zeros(3) - for i in b: - dr = i.get_position() - r0tar - phi += i.get_charge()/sqrt(np.dot(dr, dr)) - E -= i.get_charge()*dr/(np.dot(dr, dr)**(3./2)) - - err_phi1 = abs(phi - L0_l[0]) - err_phi2 = np.max(np.abs(E - np.array([ -L_L[0].real, - -L_L[0].imag, - L0_l[1] ]))) - - if debug: - print "err_phi1 = ", err_phi1 - print "err_phi2 = ", err_phi2 - - assert err_phi1 < TOL_PHI - assert err_phi2 < TOL_PHI - - # Shift the expansion somewhere else - r0tar2 = ( np.array([x, y, z]) + np.random.random(3) ) * np.array([2*SX, 2*SY, 2*SZ]) - - L0_l2, L_L2 = local_to_local(r0tar2 - r0tar, L_MAX, L0_l, L_L, L_MAX) - - phi = 0.0 - E = np.zeros(3) - for i in b: - dr = i.get_position() - r0tar2 - phi += i.get_charge()/sqrt(np.dot(dr, dr)) - E -= i.get_charge()*dr/(np.dot(dr, dr)**(3./2)) - - err_phi3 = abs(phi - L0_l2[0]) - err_phi4 = np.max(np.abs(E - np.array([ -L_L2[0].real, - -L_L2[0].imag, - L0_l2[1] ]))) - - if debug: - print "err_phi3 = ", err_phi3 - print "err_phi4 = ", err_phi4 - - assert err_phi3 < TOL_PHI2 - assert err_phi4 < TOL_PHI2 - - # Compute the multipole moment directly - Md0_l, Md_L = get_moments(b.get_positions(), b.get_charges(), L_MAX, r0c) - - # Now rotate the atoms, recompute the multipole expansion and compare the result - # to the rotated expansion - a1 = 2*pi*random.random() - a2 = 2*pi*random.random() - a3 = 2*pi*random.random() - Rz1 = np.array( [ [ cos(a1), -sin(a1), 0 ], - [ sin(a1), cos(a1), 0 ], - [ 0, 0, 1 ] ] ) - Ry = np.array( [ [ cos(a2), 0, -sin(a2) ], - [ 0, 1, 0 ], - [ sin(a2), 0, cos(a2) ] ] ) - Rz2 = np.array( [ [ cos(a3), -sin(a3), 0 ], - [ sin(a3), cos(a3), 0 ], - [ 0, 0, 1 ] ] ) - - R = np.dot(np.dot(Rz1, Ry), Rz2) - - for i in b: - i.set_position(r0c + np.dot(R, i.get_position() - r0c)) - - Me0_l, Me_L = get_moments(b.get_positions(), b.get_charges(), L_MAX, r0c) - Mf0_l, Mf_L = transform_multipole(R, L_MAX, Md0_l, Md_L) - - err_mom3 = np.max(np.abs(Me0_l-Mf0_l)) - err_mom4 = np.max(np.abs(Me_L-Mf_L)) - - if debug: - print "err_mom3 = ", err_mom3 - print "err_mom4 = ", err_mom4 - - assert err_mom3 < TOL_ROT - assert err_mom4 < TOL_ROT - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/parametrization.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/parametrization.py deleted file mode 100644 index 635c530..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/parametrization.py +++ /dev/null @@ -1,11 +0,0 @@ -from hotbit.parametrization import KSAllElectron, SlaterKosterTable - -atom=KSAllElectron('C',convergence={'density':1E-1,'energies':1E-1},txt='/dev/null') -atom.run() - -table=SlaterKosterTable(atom,atom,txt='/dev/null') -table.run(R1=1,R2=10,N=3,ntheta=50,nr=10,wflimit=1E-7) - - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/pbc.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/pbc.py deleted file mode 100644 index 56fa07e..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/pbc.py +++ /dev/null @@ -1,211 +0,0 @@ -""" -Test the mio parametrization of Frauenheim and co-workers. -""" - -import os -import glob - -import numpy as np - -from ase import read, FIRE, QuasiNewton, molecule -from hotbit import Hotbit, database_from_path - -### - -FMAX = 0.005 -OPT = FIRE - -debug = False - -### - -# From Elstner et al., Phys. Rev. B 58, 7260 -noscc_db = { - 'C=O': 1.296, - 'C-N': 1.296, - 'N-H': 1.003, - 'C-H': 1.130, - 'OCN': 127.0 - } - -scc_db = { - 'C=O': 1.224, - 'C-N': 1.382, - 'N-H': 0.996, - 'C-H': 1.131, - 'OCN': 125.5 - } - -db1 = { - False: noscc_db, - True: scc_db - } - -# From Kruger et al., J. Chem. Phys. 122, 114110 -db2 = { - 'H2': { - 'H-H': ( ( 0, 1 ), 0.750 ) - }, - 'C2H2': { - 'C-H': ( ( 1, 2 ), 1.075 ), - 'C-C': ( ( 0, 1 ), 1.203 ) - }, - 'C2H4': { - 'C-H': ( ( 0, 2 ), 1.094 ), - 'C-C': ( ( 0, 1 ), 1.328 ) - }, - 'C2H6': { - 'C-H': ( ( 0, 3 ), 1.098 ), - 'C-C': ( ( 0, 1 ), 1.501 ) - }, - 'HCN': { - 'C-H': ( ( 0, 2 ), 1.078 ), - 'C-N': ( ( 0, 1 ), 1.141 ) - }, - 'NH3': { - 'N-H': ( ( 0, 1 ), 1.021 ) - }, - 'CH4': { - 'C-H': ( ( 0, 1 ), 1.089 ) - }, - 'CO': { - # This differs from the paper, but I believe it's a typo - # paper says: 1.200 - 'C-O': ( ( 0, 1 ), 1.100 ) - }, - 'H2CO': { - 'C-H': ( ( 1, 2 ), 1.143 ), - 'C-O': ( ( 0, 1 ), 1.183 ) - }, - 'CH3OH': { - 'O-H': ( ( 1, 3 ), 0.980 ), - 'C-O': ( ( 0, 1 ), 1.422 ) - }, - 'H2O': { - 'O-H': ( ( 0, 1 ), 0.968 ) - }, - 'N2': { - # This differs from the paper, but I believe it's a typo - # paper says: 1.200 - 'N-N': ( ( 0, 1 ), 1.113 ) - }, - 'N2H4': { - 'N-H': ( ( 0, 2 ), 1.037 ), - # This differs from the paper, and I don't know why - # paper says: 1.442 - 'N-N': ( ( 0, 1 ), 1.407 ) - }, - 'H2O2': { - 'O-H': ( ( 0, 2 ), 0.991 ), - 'O-O': ( ( 0, 1 ), 1.453 ) - }, - 'CO2': { - 'C-O': ( ( 0, 1 ), 1.165 ) - } - } - - -def check_q(db, name, value): - refvalue = db[name] - if debug: - print '%10s %10.3f %10.3f' % ( name, value, refvalue ) - #assert abs(value-refvalue) < 1e-3 - - -def check_db(db, params): - if debug: - print "%10s %10s %10s ( %10s )" \ - % ( "bond", "value", "reference", "error" ) - for mol, values in db.iteritems(): - #if mol == 'H2O': - if 1: - if debug: - print mol - - a = molecule(mol) - a.center(vacuum=10.0) - a.set_pbc(False) - - #print a.get_chemical_symbols() - - calc = Hotbit( - charge_density = 'Slater', - SCC = True, - width = 1e-6, - txt = 'mio.out', - **params) - a.set_calculator(calc) - - #calc.ia.plot_table('H', 'H') - #calc.rep.get_repulsion('H', 'H').plot() - - OPT(a, logfile='opt.log').run(fmax=FMAX) - - #print a.get_charges() - - for name, ( ( i1, i2 ), refvalue ) in values.iteritems(): - value = a.get_distance(i1, i2) - if debug: - print '%10s %10.3f %10.3f ( %10.3f )' % \ - ( name, value, refvalue, abs(value-refvalue) ) - assert abs(value-refvalue) < 0.01 - - #e = [ ] - #for x in np.linspace(0.70, 0.80, 1000): - # a.set_distance(0, 1, x) - # e += [ ( x, a.get_potential_energy() ) ] - #np.savetxt('e.out', e) - -### - -params = database_from_path(os.getenv('PBC_0_2')) - -### - -if debug: - for SCC in [ False, True ]: - if SCC: - print "--- SCC ---" - else: - print "--- no SCC ---" - - calc = Hotbit( - charge_density = 'Slater', - SCC = SCC, - verbose = True, - verbose_SCC = True, - mixer = { - 'name': 'anderson', - 'convergence': 1e-6, - 'mixing_constant': 0.01 }, - maxiter = 1000, - txt = 'mio.out', - **params) - - a = read('formamide.xyz') - a.center(vacuum=10.0) - a.set_pbc(False) - a.set_calculator(calc) - - OPT(a, logfile='opt.log').run(fmax=FMAX) - - iO = 0 - iC = 1 - iN = 2 - iHC = 3 - iHN = 4 - - assert a[iO].get_symbol() == 'O' - assert a[iC].get_symbol() == 'C' - assert a[iN].get_symbol() == 'N' - assert a[iHC].get_symbol() == 'H' - assert a[iHN].get_symbol() == 'H' - - check_q(db1[SCC], 'C=O', a.get_distance(iC, iO)) - check_q(db1[SCC], 'C-N', a.get_distance(iC, iN)) - check_q(db1[SCC], 'N-H', a.get_distance(iN, iHN)) - check_q(db1[SCC], 'C-H', a.get_distance(iC, iHC)) - -### - -check_db(db2, params) diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/periodicity.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/periodicity.py deleted file mode 100644 index 31aa969..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/periodicity.py +++ /dev/null @@ -1,240 +0,0 @@ -#! /usr/bin/env python - -from math import pi - -import numpy as np - -from ase import Atoms -from ase.io import write -from hotbit.atoms import Atoms as HotbitAtoms -from hotbit.coulomb import MultipoleExpansion -from hotbit.coulomb.multipole import get_moments - -from box.fd_forces import check_forces, check_field - -### - -NAT = 4 -SX, SY, SZ = 10.0, 10.0, 10.0 -CHARGE = 1.0 - -L_MAX = 8 - -NRUNS = 1 - -debug = False - -### - -TOL_MOM = { - 3: 1e-7, - 5: 1e-7 - } -TOL_PHI = { - 3: 1e-5, - 5: 1e-6 - } -TOL_E = { - 3: 1e-5, - 5: 1e-7 - } -TOL_FOR = 1e-6 -#TOL_FIELD = 1e-3 - -### - -def electrostatics_test(b, r=3, r0=None): - if r0 is None: - r0 = np.sum(b.get_positions(), axis=0)/len(a) - - k1 = [ (1,1)[i] for i in b.get_pbc() ] - k3 = [ (1,3)[i] for i in b.get_pbc() ] - - # Check multipole moments - mp = MultipoleExpansion(L_MAX, r, k3, r0) - mp.update(b, b.get_charges()) - - # Store moments and field for later - moments = mp.get_moments() - M0_l_mp, M_L_mp = moments[1] - - phi_mp, E_mp = mp.get_potential_and_field(b) - - # Check if the field is the derivative of the potential - b.set_calculator(mp) - ffd, f0, err = check_forces(b) - if debug: - print "Finite differences forces:" - print ffd - print "Analytical forces:" - print f0 - print "Error:" - print err - - assert err < TOL_FOR - -# ffd, f0, err = check_field(b, mp) -# if debug: -# print "Finite differences field:" -# print ffd -# print "Analytical field:" -# print f0 -# print "Error:" -# print err -# -# assert err < TOL_FIELD - - # Next neighbor shell by direct summation - mp = MultipoleExpansion(L_MAX, r*r*r, k1, r0) - mp.update(b, b.get_charges()) - - phi_dir, E_dir = mp.get_potential_and_field(b) - - # Multipole moments from large cell, - # transform symmetrically around the origin - #rep = [ (r-1)/2 if i else 0 for i in b.get_pbc() ] - #rep = [ (-(r-1)/2, (r-1)/2) if i else (0, 0) for i in b.get_pbc() ] - rep = [ (0,(r-1)/2)[i] for i in b.get_pbc() ] - rep = [ ((0,0),(-(r-1)/2, (r-1)/2))[i] for i in b.get_pbc() ] - c = b.extended_copy(tuple(rep)) - - M0_l, M_L = get_moments(c.get_positions(), c.get_charges(), L_MAX, r0) - - #print M_L - #print M_L_mp - - err_mom0 = np.max(np.abs(M0_l-M0_l_mp)) - err_mom = np.max(np.abs(M_L-M_L_mp)) - - if debug: - print "error(mom) = ", err_mom0, err_mom - - assert err_mom0 < TOL_MOM[r] - assert err_mom < TOL_MOM[r] - - # Compare fields and potentials obtained by the multipole expansion - # and from direct summation - - err_phi = np.max(np.abs(phi_mp-phi_dir)) - err_E = np.max(np.abs(E_mp-E_dir)) - - if debug: - print "error(phi) = ", err_phi - print "error(E) = ", err_E - - assert err_phi < TOL_PHI[r] - assert err_E < TOL_E[r] - - - -for i in range(NRUNS): -# r = np.random.random([NAT,3])*SX -# -# q = (2*np.random.random([NAT])-1)*CHARGE -# q -= np.sum(q)/len(q) - - r = [ [ SX/4, SY/4, SZ/4 ], - [ 3*SX/4, SY/4, SZ/4 ], - [ SX/4, 3*SY/4, SZ/4 ], - [ SX/4, SY/4, 3*SZ/4 ] ] - q = [ 1, -1, 1, -1 ] - - if False: - # no periodicity, this should simply not fail - if debug: - print "0D" - a = Atoms('%iH' % NAT, - positions = r, - charges = q, - cell = [ SX, SY, SZ ], - pbc = False - ) - b = HotbitAtoms( - atoms = a, - container = 'Bravais' - ) - - electrostatics_test(b, 3) - electrostatics_test(b, 5) - - - if True: - # 1D periodicity - if debug: - print "1D" - a = Atoms('%iH' % NAT, - positions = r, - charges = q, - cell = [ SX, SY, SZ ], - pbc = [ False, False, True ] - ) - b = HotbitAtoms( - atoms = a, - container = 'Bravais' - ) - - electrostatics_test(b, 3) - electrostatics_test(b, 5) - - - if True: - # 1D and twisted periodicity - if debug: - print "1D - twisted" - a = Atoms('%iH' % NAT, - positions = r, - charges = q, - cell = [ SX, SY, SZ ], - pbc = [ False, False, True ] - ) - b = HotbitAtoms( - atoms = a, - container = 'Chiral' - ) - b.set_container( - angle = 2*pi/30, - height = SZ - ) - - electrostatics_test(b, 3) - electrostatics_test(b, 5) - - - if True: - # 2D periodicity - if debug: - print "2D" - a = Atoms('%iH' % NAT, - positions = r, - charges = q, - cell = [ SX, SY, SZ ], - pbc = [ True, False, True ] - ) - b = HotbitAtoms( - atoms = a, - container = 'Bravais' - ) - - electrostatics_test(b, 3) - electrostatics_test(b, 5) - - - if False: - # 3D periodicity - if debug: - print "3D" - a = Atoms('%iH' % NAT, - positions = r, - charges = q, - cell = [ SX, SY, SZ ], - pbc = True - ) - b = HotbitAtoms( - atoms = a, - container = 'Bravais' - ) - - electrostatics_test(b, 3) - electrostatics_test(b, 5) - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/polyethene_twisted.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/polyethene_twisted.py deleted file mode 100644 index aa242fe..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/polyethene_twisted.py +++ /dev/null @@ -1,82 +0,0 @@ -from numpy import * -from ase import optimize -from ase import * -from hotbit import * -from math import pi -from hotbit.coulomb import MultipoleExpansion - -from box.md import check_energy_conservation -from box.fd_forces import check_forces - -### - -d = 1.4 -debug = False - -### - -if False: - atoms = Atoms('C4H4', - [(0,0,0),(0.5,0,d),(0,0,2*d),(0.5,0,3*d), - (-1,0,0),(1.5,0,d),(-1,0,2*d),(1.5,0,3*d)], - container = 'Bravais', - cell = [ 4*d, 4*d, 4*d ], - pbc = [ False, False, True ]) - atoms.translate([2*d, 2*d, d/2]) -else: - atoms = Atoms('C4H4', - [(0,0,0),(0.5,0,d),(0,0,2*d),(0.5,0,3*d), - (-1,0,0),(1.5,0,d),(-1,0,2*d),(1.5,0,3*d)], - container='Chiral') - atoms.set_container(angle=2*pi/30,height=4*d) -#view(atoms) - -#calc1 = Hotbit(SCC = False, -# kpts = (1,1,20), -# txt = 'polyethene.cal') -calc2 = Hotbit(SCC = True, - gamma_cut = 3*d, - kpts = (1,1,20), - verbose_SCC = True, - # For the default 1e-3 I obtain an error in force of 2 eV/A! - mixer = { 'name': 'anderson', 'convergence': 1e-6 }, - txt = 'polyethene.cal') -calc3 = Hotbit(SCC = True, - coulomb_solver = MultipoleExpansion(8, 3, (1,1,5)), - verbose_SCC = True, - kpts = (1,1,20), - mixer = { 'name': 'anderson', 'convergence': 1e-6 }, - txt = 'polyethene.cal') - -for calc in [ calc2, calc3 ]: - atoms.set_calculator(calc) - - # Relax (twist) the structure - q = optimize.FIRE(atoms,trajectory='polyethene.trj',logfile=None) - q.run(fmax=0.5) - - # Displace atoms from their equilibrium positions and check forces - atoms.rattle(0.1) - - # Check electrostatics only -# atoms.set_charges([1.0,1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0]) -# atoms.set_calculator(calc.st.es) - - # Check forces from finite differences - ffd, f0, err = check_forces(atoms, dx=1e-6) - if debug: - print "Finite differences forces:" - print ffd - print "Analytical forces:" - print f0 - print "Difference:" - print abs(ffd-f0) - print "Error:" - print err - - assert err < 1e-5 - - # Check energy conservation from a molecular dynamics run - assert check_energy_conservation(atoms,dt=0.25*units.fs,steps=100, - tol=0.01,plot=debug) - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/save_load.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/save_load.py deleted file mode 100644 index cf97d99..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/save_load.py +++ /dev/null @@ -1,45 +0,0 @@ -from ase import * -from hotbit import Hotbit -import numpy as np -import os - -dir = os.environ['HOTBIT_DIR']+'/param/' - -atoms = Atoms('CH2',((0,0,0),(1,0,0),(-1,0,0))) -atoms.center(vacuum=5) -calc = Hotbit(charge=-2, txt='-', - elements={'H':dir + 'H.elm', 'C':dir+'C.elm'}, - tables = {'HH':dir+'H_H.par', 'CC':dir+'C_C.par', 'CH':dir+'C_H.par'}, - SCC=False, - width=0.04, - mixer='pulay') -atoms.set_calculator(calc) -e1 = atoms.get_potential_energy() - -calc.write() -calc2 = Hotbit(txt='-', filename='restart.hb') -atoms2 = calc2.get_atoms() -e2 = atoms2.get_potential_energy() - -if abs(e1-e2) > 1e-7: - raise RuntimeError("The original and loaded calculator doesn't give same results!") - -atoms = Atoms('CH2',((0,0,0),(1,0,0),(-1,0,0)),pbc=[1,1,1]) -atoms.center(vacuum=5) -calc = Hotbit(charge=0, txt='-', - elements={'H':dir + 'H.elm', 'C':dir+'C.elm'}, - tables = {'HH':dir+'H_H.par', 'CC':dir+'C_C.par', 'CH':dir+'C_H.par'}, - SCC=False, - width=0.04, - mixer='pulay') -atoms.set_calculator(calc) -e1 = atoms.get_potential_energy() - -calc.write() -calc2 = Hotbit(txt='-', filename='restart.hb') -atoms2 = calc2.get_atoms() -e2 = atoms2.get_potential_energy() - -if abs(e1-e2) > 1e-7: - raise RuntimeError("The original and loaded calculator doesn't give same results!") -os.system('rm -f restart.hb') diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/size.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/size.py deleted file mode 100644 index 3cf3529..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/size.py +++ /dev/null @@ -1,60 +0,0 @@ -from hotbit import Hotbit -from ase import * -from hotbit.test.misc import default_param -from box.mix import Timer - -from ase.lattice.cubic import FaceCenteredCubic - -t=Timer() - -#atoms = FaceCenteredCubic(directions=[[1,-1,0], [1,1,-2], [1,1,1]], - #size=(1,1,1), symbol='Au', pbc=(1,1,1)) -atoms=read('zz8H.xyz') - -atoms.set_pbc((True,False,False)) -atoms.set_cell((4*2.45951,1000,3000)) -atoms.center() -#view(atoms) -#assert False - -default_param['Anderson_memory']=0 -default_param['convergence']=1E-2 -default_param['mixing_constant']=0.1 -default_param['width']=0.1 -#calc0=Calculator0(verbose=True,SCC=True,gamma_cut=3,txt='sizef.cal',**default_param) -#atoms.set_calculator(calc0) -##atoms.get_forces() -#t() -#calc0.finalize() - -calc=Hotbit(verbose=True,SCC=True,gamma_cut=3,verbose_SCC=True,txt='size.cal',**default_param) -atoms.set_calculator(calc) -atoms.get_forces() - -calc.__del__() -#print calc.st.solver.get_iteration_info() -t() - - - -#systems=['H2COH','AuC'] - -#default_param['convergence']=1E-5 -#default_param['Anderson_memory']=3 -#default_param['width']=0.01 - - -#print ' ... forces for %s, SCC=' %system, SCC - -#atoms=molecule(system) -#atoms.center(vacuum=5) -#atoms[0].z+=0.2 -#atoms=Atoms(atoms) -#atoms.set_calculator(calc) - -#rec, de, du=energy_conservation(atoms,dt=0.2*fs,steps=50) -#calc.__del__() -#print de/du -#assert de/du<0.01 - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/size2.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/size2.py deleted file mode 100644 index 6363909..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/size2.py +++ /dev/null @@ -1,57 +0,0 @@ -from ase import * -from hotbit import Hotbit -from ase.lattice.cubic import FaceCenteredCubic -from hotbit.test.misc import default_param -import pylab as pl -from box import Atoms - - - -for SCC in [True,False]: - timings=[] - norbs=[] - sccs=['non-SCC','SCC'][SCC] - for nx in [1,2,3,4,5]: - for ny in [1,2,3,4,5]: - print 'nx',nx,ny - atoms = FaceCenteredCubic(directions=[[1,-1,0], [1,1,-2], [1,1,1]],\ - size=(nx,ny,1), symbol='Au', pbc=(0,0,0)) - - calc=Hotbit(verbose=True,SCC=SCC,gamma_cut=3,txt='size2.cal',**default_param) - atoms.set_calculator(calc) - try: - atoms.get_forces() - except: - continue - calc.timer.summary() - timings.append( calc.timer.get_timings() ) - norbs.append( calc.el.get_nr_orbitals() ) - calc.__del__() - - order=argsort(norbs) - norbs=sort(norbs) - timings2=[] - for i in order: - timings2.append(timings[i]) - - times={} - maxtime=0.0 - for key in timings2[0]: - times[key]=array([ts[key] for ts in timings2]) - maxtime=max(maxtime,times[key].max()) - - s=0.1 - for key in timings[0]: - s+=0.1 - if times[key].max()<0.05*maxtime: continue - pl.plot(norbs,times[key],label=key,lw=s) - - atoms=Atoms(atoms) - pl.title('Timings up to %s with %s' %(atoms.get_name(),sccs) ) - pl.xlabel('Number of orbitals') - pl.ylabel('Time (s)') - pl.legend(loc='upper left') - pl.savefig('size_timing_%s.png' %sccs) - #pl.plot() - #pl.show() - pl.clf() \ No newline at end of file diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/standard_set.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/standard_set.py deleted file mode 100644 index 2660f16..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/standard_set.py +++ /dev/null @@ -1,29 +0,0 @@ -from hotbit import Hotbit -#from hotbit import Calculator0 -from ase import * -from ase.data.molecules import molecule -from hotbit.test.misc import default_param -import sys - -systems=['C2H6','CH3CH2O','H2COH','H2','C2H6CHOH','isobutane'] -energies0=[-153.471502365,-232.206844117,-166.801950557,-19.356876265,-313.487801685,-287.534640343] -free = [-113.81982575044,-191.66618644170001,-141.09652875422,-12.680510375480001,-248.57609931692002,-214.95914112540004] -energies = [e-ef for e,ef in zip(energies0,free)] - -eps=1E-3 -for system,e in zip(systems,energies): - atoms=molecule(system) - atoms.center(vacuum=10) - atoms.set_pbc(False) - if e==0: - calc=Calculator0(verbose=True,SCC=False,txt='standard.cal',**default_param) - atoms.set_calculator(calc) - print 'new system',system,atoms.get_potential_energy() - sys.exit(0) - - calc=Hotbit(verbose=True,SCC=True,txt='standard.cal',**default_param) - atoms.set_calculator(calc) - e1=atoms.get_potential_energy() - if abs(e1-e)>eps: - raise AssertionError('Energy for %s is %.7f, while should be %.7f' %(system,e1,e)) - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/test.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/test.py deleted file mode 100644 index 313db02..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/test.py +++ /dev/null @@ -1,58 +0,0 @@ -import os -from time import time -import os - -tests = [ - 'atom_dimer.py', - 'standard_set.py', - 'forces.py', - 'external_field.py', - 'parametrization.py', - 'Au_chain.py', - 'graphene.py', - 'CNT5_0_chiral.py', - 'polyethene_twisted.py', - 'C6H6_wedge.py', - 'linear_response.py', - 'C6H6_cell_game.py', - 'save_load.py', - 'copy_calculator.py', - 'mulliken.py', - 'multipole_operations.py', - 'periodicity.py', - 'madelung_constants.py', - 'mio.py'] - - -skip = ['save_load.py','copy_calculator.py'] -add_env = { - 'mio.py': 'MIO_0_1' - } - -start = time() - -pth=os.environ.get('HOTBIT_DIR') - -for test in tests: - if test in skip: - print 'test', test,'skipped...' - continue - if test in add_env: - if not add_env[test] in os.environ: - print 'test', test, 'requires environment variable', \ - add_env[test], 'skipped...' - continue - try: - file = os.path.join(pth,'hotbit','test',test) - t1 = time() - ret=os.system('python %s' %file) - elapsed = time()-t1 - if ret!=0: - print test,'returned',ret,'and FAILED!' - else: - print '%-25s OK. (%.1f seconds)' %(test,elapsed) - except: - print test,'ERROR!' - -stop = time() -print "Total time elapsed: %.0f seconds." %(stop-start) diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/test_containers.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/test_containers.py deleted file mode 100644 index 79ca045..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/test_containers.py +++ /dev/null @@ -1,43 +0,0 @@ -from ase import * -from hotbit import * -from numpy import * -from box.systems import nanotube - -# testing chiral -atoms = nanotube('C',1.42,5,0) -atoms = Atoms(atoms,container='Chiral') -atoms.set_container(angle=0.0) -traj=PickleTrajectory('tmp.trj','w',atoms) -for angle in concatenate( (linspace(0,pi/2,50),linspace(pi/2,0,50)) ): - atoms.set_container(angle=angle,scale_atoms=True) - traj.write() - - -h = atoms.get_cell()[2,2] -for height in concatenate( (linspace(h,2*h,59),linspace(2*h,h,50)) ): - atoms.set_container(height=height,scale_atoms=True) - traj.write() - -for height,angle in zip( linspace(h,2*h),linspace(0,pi/4,50) ): - atoms.set_container(angle=angle,height=height,scale_atoms=True) - traj.write() - - -# testing wedge -atoms = Atoms('C2',[(2,0,0),(2.5,1,1)],container='Wedge') -atoms.set_container(angle=pi/4,height=2.0) - -traj=PickleTrajectory('tmp2.trj','w',atoms) -for height in concatenate( (linspace(2,4,50),linspace(4,2,50)) ): - atoms.set_container(height=height,scale_atoms=True) - traj.write() - - -for M in concatenate( (range(100,3,-1),range(4,101)) ): - atoms.set_container(M=M,scale_atoms=True) - traj.write() - -for height,M in zip( concatenate( (linspace(2,4,50),linspace(4,2,50)) ),concatenate( (range(50,3,-1),range(4,50)) )): - atoms.set_container(height=height,M=M,scale_atoms=True) - traj.write() - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/test_lr.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/test_lr.py deleted file mode 100644 index b40bc2b..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/test_lr.py +++ /dev/null @@ -1,50 +0,0 @@ -from hotbit import Hotbit -from hotbit import LinearResponse -from hotbit.test.misc import default_param -from ase import * -from box import Atoms -plot=True -try: - import pylab as pl -except: - plot=False - -import numpy as np -from box import mix - - -from ase.units import Hartree - -Na3=Atoms('Na3',positions=[(1.69649997,0,0),(-1.69649997,0,0),(0,2.9384241,0)],cell=(50,50,50),pbc=False) -tm=mix.Timer() - -calc=Hotbit(charge=1,SCC=True,txt='test_lr.cal',**default_param) -Na3.set_calculator(calc) -calc.solve_ground_state(Na3) -lr=LinearResponse(calc) -omega,F=lr.get_linear_response() -e,f=mix.broaden(omega,F,width=0.1) - -if plot: - pl.scatter(e2,f2) - pl.plot(e,f,label='python') - pl.legend() - pl.show() - -calc=Hotbit(SCC=True,txt='test_lr.cal',**default_param) -C60=Atoms(read('C60.xyz')) -C60.set_calculator(calc) -calc.solve_ground_state(C60) -lr=LinearResponse(calc,energy_cut=10/Hartree) -omega,F=lr.get_linear_response() -e,f=mix.broaden(omega,F,width=0.1) - -if plot: - pl.plot(e,f) - pl.show() - - - - - - diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/water.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/water.py deleted file mode 100644 index 61f4ac6..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/test/water.py +++ /dev/null @@ -1,17 +0,0 @@ -from hotbit import Hotbit -from ase import * -from box import Atoms -from box.md import quench -from hotbit.test.misc import default_param -#import cgitb; cgitb.enable() - -h2o=read('H2O.xyz') -h2o.center(vacuum=5) - -calc=Hotbit(verbose=True,SCC=True,verbose_SCC=False,txt='h2o.cal',**default_param) -h2o.set_calculator(calc) -print h2o.get_potential_energy() -#print h2o.get_forces() - -calc.timer.summary() -print calc.timer.get_timings() diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/vdw.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/vdw.py deleted file mode 100644 index 702a27d..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/vdw.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (C) 2008 NSC Jyvaskyla -# Please see the accompanying LICENSE file for further information. - -from math import sqrt - -import numpy as np -from ase.units import Hartree, Bohr -from weakref import proxy - - -def C6_from_p(p, nvel): - N = 1.17 + 0.33*nvel - return 0.75*sqrt(N*p) - - -def p_from_C6(C6, nvel): - N = 1.17 + 0.33*nvel - return (C6/0.75)**2/N - - -class vdWPairCorrection: - - def __init__(self, C6a, pa, nvela, R0a, C6b=None, pb=None, nvelb=None, R0b=None, d=3.0, N=7, M=4, Rmax=10.0): - self.C6a = C6a - self.pa = pa - self.nvela = nvela - self.R0a = R0a - if C6b is None and pb is None and nvelb is None: - self.C6b = C6a - self.pb = pa - self.nvelb = nvela - else: - self.C6b = C6b - self.pb = pb - self.nvelb = nvelb - if R0b is None: - self.R0b = R0a - else: - self.R0b = R0b - self.d = d - self.N = N - self.M = M - self.Rmax = Rmax - - # Compute missing coefficients - if self.C6a is None: - self.C6a = C6_from_p(self.pa, self.nvela) - elif self.pa is None: - self.pa = p_from_C6(self.C6a, self.nvela) - if self.C6b is None: - self.C6b = C6_from_p(self.pb, self.nvelb) - elif self.pb is None: - self.pb = p_from_C6(self.C6b, self.nvelb) - - # Compute cross terms - self.C6ab = 2 * self.C6a * self.C6b * self.pa * self.pb / (self.pa**2 * self.C6a + self.pb**2 * self.C6b) - self.R0ab = (self.R0a**3 + self.R0b**3)/(self.R0a**2 + self.R0b**2) - - - def __call__(self, r, der=0): - if r is None: - return self.Rmax - - h2 = self.d/(self.R0ab**self.N) - h1 = np.exp(-h2*r**self.N) - f = (1.0-h1)**self.M - h3 = self.C6ab/(r**6) - - if der == 0: - return -f * h3 - elif der == 1: - df = self.M*(1.0-h1)**(self.M-1) * h2*self.N*r**(self.N-1)*h1 - return ( 6 * f / r - df ) * h3 - - -def setup_vdw(calc): - #if calc.get('vdw'): - # raise NotImplementedError('van der Waals interactions are not yet implemented.') - - elms = len(calc.el.present) - for i,s1 in enumerate(calc.el.present): - for s2 in calc.el.present[i:]: - # - # here vdw is simply the interaction - # between elements s1 and s2 - # - e1 = calc.el.elements[s1] - e2 = calc.el.elements[s2] - vdW = vdWPairCorrection(e1.get_C6(), e1.get_p(), e1.get_valence_number(), e1.get_R0(), - e2.get_C6(), e2.get_p(), e2.get_valence_number(), e2.get_R0()) - calc.pp.add_pair_potential(s1,s2,vdW,eVA=False) - - # debug - #x, y, dy = calc.pp.get_table(s1, s2) - #import finite_differences as fd - #dyn = fd.dx(x, y) - #np.savetxt('pp_%s_%s.out' % ( s1, s2 ), np.transpose([x, y, dy, dyn])) diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/version.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/version.py deleted file mode 100644 index 9063dd8..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/version.py +++ /dev/null @@ -1 +0,0 @@ -hotbit_version = "0.1 (svn=exported)" diff --git a/build/lib.macosx-10.7-x86_64-2.7/hotbit/wfpropagation.py b/build/lib.macosx-10.7-x86_64-2.7/hotbit/wfpropagation.py deleted file mode 100644 index bf6e53b..0000000 --- a/build/lib.macosx-10.7-x86_64-2.7/hotbit/wfpropagation.py +++ /dev/null @@ -1,122 +0,0 @@ -import numpy as np -from box import mix -from hotbit.auxil import wf_dot_product, matrix_has_property, same_matrix -dot=np.dot -hbar=0.02342178268 - -def matrix_square_root(A): - """ Return the square root of real symmetric matrix A. - - Matrix multiplications to get inv, sqrt or inverse sqrt - A_inv=U*sqrt(D)*U', where D are diagonal eigenvalue matrix and - U'=transpose(U) - """ - assert matrix_has_property(A,'symmetric') - D, U=np.linalg.eigh(A) - assert np.all(D>=0) - assert matrix_has_property(U,'orthogonal') - d=np.sqrt(D) - return dot( dot(U,np.diag(d)),U.transpose().conjugate() ) - - -def density_matrix(wf,occ): - n=len(occ) - raise NotImplementedError('complexity?') - rho=np.zeros((n,n)) - for i in range(n): - for j in range(n): - rho[i,j]=sum( occ*wf[i,:]*wf[j,:].conjugate() ) - return rho - - -def mulliken(rho,calc,S): - """ Return excess Mulliken populations. """ - q=[] - N=len(calc.el) - rhoS=dot(rho,S) - for i in range(N): - orbitals=calc.el.orbitals(i,indices=True) - q.append( sum(rhoS.diagonal()[orbitals]) ) - return np.array(q)-calc.el.get_valences() - - -class WFPropagation: - def __init__(self,calc): - self.calc=calc - self.st=calc.st - self.ia=calc.ia - self.es=calc.es - self.env=calc.env - - # this is just in case ions are static... - self.S=self.ia.S - self.H0=self.ia.H0 - self.Si=np.linalg.inv(self.S) - self.Ss=matrix_square_root(self.S) - self.Sis=np.linalg.inv(self.Ss) - self.n=self.S.shape[0] - - - def propagate(self,dt): - """ -1/2 -1/2 -1/2 -1/2 - -1/2 1-i/4*[ S(1) * H(1) * S(1) + S(0) * H(0) * S(0) ]*dt 1/2 - wf(t+dt) = S(1) * --------------------------------------------------------------- S(0) wf(t) - -1/2 -1/2 -1/2 -1/2 - 1+i/4*[ S(1) * H(1) * S(1) + S(0) * H(0) * S(0) ]*dt - """ - raise RuntimeError('WF propagation still work in progress -- to be developed.') - wf=self.st.wf - if not isinstance(wf[0,0],complex): - wf=wf*(1.0+0.0j) #make wave functions of complex type - - S=self.S - H0=self.H0 - Si=self.Si # !!! calculate inverse, square root, and inverse square root - Ss=self.Ss # !!! again if ions are moving - Sis=self.Sis - one = np.identity(self.n) - - self.es.construct_tables() - rho=density_matrix(wf,self.calc.st.f) - dq=mulliken(rho,self.calc,S) - - H1=self.es.construct_H1( dq ) - H = H0 + H1*S - - SHS1=dot(Sis,dot(H,Sis)) - SHS0=SHS1 - num = one - 0.25j*(SHS1+SHS0)*dt/hbar - den = one + 0.25j*(SHS1+SHS0)*dt/hbar - prod = dot( num,np.linalg.inv(den) ) - - operator = dot( Sis,dot(prod,Ss) ) - - # check that matrices are OK; to be removed when thigs work (for efficiency) - tol=1E-10 - assert same_matrix( np.dot(Si,S),np.identity(self.n),tol=tol ) - assert same_matrix( np.dot(Ss,Ss),S,tol=tol ) - assert same_matrix( np.dot(Sis,Sis),Si,tol=tol ) - assert same_matrix( np.dot(Sis,Ss),np.identity(self.n),tol=tol ) - - # perform wave function propagation - for i in range(self.n): - wf[:,i]=dot(operator,wf[:,i]) - - rho=density_matrix(wf,self.calc.st.f) - dq=mulliken(rho,self.calc,S) - self.st.wf=wf - self.st.dq=dq - # propagation would need to be done self-consistenly (wrt. dq) - - # !!! make update to work via states.update - #self.st.update(self.st.e,wf) - self.env.propagate_time(dt) - self.st.large_update() - - - - - - - -