def test_emt1(): from ase import Atoms from ase.calculators.emt import EMT from ase.constraints import FixBondLength from ase.io import Trajectory from ase.optimize import BFGS a = 3.6 b = a / 2 cu = Atoms('Cu2Ag', positions=[(0, 0, 0), (b, b, 0), (a, a, b)], calculator=EMT()) e0 = cu.get_potential_energy() print(e0) d0 = cu.get_distance(0, 1) cu.set_constraint(FixBondLength(0, 1)) t = Trajectory('cu2ag.traj', 'w', cu) qn = BFGS(cu) qn.attach(t.write) def f(): print(cu.get_distance(0, 1)) qn.attach(f) qn.run(fmax=0.001) assert abs(cu.get_distance(0, 1) - d0) < 1e-14
def relaxGPAW(structure, label, calc, forcemax=0.1, niter_max=1, steps=10): calc.set(txt=label + '_init.txt') # Set calculator structure.set_calculator(calc) # loop a number of times to capture if minimization stops with high force # due to the VariansBreak calls niter = 0 # If the structure is already fully relaxed just return it if (structure.get_forces()**2).sum(axis=1).max()**0.5 < forcemax: return structure #print('relaxgpaw start',flush=True) traj = Trajectory(label + '_lcao.traj', 'w', structure) while (structure.get_forces()** 2).sum(axis=1).max()**0.5 > forcemax and niter < niter_max: dyn = BFGS(structure, logfile=label + '.log') vb = VariansBreak(structure, dyn, min_stdev=0.01, N=15) dyn.attach(traj) dyn.attach(vb) dyn.run(fmax=forcemax, steps=steps) niter += 1 #print('relaxgpaw over',flush=True) return structure
def relaxGPAW(structure, label, forcemax=0.1, niter_max=1, steps=10): # Set calculator calc = get_calculator() calc.set(txt=label+'_true.txt') # Set calculator structure.set_calculator(calc) # loop a number of times to capture if minimization stops with high force # due to the VariansBreak calls niter = 0 # If the structure is already fully relaxed just return it if (structure.get_forces()**2).sum(axis = 1).max()**0.5 < forcemax: return structure traj = Trajectory(label+'_lcao.traj','w', structure) while (structure.get_forces()**2).sum(axis = 1).max()**0.5 > forcemax and niter < niter_max: dyn = BFGS(structure, logfile=label+'.log') vb = VariansBreak(structure, dyn, min_stdev = 0.01, N = 15) dyn.attach(traj) dyn.attach(vb) dyn.run(fmax = forcemax, steps = steps) niter += 1 E = structure.get_potential_energy() F = structure.get_forces() del calc del dyn return structure, E, F
def relax_VarianceBreak(structure, calc, label='', niter_max=10, forcemax=0.1): ''' Relax a structure and saves the trajectory based in the index i Parameters ---------- structure : ase Atoms object to be relaxed Returns ------- ''' # Set calculator structure.set_calculator(calc) # loop a number of times to capture if minimization stops with high force # due to the VariansBreak calls niter = 0 # If the structure is already fully relaxed just return it if (structure.get_forces()**2).sum(axis = 1).max()**0.5 < forcemax: return structure while (structure.get_forces()**2).sum(axis = 1).max()**0.5 > forcemax and niter < niter_max: dyn = BFGS(structure, logfile=label+'.log') vb = VariansBreak(structure, dyn, min_stdev = 0.01, N = 15) dyn.attach(vb) dyn.run(fmax = forcemax, steps = 200) niter += 1 return structure
def relaxGPAW(structure, label, forcemax=0.1, niter_max=1, steps=10): ''' Relax a structure and saves the trajectory based in the index i Parameters ---------- structure : ase Atoms object to be relaxed i : index which the trajectory is saved under ranks: ranks of the processors to relax the structure Returns ------- structure : relaxed Atoms object ''' # Create calculator calc=GPAW(#poissonsolver = PoissonSolver(relax = 'GS',eps = 1.0e-7), # C mode = 'lcao', basis = 'dzp', xc='PBE', #gpts = h2gpts(0.2, structure.get_cell(), idiv = 8), # C occupations=FermiDirac(0.1), #maxiter=99, # C maxiter=49, # Sn3O3 mixer=Mixer(nmaxold=5, beta=0.05, weight=75), nbands=-50, #kpts=(1,1,1), # C kpts=(2,2,1), # Sn3O3 txt = label+ '_lcao.txt') # Set calculator structure.set_calculator(calc) # loop a number of times to capture if minimization stops with high force # due to the VariansBreak calls niter = 0 # If the structure is already fully relaxed just return it if (structure.get_forces()**2).sum(axis = 1).max()**0.5 < forcemax: return structure traj = Trajectory(label+'_lcao.traj','w', structure) while (structure.get_forces()**2).sum(axis = 1).max()**0.5 > forcemax and niter < niter_max: dyn = BFGS(structure, logfile=label+'.log') vb = VariansBreak(structure, dyn, min_stdev = 0.01, N = 15) dyn.attach(traj) dyn.attach(vb) dyn.run(fmax = forcemax, steps = steps) niter += 1 return structure
def relaxGPAW(structure, label, calc=None, forcemax=0.1, niter_max=1, steps=10): # Create calculator if calc is None: calc = GPAW( poissonsolver=PoissonSolver(relax='GS', eps=1.0e-7), # C mode='lcao', basis='dzp', xc='PBE', gpts=h2gpts(0.2, structure.get_cell(), idiv=8), # C occupations=FermiDirac(0.1), maxiter=99, # C #maxiter=49, # Sn3O3 mixer=Mixer(nmaxold=5, beta=0.05, weight=75), nbands=-50, #kpts=(1,1,1), # C kpts=(2, 2, 1), # Sn3O3 txt=label + '_lcao.txt') else: calc.set(txt=label + '_true.txt') # Set calculator structure.set_calculator(calc) # loop a number of times to capture if minimization stops with high force # due to the VariansBreak calls niter = 0 # If the structure is already fully relaxed just return it if (structure.get_forces()**2).sum(axis=1).max()**0.5 < forcemax: return structure traj = Trajectory(label + '_lcao.traj', 'w', structure) while (structure.get_forces()** 2).sum(axis=1).max()**0.5 > forcemax and niter < niter_max: dyn = BFGS(structure, logfile=label + '.log') vb = VariansBreak(structure, dyn, min_stdev=0.01, N=15) dyn.attach(traj) dyn.attach(vb) dyn.run(fmax=forcemax, steps=steps) niter += 1 E = structure.get_potential_energy() F = structure.get_forces() return structure, E, F
def main(fname): atoms = read(fname) prefix = fname.split("/")[-1] traj = Trajectory(fname + ".traj", atoms) calc = GPAW(mode=PW(600), xc="PBE", nbands="120%", kpts={ "density": 5.4, "even": True }) atoms.set_calculator(calc) relaxer = BFGS(atoms, logfile=fname + ".log") relaxer.attach(traj) relaxer.run(fmax=0.025)
def opt_run(ixsf_path, itraj_path, ixsf_file_name, index): print('%d' % index + ' In directory : %s' % (ixsf_path + ixsf_file_name)) atoms = read(ixsf_path + ixsf_file_name) calc = ANNCalculator(potentials={ "Ga": "Ga.10t-10t.nn", "N": "N.10t-10t.nn" }) atoms.set_calculator(calc) ucf = UnitCellFilter(atoms) opt = BFGS(ucf) traj = Trajectory(itraj_path + 'opt_%i.traj' % index, 'w', atoms) opt.attach(traj, interval=40) opt.run(fmax=0.05)
def main(argv): relax_atoms = (argv[1] == "atoms") runID = int(argv[0]) print("Running job: %d" % (runID)) db_name = db_name_atoms #db_name = "/home/ntnu/davidkl/Documents/GPAWTutorials/ceTest.db" db = ase.db.connect(db_name) new_run = not db.get(id=runID).key_value_pairs["started"] # Update the databse db.update(runID, started=True, converged=False) atoms = db.get_atoms(id=runID) calc = EAM(potential="/home/davidkl/Documents/EAM/mg-al-set.eam.alloy") atoms.set_calculator(calc) init_energy = atoms.get_potential_energy() logfile = "CE_eam/ceEAM%d.log" % (runID) traj = "CE_eam/ceEAM%d.traj" % (runID) trajObj = Trajectory(traj, 'w', atoms) if (relax_atoms): relaxer = BFGS(atoms, logfile=logfile) relaxer.attach(trajObj) relaxer.run(fmax=0.025) energy = atoms.get_potential_energy() else: res = minimize(target_function, x0=4.05, args=(atoms, )) a = res["x"] atoms = set_cell_parameter(atoms, a) energy = atoms.get_potential_energy() print("Final energy: {}, final a_la: {}".format(energy, a)) row = db.get(id=runID) del db[runID] kvp = row.key_value_pairs kvp["init_energy"] = init_energy runID = db.write(atoms, key_value_pairs=kvp) db.update(runID, converged=True) print("Energy: %.2E eV/atom" % (energy / len(atoms))) print("Initial energy: %.2E eV/atom" % (init_energy / len(atoms)))
def main(argv): n_mg = int(argv[0]) atoms = bulk("Al") atoms = atoms * (4, 4, 4) for i in range(n_mg): atoms[i].symbol = "Mg" atoms.rattle(stdev=0.005) calc = gp.GPAW(mode=gp.PW(500), xc="PBE", kpts=(4, 4, 4), nbands="120%") atoms.set_calculator(calc) logfile = "bfgsTest%d.log" % (n_mg) traj = "bfgsTest%d.traj" % (n_mg) trajObj = Trajectory(traj, 'w', atoms) relaxer = BFGS(atoms, logfile=logfile) relaxer.attach(trajObj) try: relaxer.run(fmax=0.05) except: pass
def opt(atoms=None, gen='poscar.gen', fmax=0.3, step=100, v=True): if atoms is None: atoms = read(gen) atoms.calc = IRFF(atoms=atoms, libfile='ffield.json', rcut=None, nn=True) def check(atoms=atoms): epot_ = atoms.get_potential_energy() r = atoms.calc.r.numpy() i_ = np.where(np.logical_and(r < 0.5, r > 0.0001)) n = len(i_[0]) try: assert not np.isnan(epot_), '- Energy is NaN!' except: atoms.write('poscarN.gen') raise ValueError('- Energy is NaN!') optimizer = BFGS(atoms, trajectory="opt.traj") optimizer.attach(check, interval=1) optimizer.run(fmax, step) if v: images = Trajectory('opt.traj') view(images[-1]) return images[-1]
kpts=(k_pts, k_pts, k_pts), occupations=FermiDirac(smear), txt=system_name + '.out') bulk_mat.set_calculator(calc) save_atoms(bulk_mat, e_cut, nbands, k_pts, smear, initial_magmom, int(sys.argv[2]), 1, str(sys.argv[4])) calc = GPAW(mode=PW(e_cut), nbands=nbands, xc='PBE', spinpol=True, kpts=(k_pts, k_pts, k_pts), occupations=FermiDirac(smear), txt=system_name + '.out') saver = Gpw_save(calc, system_name + '_relaxed.gpw') traj = Trajectory(system_name + '_relaxed.traj', 'w', bulk_mat) ucf = UnitCellFilter(bulk_mat) relaxer = BFGS(ucf, logfile=system_name + '.txt') relaxer.attach(traj) relaxer.attach(saver) relaxer.run(fmax=0.025) bulk_mat.get_potential_energy() #Save the final state of the calculations calc.write(system_name + '_relaxer_final.gpw') save_atoms(bulk_mat, e_cut, nbands, k_pts, smear, initial_magmom, int(sys.argv[2]), 0, str(sys.argv[4]))
from ase.optimize import BFGS from ase.io import read, write from ase.calculators.emt import EMT from ase.ga.relax_attaches import VariansBreak import sys fname = sys.argv[1] print('Now relaxing {0}'.format(fname)) a = read(fname) a.calc = EMT() dyn = BFGS(a, trajectory=None, logfile=None) vb = VariansBreak(a, dyn) dyn.attach(vb.write) dyn.run(fmax=0.05) a.info['key_value_pairs']['raw_score'] = -a.get_potential_energy() write(fname[:-5] + '_done.traj', a) print('Done relaxing {0}'.format(fname))
from ase.optimize import BFGS from ase.io import read, write from ase.calculators.emt import EMT from ase.ga.relax_attaches import VariansBreak import sys fname = sys.argv[1] print("Now relaxing {0}".format(fname)) a = read(fname) a.set_calculator(EMT()) dyn = BFGS(a, trajectory=None, logfile=None) vb = VariansBreak(a, dyn) dyn.attach(vb.write) dyn.run(fmax=0.05) a.info["key_value_pairs"]["raw_score"] = -a.get_potential_energy() write(fname[:-5] + "_done.traj", a) print("Done relaxing {0}".format(fname))
calc = Vasp(xc='PBE',lreal='Auto',kpts=[1,1,1],ismear=1,sigma=0.2,algo='fast',istart=0,npar=8,encut=300) #calc = EMT() for i in range(0, numOfImages): #determines the number of nodes image = initial.copy() image.set_calculator(calc) image.set_constraint(constraint) images.append(image) images.append(final) neb = NEB(images, climb=True) neb.interpolate() dyn = BFGS(neb, logfile="logFile") for i in range(0, numOfImages): dyn.attach(PickleTrajectory('neb-%d.traj' % i, 'w', images[i])) dyn.run(fmax=0.014) #writes the coordinates for each image in NEB path in .xyz format string = 'structure' path = os.getcwd() path = path + '/neb-scratch' if not os.path.exists(path): os.makedirs(path) outFileName = 'NEB-trajectory.xyz' if os.path.exists(outFileName): os.remove(outFileName) for i in range(0, neb.nimages): string = 'structure%03d' % (i,) +'.xyz'
def flosic(mol, mf, fod1, fod2, sysname=None, datatype=np.float64, print_dm_one=False, print_dm_all=False, debug=False, calc_forces=False, nuclei=None, l_ij=None, ods=None, idx_1s=[0, 0], fixed_vsic=None, ham_sic='HOO'): # Get the atomic overlap and set the number of spins to two. s1e = mf.get_ovlp(mol) nspin = 2 # Get the KSO. ks = np.array(mf.mo_coeff) # Build the KSO density matrix. dm_ks = mf.make_rdm1() # Get the dimensions. nks_work = np.shape(ks) nks = nks_work[1] # Get the occupation of the KSO. occup = np.array(mf.mo_occ).copy() nksocc = nspin * [0] for j in range(nspin): for i in range(0, nks): if occup[j][i] != 0.0: nksocc[j] += 1 # assign nfod var (i would like to have ir) nfod = nspin * [0] for s in range(nspin): fod = fod1 if s == 1: fod = fod2 nfod[s] = fod.get_number_of_atoms() # check if the calling object still has the required data structures sa_mode = False try: pflo = mf.FLOSIC.pflo cesicc = mf.FLOSIC.cesicc except AttributeError: # we use flosic() without the FLOSIC class pflo = None cesicc = None sa_mode = True # check if we still have to create the # ESICC and FLO class objects, if so, do it and assign # them to the class variables if cesicc is None: cesicc = list() pflo = list() for s in range(nspin): fod = fod1 if s == 1: fod = fod2 c = po.ESICC(atoms=fod, mf=mf, spin=s) cesicc.append(c) pflo.append(c.FLO) if not sa_mode: mf.FLOSIC.cesicc = cesicc mf.FLOSIC.pflo = pflo #print(">> pflo fod:", mf.FLOSIC.pflo, pflo) # Get the Kohn-Sham orbitals at FOD positions. # psi_ai_spin has the dimension (Number of FODS x spin x Number of KS wf) # Obviously, we have to rearrange that, so that only the spin that is actually needed # for the descriptor is taken into account. # IMPORTANT! Units have to be in Bohr! ao1 = numint.eval_ao(mol, fod1.positions / units.Bohr) psi_ai_1 = ao1.dot(ks) ao2 = numint.eval_ao(mol, fod2.positions / units.Bohr) psi_ai_2 = ao2.dot(ks) # Some diagnostic output. if debug == True: print('FLOSIC input: DONE.') print( 'Parameters: \n{:d} FODs for spin 0 \n{:d} FODs for spin 1 \n{:d} KS wavefunctions in total \n{:d} occupied KS orbitals for spin1 \n{:d} occupied KS orbitals for spin2' .format(nfod[0], nfod[1], nks, nksocc[0], nksocc[1])) # Get psi_ai_work, which then gets passed to the rotation matrix building routine. psi_ai_work = np.zeros((nspin, np.max(nfod), np.max(nksocc)), dtype=datatype) # Iterate over the spin. for s in range(nspin): l = 0 # Iterate over the Kohn sham wf. for i in range(0, nks): if occup[s][i] != 0.0: # Iterate over the FODs. for k in range(0, nfod[s]): if s == 0: psi_ai_work[s, k, l] = psi_ai_1[k, s, i] if s == 1: psi_ai_work[s, k, l] = psi_ai_2[k, s, i] l = l + 1 if l > nksocc[s]: print( 'WARNING: Attempting to use not occupied KS wf for FLOSIC.' ) # fo will hold the FOs. sfo is needed in order to determine the overlap matrix. fo = np.zeros((nspin, nks, nks), dtype=datatype) sfo = np.zeros((nspin, nks, nks), dtype=datatype) # Now we need to orthonormalize the FOs, in order to get the FLOs. flo = np.zeros((nspin, nks, nks), dtype=datatype) for s in range(nspin): # note that the coefficients in the # FLO object are stored in Fortran order #print flo.shape, fo.shape, sfo.shape #print np.transpose(pflo[s].flo.copy()).shape flo[s, :, :] = np.transpose(pflo[s].flo.copy()) fo[s, :, 0:nksocc[s]] = np.transpose(pflo[s].fo.copy()) sfo[s, :, 0:nksocc[s]] = np.transpose(pflo[s].sfo.copy()) # For the unoccupied orbitals copy the FOs (and therefore the KSO). for i in range(nfod[s], nks): fo[s, :, i] = ks[s, :, i].copy() flo[s, :, i] = ks[s, :, i].copy() # store flo's in global object mf.flo_coeff = flo.copy() if debug == True: print('KS have been transformed into FO.') # check if we want to apply improved scf cycle if not sa_mode: if mf.FLOSIC.preopt: #print ">>>>> flo new <<<<<<" #pflo = list() if (mf.FLOSIC.neval_vsic >= mf.FLOSIC.preopt_start_cycle): print('--- FOD IN-SCF OPTIMIZATION ---') if mf.FLOSIC.on is None: print('IN-SCF OPTIMIZATION requires use of O(N)') sys.exit() for s in range(nspin): optfn = 'optout_{}.xyz'.format(s) # delete old optimize log file _fmin = mf.FLOSIC.preopt_fmin if mf.FLOSIC.neval_vsic == 0: _fmax = 0.0075 try: os.remove(optfn) except: # do nothing in case there is no such file pass else: _fmax = 0.0075 / (float(mf.FLOSIC.neval_vsic) * 0.75) if _fmax > 0.0075: _fmax = 0.0075 if _fmax < _fmin: _fmax = _fmin # unify access to fod-atoms objects #sys.exit() fod = fod1 if s == 1: fod = fod2 # check fod gradients if optimization of fods required _c = fod.get_calculator() _ff = _c.get_forces() frms = (_ff**2).sum(axis=1).max() print('--- optimizing FODs for spin {} frms {:6.4f} fmax {:6.4f} ---'\ .format(s,np.sqrt(frms),_fmax)) if frms >= _fmax**2: c1sidx = list() on = mf.FLOSIC.on # fix the C1s fod's for fodid in range(on.nfod[s]): _na = mol.atom_pure_symbol(on.fod_atm[s][fodid][0]) _ft = on.fod_atm[s][fodid][2] ftype = '{:>2}{:>03d}:{:>3}'\ .format(_na,on.fod_atm[s][fodid][0],_ft) _optim = 'yes' if (_ft == 'C1s') and mf.FLOSIC.preopt_fix1s: _optim = 'fix' c1sidx.append(fodid) print(" fod nr: {:>3d} type: {:>9} optimize: {}"\ .format(fodid, ftype, _optim),flush=True) # fix 1s core descriptors, they will not be optimized! # if you do not want that, initialize them sligthly off # the nucleus position if len(c1sidx) > 0: c1score = FixAtoms(indices=c1sidx) fod.set_constraint(c1score) def _writexyz(a=fod, s=s, optfn=optfn): '''service function to monitor the fod optimization''' # now write xyzfile write(optfn, a, append=True) _c = a.get_calculator() _esic = a.get_potential_energy() _tsic = _c.time_vsic _c.time_vsic = 0.0 _tforce = _c.time_desicdai _c.time_desicdai = 0.0 print(' -> esic: {:>14.6f} [eV] | (timing: {:5.1f} vsic, {:5.1f} desic [s])'\ .format(_esic, _tsic, _tforce), flush=True) # run the optimizer # the maxstep option may need to be adjusted if mf.FLOSIC.neval_vsic == mf.FLOSIC.preopt_start_cycle: # make a initial rough optimization #dyn = BFGS(atoms=fod, # logfile='OPT_FRMORB.log', # maxstep=mf.FLOSIC.opt_init_mxstep #) dyn = BFGS( atoms=fod, logfile='OPT_FRMORB.log', #downhill_check=True, maxstep=0.004) dyn.attach(_writexyz, interval=1) dyn.run(fmax=_fmax * 4, steps=99) # optimize more tighly #dyn = BFGS(atoms=fod, # logfile='OPT_FRMORB.log', # maxstep=mf.FLOSIC.opt_mxstep) # #memory=25) dyn = BFGS( atoms=fod, logfile='OPT_FRMORB.log', #downhill_check=True, maxstep=0.01) dyn.attach(_writexyz, interval=1) dyn.run(fmax=_fmax, steps=299) else: print('--- frms {:7.5f} below fmax -> not opt needed'. format(frms)) #sys.exit() # Now we want to calculate the SIC. Therefore, variables summing the SIC contribution # of the orbitals are initialized. exc_sic_flo = 0.0 ecoul_sic_flo = 0.0 nelec_sic_flo = 0.0 # Get the KS total energy. This is needed to calculate e_sic as difference between # e_tot(flosic) - e_tot(dft) etot_ks = mf.e_tot # The variables vsics and onedm save the contributions of the orbitals themselves. vsics = np.zeros((nspin, np.max(nfod), nks, nks), dtype=datatype) onedm = np.zeros((nspin, np.max(nfod), nks, nks), dtype=datatype) exc_orb = np.zeros((nspin, np.max(nfod)), dtype=np.float64) ecoul_orb = np.zeros((nspin, np.max(nfod)), dtype=np.float64) # Save for fixed vsic all_veff_work_flo_up = [] all_veff_work_flo_dn = [] all_veff_work_flo = [] all_exc_work_flo_up = [] all_exc_work_flo_dn = [] all_exc_work_flo = [] all_ecoul_work_flo_up = [] all_ecoul_work_flo_dn = [] all_ecoul_work_flo = [] if fixed_vsic is not None: all_veff_work_flo = fixed_vsic[0] all_exc_work_flo = fixed_vsic[1] all_ecoul_work_flo = fixed_vsic[2] # Bra and Ket are useful for doing scalar products using matrix multiplication. ket = np.zeros((nks, 1), dtype=datatype) bra = np.zeros((1, nks), dtype=datatype) # this is the main loop that goes over each Fermi-orbital for s in range(0, nspin): lfod = fod1 if s == 1: lfod = fod2 #print('>>> lfod pos:', np.sum(lfod.positions)) # Get the SIC for every orbital. # !!! It is a VERY bad idea to use one variable # for two things (this is MRP style) !!!! # fixed_vsic schould be True / False # and other information (float - data) have to be stored # in a seperate variable !! #print(">>>>> flosic: ", fixed_vsic) if fixed_vsic is None: # the fod positions of the base class may have changed, # if so, update the FLO objects positions as well pdiff = np.linalg.norm(lfod.positions - pflo[s].fod * units.Bohr) #print('>> pdiff', pdiff) if (pdiff > np.finfo(np.float64).eps): #print('>> pflo position update') pflo[s].fod[:, :] = lfod.positions[:, :] / units.Bohr # save the last vsic (if there is one) and mix a bit # (improoves convergence!) vsic_last = None try: if not np.isclose(np.sum(np.abs(pflo[s].vsic[j])), 0.0): vsic_last = pflo[s].vsic[j].copy() onedm_last = pflo[s].onedm[j].copy() except IndexError: pass #print('>> fod for update_vsic', np.sum(pflo[0].fod * units.Bohr), flush=True) #print(np.array_str(pflo[s].fod, precision=4, max_line_width=220)) pflo[s].update_vsic(uall=True) #print(">>> ESIC: {}".format(pflo[s]._esictot)) # now save the required data in the corresponding data structures for j in range(0, nfod[s]): #_esic_orb = -exc_work_flo - ecoul_work_flo exc_work_flo = pflo[s].energies[j, 2] ecoul_work_flo = pflo[s].energies[j, 1] _esic_orb = pflo[s].energies[j, 0] ecoul_orb[s, j] = pflo[s].energies[j, 1] exc_orb[s, j] = pflo[s].energies[j, 2] exc_sic_flo = exc_sic_flo + exc_work_flo ecoul_sic_flo = ecoul_sic_flo + ecoul_work_flo # Get the SIC potential and energy for FLO. onedm[s, j] = pflo[s].onedm[j] vsics[s, j] = pflo[s].vsic[j] # averrage sic potential to improve convergence if vsic_last is not None: #print('VSIC mixing') # _f = 0.20 _f = 0.0 vsics[s, j] = (1 - _f) * vsics[s, j] + _f * vsic_last onedm[s, j] = (1 - _f) * onedm[s, j] + _f * onedm_last # THa: Be aware that this veff_work_flo # does *NOT* habve a spin index ! veff_work_flo = pflo[s].vsic[j] if s == 0: all_veff_work_flo_up.append(veff_work_flo) if s == 1: all_veff_work_flo_dn.append(veff_work_flo) if ods == None: if fixed_vsic is not None: exc_work_flo = all_exc_work_flo[s][j] # Tha: im pretty sure the following code is bullshit ... ! if ods == True: rhoi = dft.numint.get_rho(mf._numint, mol, dm_work_flo[s], mf.grids) rhot = dft.numint.get_rho(mf._numint, mol, dm_ks, mf.grids) print('rhot', rhot.sum()) print('rhoi', rhoi.sum()) print('rho_i.sum()/rhot.sum()', rhoi.sum() / rhot.sum()) Xi = (rhoi.sum() / rhot.sum())**(0.04) exc_i = veff_work_flo.__dict__['exc'] print('Xi', Xi) exc_work_flo = Xi * exc_i if s == 0: all_ecoul_work_flo_up.append(ecoul_work_flo) if s == 1: all_ecoul_work_flo_dn.append(ecoul_work_flo) if fixed_vsic is not None: ecoul_work_flo = all_ecoul_work_flo[s][j] # Diagnostic output, if needed. This checks once again if electrons have been 'lost'. if debug == True: nelec_work_flo, dumm1, dumm2 = \ dft.numint.nr_vxc(mol, mf.grids, mf.xc, dm_work_flo, spin=1) nelec_sic_flo = nelec_sic_flo + nelec_work_flo # Save values for fixed_vsic all_veff_work_flo = [all_veff_work_flo_up, all_veff_work_flo_dn] all_exc_work_flo = [all_exc_work_flo_up, all_exc_work_flo_dn] all_ecoul_work_flo = [all_ecoul_work_flo_up, all_ecoul_work_flo_dn] # Print the density matrix if wished. if print_dm_all == True: dm_flo = dynamic_rdm(flo, occup) print('Complete-FOD-Density-Matrix') print(dm_flo) # Now that we got all the contributions, build the SIC energy. # changed by SS # esic_flo = ecoul_sic_flo + exc_sic_flo # print("Total ESIC = {:9.6f}".format(esic_flo)) # etot_sic_flo = etot_ks - esic_flo esic_flo = -1 * (ecoul_sic_flo + exc_sic_flo) print("ESIC = {:9.6f}".format(esic_flo)) etot_sic_flo = etot_ks + esic_flo # Next step is the energy eigenvalue correction / SIC Hamiltonian. # First, initialize all variables. h_sic = np.zeros((nspin, nks, nks), dtype=datatype) h_sic_virtual = np.zeros((nspin, nks, nks), dtype=datatype) h_ks = np.zeros((nspin, nks, nks), dtype=datatype) v_virtual = np.zeros((nspin, nks, nks), dtype=datatype) sumpfs = np.zeros((nks, nks), dtype=datatype) lambda_ij = np.zeros((nspin, np.max(nfod), np.max(nfod)), dtype=datatype) # We also need the DFT hamiltonian. dm_ks = mf.make_rdm1() h1e = mf.get_hcore(mol) vhf = mf.get_veff(mol, dm_ks) hamil = mf.get_fock(h1e, s1e, vhf, dm_ks) # v_virtual is the projector of the virtual subspace, that might be needed # depending on which unified hamiltonian approximation is used. for s in range(0, nspin): if nfod[s] != 0: for i in range(nfod[s], nks): bra[0, :] = np.transpose(flo[s, :, i]) ket[:, 0] = (flo[s, :, i]) v_virtual[s] = v_virtual[s] + np.dot(ket, bra) # Get the KS eigenvalues for comparison. eval_ks, trash = mf.eig(hamil, s1e) # Calculate the Cholesky decomposition of the atomic overlap and apply it to the # FLO. With this, things like the overlap matrix can be calculated more easily. sflo = np.zeros((nspin, nks, nks), dtype=datatype) sroot = np.linalg.cholesky(s1e) for s in range(nspin): sflo[s] = np.dot(np.transpose(sroot), flo[s, :, :]) # Get epsilon^k_kl, here named lambda to avoid confusion. (This is needed for the # forces.) for s in range(nspin): for j in range(nfod[s]): for i in range(nfod[s]): bra[0, :] = np.transpose(flo[s, :, i]) ket[:, 0] = (flo[s, :, j]) right = np.dot(vsics[s, j], ket) lambda_ij[s, i, j] = -np.dot(bra, right) # Test lampda_ij as well input for the AF correction cst = np.zeros((nspin, np.max(nfod), np.max(nfod)), dtype=datatype) if l_ij == True: kappa_ij = np.zeros((nspin, np.max(nfod), np.max(nfod)), dtype=datatype) for s in range(nspin): for j in range(nfod[s]): for i in range(nfod[s]): bra[0, :] = np.transpose(flo[s, :, i]) #print '<bra,bra>' #print np.dot(bra,sflo[s,:,i]) ket[:, 0] = (flo[s, :, j]) #print '<ket|ket>' #print np.dot(np.transpose(ket),ket) delta = vsics[s, i] - vsics[s, j] #delta = np.dot(np.transpose(sroot),vsics[s,i]-vsics[s,j]) right = np.dot(delta, ket) right1 = np.dot(vsics[s, i], ket) #right1 = np.dot(np.transpose(sroot),right1) right2 = np.dot(vsics[s, j], (flo[s, :, i])) #right2 = np.dot(np.transpose(sroot),right2) kappa_ij[s, i, j] = 1 * (np.dot(bra, right)) #lambda_ij[s,i,j] = np.dot(bra,right1) - np.dot(np.transpose(flo[s,:,j]),right2) # test cst[s, i, j] = np.dot(bra, ket) for s in range(nspin): for i in range(nfod[s]): for j in range(nfod[s]): bra[0, :] = np.transpose(flo[s, :, i]) #print '<bra,bra>' #print np.dot(bra,sflo[s,:,i]) ket[:, 0] = (flo[s, :, j]) #print '<ket|ket>' #print np.dot(np.transpose(ket),ket) delta = vsics[s, i] - vsics[s, j] #delta = np.dot(np.transpose(sroot),vsics[s,i]-vsics[s,j]) right = np.dot(delta, ket) right1 = np.dot(vsics[s, i], ket) #right1 = np.dot(np.transpose(sroot),right1) right2 = np.dot(vsics[s, j], (flo[s, :, i])) #right2 = np.dot(np.transpose(sroot),right2) kappa_ij[s, i, j] = lambda_ij[s, i, j] - 1 * (np.dot(bra, right)) #lambda_ij[s,i,j] = np.dot(bra,right1) - np.dot(np.transpose(flo[s,:,j]),right2) # test cst[s, i, j] = np.dot(bra, ket) if l_ij == True: for s in range(nspin): # printing the lampda_ij matrix for both spin channels print('kappa_ij spin%0.1f' % s) print(kappa_ij[s, :, :]) #print 'RMS lambda_ij' #M = lambda_ij[s,:,:] #print (M-M.T)[np.triu_indices((M-M.T).shape[0])].sum() print('RMS lambda_ij') print(force_max_lij(kappa_ij)) # DEV # (SS) Debuging atomic force correction # AF = Force1 + Force2 # AF = -2 \sum_{i=1}^{N}\sum_{s,t}^{N_bas} c_s^{i}c_t^{i} < df_s/dR_nu| H_SIC | f_t> + # +2 \sum_{i,j}^{M}\lampda_{ij}\sum_{s,t}^{N_bas} c_s^{i}c_t^{j} < df_s/dR_nu| f_t> # we assuming that we have Force one while updating the hamiltonian in SCF modus # therefore we only try to implement the Force2 term if debug == True: gradpsi_nuclei = np.zeros((nspin, np.max(nfod), len(nuclei), 3), dtype=datatype) #gradpsi_nuclei = np.zeros((nspin,np.max(nfod),np.max(nksocc),3), dtype=datatype) for s in range(nspin): # printing the lampda_ij matrix for both spin channels print('lambda_ij') print(lambda_ij[s, :, :]) #nuc = nuclei.positions/units.Bohr #for nu in range(len(nuc)): # get the gradient of the basis functions at the nuclei positions # all positions at some time # the next lines are similiar to the FOD generation while changing fod1 to nuclei print('Nuclei positions [Bohr]') print(nuclei.positions / units.Bohr) nuclei1 = mol.eval_gto('GTOval_ip_sph', nuclei.positions / units.Bohr, comp=3) gradpsi_nuclei1 = [x.dot(flo) for x in nuclei1] nuclei2 = mol.eval_gto('GTOval_ip_sph', nuclei.positions / units.Bohr, comp=3) gradpsi_nuclei2 = [x.dot(flo) for x in nuclei2] print('Grad nuclei1') print(np.shape(gradpsi_nuclei1)) # Rearrange the data to make it more usable. x_1 = gradpsi_nuclei1[0] y_1 = gradpsi_nuclei1[1] z_1 = gradpsi_nuclei1[2] x_2 = gradpsi_nuclei2[0] y_2 = gradpsi_nuclei2[1] z_2 = gradpsi_nuclei2[2] # Iterate over the spin. for j in range(0, nspin): l = 0 # Iterate over the Kohn sham wf. for i in range(0, nfod[j]): if occup[j][i] != 0.0: # Iterate over the fods. for k in range(0, nfod[j]): if j == 0: gradpsi_nuclei[j, k, l, 0] = x_1[k][j][i] gradpsi_nuclei[j, k, l, 1] = y_1[k][j][i] gradpsi_nuclei[j, k, l, 2] = z_1[k][j][i] if j == 1: gradpsi_nuclei[j, k, l, 0] = x_2[k][j][i] gradpsi_nuclei[j, k, l, 1] = y_2[k][j][i] gradpsi_nuclei[j, k, l, 2] = z_2[k][j][i] l = l + 1 # Variables neeed later sroot = np.zeros((np.max(nfod), np.max(nfod)), dtype=datatype) sroot = np.linalg.cholesky(s1e) sks = np.zeros((nspin, nks, nks), dtype=datatype) # Components of the AF correction AFx = np.zeros((nspin, len(nuclei)), dtype=datatype) AFy = np.zeros((nspin, len(nuclei)), dtype=datatype) AFz = np.zeros((nspin, len(nuclei)), dtype=datatype) for s in range(nspin): # This is for debugging reasons we need a different sign for the force if int(s) == int(0): print('SPIN UP') pre = 1. if int(s) != int(0): print('SPIN DOWN') pre = -1. # Fill sks sks[s, :, :] = np.dot(np.transpose(sroot), ks[s, :, :]) # Get AF force correction . for i in range(0, nfod[s]): sumx = np.zeros((nfod[s]), dtype=datatype) sumy = np.zeros((nfod[s]), dtype=datatype) sumz = np.zeros((nfod[s]), dtype=datatype) for a in range(0, nfod[s]): # we need a correction for each cartesian coordinate (x,y,z) # gradient of the basis function x basisfunction summed over grid #sumx = (gradpsi_nuclei[s,:,a,0]*sks[s,:,a]).sum() + sumx #sumy = (gradpsi_nuclei[s,:,a,1]*sks[s,:,a]).sum() + sumy #sumz = (gradpsi_nuclei[s,:,a,2]*sks[s,:,a]).sum() + sumz sumx = (gradpsi_nuclei[s, :, a, 0] * flo[s, :, i]).sum() + sumx sumy = (gradpsi_nuclei[s, :, a, 1] * flo[s, :, i]).sum() + sumy sumz = (gradpsi_nuclei[s, :, a, 2] * flo[s, :, i]).sum() + sumz flo[s, :, i] # the prefactor of the lampda matrix af1 = 2. * lambda_ij[s, :, :].sum() # the prefactor of the coeffcients af2 = cst[s, :, :].sum() afx = af1 * af2 * sumx afy = af1 * af2 * sumy afz = af1 * af2 * sumz # For now we using only on spin channel # I introduced a spin scanling factor of sqrt(2) ss = 1. #2.*np.sqrt(2.) AFx[s, i] = ss * pre * afx.sum() AFy[s, i] = ss * pre * afy.sum() AFz[s, i] = ss * pre * afz.sum() print('Atomic force correction') AF = [] print('AF_dx') print(AFx) print('AF_dy') print(AFy) print('AF_dz') print(AFz) for i in range(0, len(nuclei)): if i == 0: AF.append([ AFx[0, 0] - AFx[1, 0], AFy[0, 0] - AFy[1, 0], AFz[0, 0] - AFz[1, 0] ]) print('%i %0.5f %0.5f %0.5f' % (i, AFx[0, 0] - AFx[1, 0], AFy[0, 0] - AFy[1, 0], AFz[0, 0] - AFz[1, 0])) if i == 1: AF.append([ abs(AFx[0, 0]) + abs(AFx[1, 0]), abs(AFy[0, 0]) + abs(AFy[1, 0]), abs(AFz[0, 0]) + abs(AFz[1, 0]) ]) print('%i %0.5f %0.5f %0.5f' % (i, abs(AFx[0, 0]) + abs(AFx[1, 0]), abs(AFy[0, 0]) + abs(AFy[1, 0]), abs(AFz[0, 0]) + abs(AFz[1, 0]))) # the AF variable will be returned to other functions # if debug= True option is chosen print(AF) # Do the energy eigenvalue correction and the SIC Hamiltonian. for s in range(nspin): sumpfs[:, :] = 0.0 if nfod[s] != 0: for i in range(0, nfod[s]): # Assuming that virtual coefficients are zero. ps = np.dot(onedm[s, i], s1e) pf = np.dot(onedm[s, i], vsics[s, i]) fps = np.dot(vsics[s, i], ps) spf = np.dot(s1e, pf) h_sic[s] = h_sic[s] + fps + spf # Assuming they are not. # NOTE: They almost always are in our formalism. I'm not deleting this # code because it might come in handy at some other point, but it is more # or less not needed. pfp = np.dot(pf, onedm[s, i]) fp = np.dot(vsics[s, i], onedm[s, i]) vfp = np.dot(v_virtual[s], fp) pfv = np.dot(pf, v_virtual[s]) sumpf = pfp + vfp + pfv sumpfs = np.dot(sumpf, s1e) + sumpfs # Get the SIC Hamiltonian. h_sic[s] = -0.5 * h_sic[s] h_sic_virtual[s] = -np.dot(s1e, sumpfs) h_ks[s] = eval_ks[s] * np.eye(nks, nks) # Get the SIC eigenvalues. eval_flo, trash = mf.eig(hamil + h_sic, s1e) # Again, the next line is only for cases where the virtual coefficient are not zero, which they should be here. eval_flo_2, trash = mf.eig(hamil + h_sic_virtual, s1e) if ham_sic == 'HOOOV': eval_flo = eval_flo_2 for s in range(nspin): # Output the H**O energy eigenvalue if needed. # Get the H**O for DFT and FLO-SIC. Note: there might be two spin channels but # only one H**O. Therefore we have to make sure the correct one is outputted. if nfod[s] != 0: if s == 0: HOMO_ks = 1. * eval_ks[s][nfod[s] - 1] HOMO_flo = 1 * eval_flo[s][nfod[s] - 1] if s == 1 and HOMO_ks < 1. * eval_ks[s][nfod[s] - 1]: HOMO_ks = 1. * eval_ks[s][nfod[s] - 1] HOMO_flo = 1 * eval_flo[s][nfod[s] - 1] # Print the H**O values if wished. if debug == True: print('DFT, FLO-SIC H**O value in Hartree', HOMO_ks, HOMO_flo) print('DFT, FLO-SIC H**O value in eV', HOMO_ks * units.Hartree, HOMO_flo * units.Hartree) # Next step is to calculate the forces. This is done by the following routine. fforce_output = np.zeros((nfod[0] + nfod[1], 3), dtype=datatype) if calc_forces == True: fforce_output = get_fermi_forces(nspin, pflo) # Output the results on the screen if wished. Output is also given in form of the # output dictionary. if debug == True: print('\n') print('-----Number-Of-----') print('Electrons in both spin channels: %0.5f %0.5f' % (nelec_sic_flo[0], nelec_sic_flo[1])) print('Number of FODs in both spin channels: %0.5f %0.5f' % (nfod[0], nfod[1])) print('The numbers in the two lines above should be identical.') print('If they are not, something went terribly wrong.') print('\n') print('-----Total Energy-----') print('Total Energy (DFT, FLO-SIC): %0.5f %0.5f' % (etot_ks, etot_sic_flo)) # Fill the output dictionary. if ham_sic == 'HOO': h_sic_ks_base = h_sic #h_sic_virtual #h_sic if ham_sic == 'HOOOV': h_sic_ks_base = h_sic_virtual return_dict = {} # The DFT total energy. return_dict['etot_dft'] = etot_ks # The FLO-SIC total energy. return_dict['etot_sic'] = etot_sic_flo # The DFT H**O value. return_dict['homo_dft'] = HOMO_ks # The FLO-SIC H**O value. return_dict['homo_sic'] = HOMO_flo # The SIC Hamiltonian. return_dict['hamil'] = h_sic_ks_base # The FOD forces. return_dict['fforces'] = fforce_output # The FLOs. return_dict['flo'] = flo # The dipole momemt. return_dict['dipole'] = mf.dip_moment(verbose=0) # The FLO-SIC evalues. return_dict['evalues'] = eval_flo # The lambda_ij return_dict['lambda_ij'] = lambda_ij # The VSICs if fixed_vsic is not None: return_dict['fixed_vsic'] = [ all_veff_work_flo, all_exc_work_flo, all_ecoul_work_flo ] else: return_dict['fixed_vsic'] = None if debug == True: # Test AF return_dict['AF'] = AF # Done with FLO-SIC! return return_dict
def main( argv ): runID = int( argv[0] ) params = { "cutoff":200, "kpts":1, "n_atoms_to_shift":0, "nbands":-1, "relax":False, "gamma":False } db_name = "none" dbPaths = [ "/home/ntnu/davidkl/GPAWTutorial/Exercises/AlOutOfPositionEnergy/aloutofpos.db", "aloutofpos.db" ] # Find the correct database for name in dbPaths: if ( os.path.isfile(name) ): db_name = name break if ( db_name == "none" ): print ("Could not find database") return # Read parameters from database con = sq.connect( db_name ) cur = con.cursor() cur.execute( "SELECT cutoff,kpts,n_atoms_to_shift,nbands,relax,gamma FROM simpar WHERE ID=?", (runID,) ) dbparams = cur.fetchall()[0] con.close() # Transfer the parameters to the params dictionary params["cutoff"] = dbparams[0] params["kpts"] = dbparams[1] params["n_atoms_to_shift"] = dbparams[2] params["nbands"] = dbparams[3] params["relax"] = dbparams[4] params["gamma"] = dbparams[5] if ( params["gamma"] ): kpts = {"size":(params["kpts"],params["kpts"],params["kpts"]), "gamma":True} else: kpts = (params["kpts"],params["kpts"],params["kpts"]) # Initialize the calculator calc = gp.GPAW( mode=gp.PW(params["cutoff"]), xc="PBE", nbands=params["nbands"], kpts=kpts ) # Initialize the atoms aluminum = build.bulk( "Al", crystalstructure="fcc" ) P = build.find_optimal_cell_shape_pure_python( aluminum.cell, 32, "sc" ) aluminum = build.make_supercell( aluminum, P ) aluminum = moveAtoms( aluminum, params["n_atoms_to_shift"], alat=4.05 ) aluminum.set_calculator( calc ) if ( params["relax"] ): logfile = "logilfe%d.log"%(runID) trajfile = "optTrajectory%d.traj"%(runID) traj = Trajectory( trajfile, 'w', aluminum ) # Optimize internal positions relaxer = BFGS( aluminum, logfile=logfile ) relaxer.attach( traj ) relaxer.run( fmax=0.05 ) # Optimize cell strain = StrainFilter( aluminum ) relaxer = BFGS( strain, logfile=logfile ) relaxer.attach( traj ) relaxer.run( fmax=0.05 ) energy = aluminum.get_potential_energy() # Add results to the database asedb = ase.db.connect( db_name ) lastID = asedb.write( aluminum, relaxed=True ) # Update the parameters in the database con = sq.connect( db_name ) cur = con.cursor() cur.execute( "UPDATE simpar SET status=?,systemID=? WHERE ID=?", ("finished",lastID,runID) ) con.commit() con.close()
from ase import Atoms from ase.calculators.emt import EMT from ase.constraints import FixBondLength from ase.io import Trajectory from ase.optimize import BFGS a = 3.6 b = a / 2 cu = Atoms('Cu2Ag', positions=[(0, 0, 0), (b, b, 0), (a, a, b)], calculator=EMT()) e0 = cu.get_potential_energy() print(e0) d0 = cu.get_distance(0, 1) cu.set_constraint(FixBondLength(0, 1)) t = Trajectory('cu2ag.traj', 'w', cu) qn = BFGS(cu) qn.attach(t.write) def f(): print(cu.get_distance(0,1)) qn.attach(f) qn.run(fmax=0.01) assert abs(cu.get_distance(0, 1) - d0) < 1e-14
def main(argv): print("Dry-run", gp.dry_run) if (len(argv) > 2): print("Usage: python almg.py paramID") return possible_dbs = { "vilje": "/home/ntnu/davidkl/GPAWTutorial/Exercises/AlMg/AlMg.db", "laptop": "AlMg.db" } # Find which database to use db_name = None for key in possible_dbs: if (os.path.isfile(possible_dbs[key])): db_name = possible_dbs[key] break if (db_name is None): raise RuntimeError("Could not find database") #db_name = "/home/ntnu/davidkl/GPAWTutorial/Exercises/AlMg/AlMg.db" db = ase.db.connect(db_name) runID = int(argv[0]) # Read parameters from the database con = sq.connect(db_name) cur = con.cursor() cur.execute( "SELECT hspacing,relax,atomID,kpts,nbands,latticeConst,cutoff,traj,fmax,tags FROM runs WHERE ID=?", (runID, )) params = cur.fetchall()[0] con.close() save_pov = False run_sim = True swap_atoms = False useOnlyUnitCellFilter = True repeatFCCStructure = True # If False, ASE find_optimal_cell_shape will be used to create the unit cell h_spacing = params[0] relax = params[1] atom_row_id = params[2] Nkpts = params[3] nbands = params[4] cutoff = params[6] old_traj = params[7] fmax = params[8] tags = params[9] # Lattice parameter a = float(params[5]) if (old_traj != "none"): # Read the atoms from the trajectory file print("Reading atoms from trajectory file") traj = Trajectory(old_traj) atoms = traj[-1] elif (atom_row_id < 0): print( "Building supercell using find_optimal_cell_shape_pure_python from ASE" ) # Target primitive cell atoms = build.bulk("Al", crystalstructure="fcc", a=a) # Create a supercell consisting of 32 atoms if (not "test" in tags): # Skip this if the run is a test run. For some reason the target_shape="fcc" does not work # using sc instead if (repeatFCCStructure): atoms = atoms * (4, 4, 2) else: P = build.find_optimal_cell_shape_pure_python( atoms.cell, 32, "sc") atoms = build.make_supercell(atoms, P) # Replace some atoms with Mg atoms n_mg_atoms = int(0.2 * len(atoms)) for i in range(n_mg_atoms): atoms[i].set("symbol", "Mg") else: print("Reading atoms object from the database") # Read atoms from database atoms = db.get_atoms(selection=atom_row_id) if (swap_atoms): from ase.io import write for i in range(0, 2 * len(atoms)): first = np.random.randint(0, len(atoms)) second = np.random.randint(0, len(atoms)) firstSymbol = atoms[first].symbol atoms[first].symbol = atoms[second].symbol atoms[second].symbol = firstSymbol atoms.write("almg_swap.xyz") if (save_pov): from ase.io import write write("Al.pov", atoms * (3, 3, 1), rotation="-10z,-70x") return if (run_sim): kpts = {"size": (Nkpts, Nkpts, Nkpts), "gamma": True} # Monkhorst pack kpts = (Nkpts, Nkpts, Nkpts) if (cutoff > 0): mode = PW(cutoff) else: mode = "fd" #calc = GPAW( mode="fd", h=h_spacing, xc="PBE", nbands=nbands, kpts=kpts, basis="dzp", poissonsolver=PoissonSolver(relax="GS", eps=1E-7) ) densityConv = 1E-2 # Default 1E-4 wfsConv = 5E-3 cnvg = {"density": 1E-2, "eigenstates": 5E-3} calc = GPAW(mode=mode, xc="PBE", nbands=nbands, kpts=kpts) calc.set(convergence=cnvg) atoms.set_calculator(calc) logfile = "none" trajfile = "none" if (relax): from ase.optimize import QuasiNewton, BFGS #from ase.optimize.precon import PreconLBFGS uid = rnd.randint(0, 10000000) # First relax only the unit cell logfile = "relaxation_%d.log" % (uid) trajfile = "trajectory_%d.traj" % (uid) print("Logfile: %s, Trajectory file: %s" % (logfile, trajfile)) traj = Trajectory(trajfile, 'w', atoms) if (not useOnlyUnitCellFilter): for num_kpts in [Nkpts]: kpts = (num_kpts, num_kpts, num_kpts) calc.set(kpts=kpts) energy = atoms.get_potential_energy() # Relax unit cell strfilter = StrainFilter(atoms) relaxer = BFGS(strfilter, logfile=logfile) relaxer.attach(traj) convergence = np.abs(0.01 * energy) relaxer.run( fmax=convergence ) # NOTE: Uses generalized forces = volume*stress # Relax atoms within the unit cell relaxer = BFGS(atoms, logfile=logfile) relaxer.attach(traj) relaxer.run(fmax=fmax) else: # Optimize both simultaneously uf = UnitCellFilter(atoms) relaxer = PreconLBFGS(uf, logfile=logfile) relaxer.attach(traj) relaxer.run(fmax=fmax) energy = atoms.get_potential_energy() print("Energy %.2f eV/atom" % (energy)) lastID = db.write(atoms, relaxed=True) # Update the database con = sq.connect(db_name) cur = con.cursor() cur.execute( "UPDATE runs SET status='finished',resultID=?,logfile=?,traj=? WHERE ID=?", (lastID, logfile, trajfile, runID)) con.commit() con.close()
if i == j: image.set_calculator(calc) image.set_constraint(constraint) images.append(image) images.append(final) neb = NEB(images, climb=True, parallel=True) neb.interpolate() dyn = BFGS(neb, logfile="logFile") #if rank % (size // ) == 0: # traj = PickleTrajectory('neb%d.traj' % j, 'w', images[j], master=True) # qn.attach(traj) for i in range(0, numOfImages): dyn.attach(PickleTrajectory('neb-%d.traj' % i, 'w', images[i]), master=True) dyn.run(fmax=0.014) #writes the coordinates for each image in NEB path in .xyz format string = 'structure' path = os.getcwd() path = path + '/neb-scratch' if not os.path.exists(path): os.makedirs(path) outFileName = 'NEB-trajectory.xyz' if os.path.exists(outFileName): os.remove(outFileName) for i in range(0, neb.nimages): string = 'structure%03d' % (i,) +'.xyz'
class IRMD(object): ''' Intelligent Reactive Molecular Dynamics ''' def __init__(self, atoms=None, gen='poscar.gen', index=-1, totstep=100, intT=300, Tmax=10000, time_step=0.1, ro=None, rtole=0.5, Iter=0, massages=1): self.Epot = [] self.epot = 0.0 self.ekin = 0.0 self.T = 0.0 self.intT = intT self.Tmax = Tmax self.totstep = totstep self.ro = ro self.rtole = rtole self.Iter = Iter self.atoms = atoms self.time_step = time_step if self.atoms is None: self.atoms = read(gen, index=index) self.atoms.calc = IRFF(atoms=self.atoms, libfile='ffield.json', rcut=None, nn=True, massages=massages) self.natom = len(self.atoms) self.dyn = None def run(self): MaxwellBoltzmannDistribution(self.atoms, self.intT * units.kB) self.dyn = VelocityVerlet(self.atoms, self.time_step * units.fs, trajectory='md.traj') def printenergy(a=self.atoms): epot_ = a.get_potential_energy() r = a.calc.r.numpy() i_ = np.where(np.logical_and(r < self.rtole * self.ro, r > 0.0001)) n = len(i_[0]) self.Epot.append(epot_) self.epot = epot_ / self.natom self.ekin = a.get_kinetic_energy() / self.natom self.T = self.ekin / (1.5 * units.kB) self.step = self.dyn.nsteps print('Step %d Epot = %.3feV Ekin = %.3feV (T=%3.0fK) ' 'Etot = %.3feV' % (self.step, self.epot, self.ekin, self.T, self.epot + self.ekin)) try: assert n == 0 and self.T < self.Tmax, 'Atoms too closed!' except: for _ in i_: print('atoms pair', _) print('Atoms too closed or temperature too high, stop at %d.' % self.step) self.dyn.max_steps = self.dyn.nsteps - 1 # traj = Trajectory('md.traj', 'w', self.atoms) self.dyn.attach(printenergy, interval=1) # self.dyn.attach(traj.write,interval=1) self.dyn.run(self.totstep) def opt(self): self.dyn = BFGS(self.atoms, trajectory='md.traj') def check(a=self.atoms): epot_ = a.get_potential_energy() r = a.calc.r.numpy() i_ = np.where(np.logical_and(r < self.rtole * self.ro, r > 0.0001)) n = len(i_[0]) self.Epot.append(epot_) self.epot = epot_ / self.natom self.step = self.dyn.nsteps try: assert n == 0 and (not np.isnan(epot_)), 'Atoms too closed!' except: for _ in i_: print('atoms pair', _) print('Atoms too closed or temperature too high, stop at %d.' % self.step) self.dyn.max_steps = self.dyn.nsteps - 1 # raise ValueError('- Energy is NaN!' ) self.dyn.attach(check, interval=1) self.dyn.run(0.00001, self.totstep) def logout(self): with open('md.log', 'w') as fmd: fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n- Energies From Machine Learning MD Iteration %4d -\n' % self.Iter) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write('- Ebond=%f ' % self.atoms.calc.Ebond) fmd.write('- Elone=%f ' % self.atoms.calc.Elone) fmd.write('- Eover=%f ' % self.atoms.calc.Eover) fmd.write('- Eunder=%f \n' % self.atoms.calc.Eunder) fmd.write('- Eang=%f ' % self.atoms.calc.Eang) fmd.write('- Epen=%f ' % self.atoms.calc.Epen) fmd.write('- Etcon=%f \n' % self.atoms.calc.Etcon) fmd.write('- Etor=%f ' % self.atoms.calc.Etor) fmd.write('- Efcon=%f ' % self.atoms.calc.Efcon) fmd.write('- Evdw=%f ' % self.atoms.calc.Evdw) fmd.write('- Ecoul=%f \n' % self.atoms.calc.Ecoul) fmd.write('- Ehb=%f ' % self.atoms.calc.Ehb) fmd.write('- Eself=%f ' % self.atoms.calc.Eself) fmd.write('- Ezpe=%f \n' % self.atoms.calc.zpe) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n- Atomic Information (Delta and Bond order) -\n' ) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n AtomID Sym Delta NLP DLPC Bond-Order \n') for i in range(self.natom): fmd.write( '%6d %2s %9.6f %9.6f %9.6f' % (i, self.atoms.calc.atom_name[i], self.atoms.calc.Delta[i], self.atoms.calc.nlp[i], self.atoms.calc.Delta_lpcorr[i])) for j in range(self.natom): if self.atoms.calc.bo0[i][j] > self.atoms.calc.botol: fmd.write(' %3d %2s %9.6f' % (j, self.atoms.calc.atom_name[j], self.atoms.calc.bo0[i][j])) fmd.write(' \n') fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n- Atomic Energies & Forces -\n' ) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n AtomID Sym Delta_lp Elone Eover Eunder Fx Fy Fz\n' ) for i in range(self.natom): fmd.write( '%6d %2s %9.6f %9.6f %9.6f %9.6f ' % (i, self.atoms.calc.atom_name[i], self.atoms.calc.Delta_lp[i], self.atoms.calc.elone[i], self.atoms.calc.eover[i], self.atoms.calc.eunder[i])) for f in self.atoms.calc.results['forces'][i]: fmd.write(' %9.6f ' % f) fmd.write(' \n') fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write('\n- Machine Learning MD Completed!\n') def close(self): self.logout() self.dyn = None self.atoms = None
from ase.io import read from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.neb import NEB from ase.optimize import BFGS from ase.io.trajectory import PickleTrajectory from ase.parallel import rank, size initial = read('initial.traj') final = read('final.traj') constraint = FixAtoms(mask=[atom.tag > 1 for atom in initial]) images = [initial] j = rank * 3 // size # my image number for i in range(3): image = initial.copy() if i == j: image.set_calculator(EMT()) image.set_constraint(constraint) images.append(image) images.append(final) neb = NEB(images, parallel=True) neb.interpolate() qn = BFGS(neb) if rank % (size // 3) == 0: traj = PickleTrajectory('neb%d.traj' % j, 'w', images[1 + j], master=True) qn.attach(traj) qn.run(fmax=0.05)
class IRMD(object): ''' Intelligent Reactive Molecular Dynamics ''' def __init__(self, label=None, atoms=None, gen='poscar.gen', ffield='ffield.json', index=-1, totstep=100, vdwnn=False, nn=True, initT=300, Tmax=10000, time_step=0.1, Iter=0, ro=None, rmin=0.6, rmax=1.3, angmax=20.0, CheckZmat=False, zmat_id=None, zmat_index=None, InitZmat=None, learnpair=None, groupi=[], groupj=[], beta=None, freeatoms=None, dEstop=1000, dEtole=1.0, print_interval=1): self.Epot = [] self.epot = 0.0 self.ekin = 0.0 self.T = 0.0 self.initT = initT self.Tmax = Tmax self.totstep = totstep self.ro = ro self.rmin = rmin self.Iter = Iter self.atoms = atoms self.time_step = time_step self.step = 0 self.rmax = rmax self.angmax = angmax self.CheckZmat = CheckZmat self.zmat_id = zmat_id self.zmat_index = zmat_index self.InitZmat = InitZmat self.zmats = [] self.dEstop = dEstop self.dEtole = dEtole self.learnpair = learnpair self.groupi = groupi self.groupj = groupj self.beta = beta self.freeatoms = freeatoms self.print_interval = print_interval if self.atoms is None: self.atoms = read(gen, index=index) self.atoms.calc = IRFF(atoms=self.atoms, mol=label, libfile=ffield, rcut=None, nn=nn, vdwnn=vdwnn) self.natom = len(self.atoms) self.re = self.atoms.calc.re self.dyn = None self.atoms.calc.calculate(atoms=self.atoms) self.InitBonds = getBonds(self.natom, self.atoms.calc.r, self.rmax * self.re) if (self.atoms is None) and gen.endswith('.gen'): MaxwellBoltzmannDistribution(self.atoms, self.initT * units.kB) else: temp = self.atoms.get_temperature() if temp > 0.0000001: scale = np.sqrt(self.initT / temp) p = self.atoms.get_momenta() p = scale * p self.atoms.set_momenta(p) else: MaxwellBoltzmannDistribution(self.atoms, self.initT * units.kB) def run(self): self.zv, self.zvlo, self.zvhi = None, 0.0, 0.0 self.dyn = VelocityVerlet(self.atoms, self.time_step * units.fs, trajectory='md.traj') if (not self.learnpair is None) and (not self.beta is None): vij = self.atoms.positions[ self.learnpair[1]] - self.atoms.positions[self.learnpair[0]] rij = np.sqrt(np.sum(np.square(vij))) vij = vij / rij self.dEstop_ = 0.0 def printenergy(a=self.atoms): n = 0 self.Deformed = 0.0 epot_ = a.get_potential_energy() v = self.atoms.get_velocities() if not self.beta is None: if not self.learnpair is None: # v = np.sqrt(np.sum(np.square(v),axis=1)) di = np.dot(v[self.learnpair[0]], vij) dj = np.dot(v[self.learnpair[1]], vij) for iv, v_ in enumerate(v): d = np.dot(v_, vij) d_ = d if iv in self.groupi: if abs(d) > abs(di): if abs(d * self.beta) > abs(di): d_ = d * self.beta else: d_ = di elif iv in self.groupj: if abs(d) > abs(dj): if abs(d * self.beta) > abs(dj): d_ = d * self.beta else: d_ = dj vd = d * vij vd_ = d_ * vij v[iv] = vd_ + self.beta * (v[iv] - vd) elif not self.freeatoms is None: for iv, v_ in enumerate(v): if iv not in self.freeatoms: v[iv] = v_ * self.beta # else: # v = v*self.beta self.atoms.set_velocities(v) if self.CheckZmat: self.Deformed, zmat, self.zv, self.zvlo, self.zvhi = check_zmat( atoms=a, rmin=self.rmin, rmax=self.rmax, angmax=self.angmax, zmat_id=self.zmat_id, zmat_index=self.zmat_index, InitZmat=self.InitZmat) if not self.zv is None: if self.zv[1] == 0: df_i = self.zmat_id[self.zv[0]] df_j = self.zmat_index[self.zv[0]][0] v[df_i][0] = 0.0 v[df_i][1] = 0.0 v[df_i][2] = 0.0 v[df_j][0] = 0.0 v[df_j][1] = 0.0 v[df_j][2] = 0.0 self.atoms.set_velocities(v) bonds = getBonds(self.natom, self.atoms.calc.r, 1.22 * self.re) newbond = self.checkBond(bonds) if newbond: self.zv = None self.Deformed += 0.2 bonds = getBonds(self.natom, self.atoms.calc.r, 1.25 * self.re) newbond = self.checkBond(bonds) if newbond: self.Deformed += 0.2 bonds = getBonds(self.natom, self.atoms.calc.r, 1.23 * self.re) newbond = self.checkBond(bonds) if newbond: self.Deformed += 0.2 bonds = getBonds(self.natom, self.atoms.calc.r, 1.21 * self.re) newbond = self.checkBond(bonds) if newbond: self.Deformed += 0.2 bonds = getBonds(self.natom, self.atoms.calc.r, 1.19 * self.re) newbond = self.checkBond(bonds) if newbond: self.Deformed += 0.2 bonds = getBonds(self.natom, self.atoms.calc.r, 1.17 * self.re) newbond = self.checkBond(bonds) self.zmats.append(zmat) else: r = a.calc.r.detach().numpy() i_ = np.where( np.logical_and(r < self.rmin * self.ro, r > 0.0001)) n = len(i_[0]) if len(self.Epot) == 0: dE_ = 0.0 else: dE_ = abs(epot_ - self.Epot[-1]) if dE_ > self.dEtole: self.dEstop_ += dE_ self.Epot.append(epot_) self.epot = epot_ / self.natom self.ekin = a.get_kinetic_energy() / self.natom self.T = self.ekin / (1.5 * units.kB) self.step = self.dyn.nsteps print('Step %d Epot = %.3feV Ekin = %.3feV (T=%3.0fK) ' 'Etot = %.3feV' % (self.step, self.epot, self.ekin, self.T, self.epot + self.ekin)) try: if self.CheckZmat: assert self.Deformed < 1 and self.dEstop_ < self.dEstop, 'Atoms structure is deformed!' else: assert n == 0 and self.T < self.Tmax and self.dEstop_ < self.dEstop, 'Atoms too closed or Temperature goes too high!' except: # for _ in i_: # print('atoms pair',_) if n > 0: print('Atoms too closed, stop at %d.' % self.step) elif self.Deformed >= 1.0: print( 'Structure Deformed = %f exceed the limit, stop at %d.' % (self.Deformed, self.step)) elif self.dEstop_ > self.dEstop: print('The sum of dE = %f exceed the limit, stop at %d.' % (self.dEstop_, self.step)) elif self.T > self.Tmax: print('Temperature = %f too high!, stop at %d.' % (self.T, self.step)) else: print('unknown reason, stop at %d.' % self.step) self.dyn.max_steps = self.dyn.nsteps - 1 # traj = Trajectory('md.traj', 'w', self.atoms) self.dyn.attach(printenergy, interval=self.print_interval) # self.dyn.attach(traj.write,interval=1) self.dyn.run(self.totstep) return self.Deformed, self.zmats, self.zv, self.zvlo, self.zvhi def opt(self): self.zv, self.zvlo, self.zvhi = None, 0.0, 0.0 self.dyn = BFGS(self.atoms, trajectory='md.traj') def check(a=self.atoms): epot_ = a.get_potential_energy() n, self.Deformed = 0, 0 if self.CheckZmat: Deformed, zmat, self.zv, self.zvlo, self.zvhi = check_zmat( atoms=a, rmin=self.rmin, rmax=self.rmax, angmax=self.angmax, zmat_id=self.zmat_id, zmat_index=self.zmat_index, InitZmat=self.InitZmat) bonds = getBonds(self.natom, self.atoms.calc.r, 1.18 * self.re) newbond = self.checkBond(bonds) if newbond: self.zv = None self.Deformed += 0.2 bonds = getBonds(self.natom, self.atoms.calc.r, 1.25 * self.re) newbond = self.checkBond(bonds) if newbond: self.Deformed += 0.2 bonds = getBonds(self.natom, self.atoms.calc.r, 1.23 * self.re) newbond = self.checkBond(bonds) if newbond: self.Deformed += 0.2 bonds = getBonds(self.natom, self.atoms.calc.r, 1.21 * self.re) newbond = self.checkBond(bonds) if newbond: self.Deformed += 0.2 bonds = getBonds(self.natom, self.atoms.calc.r, 1.19 * self.re) newbond = self.checkBond(bonds) if newbond: self.Deformed += 0.2 bonds = getBonds(self.natom, self.atoms.calc.r, 1.17 * self.re) newbond = self.checkBond(bonds) self.zmats.append(zmat) else: r = a.calc.r.detach().numpy() i_ = np.where( np.logical_and(r < self.rmin * self.ro, r > 0.0001)) n = len(i_[0]) self.Epot.append(epot_) self.epot = epot_ / self.natom self.step = self.dyn.nsteps try: if self.CheckZmat: assert Deformed < 1, 'Atoms too closed or Deformed!' else: assert n == 0 and ( not np.isnan(epot_)), 'Atoms too closed!' except: if n > 0: print('Atoms too closed, stop at %d.' % self.step) elif self.Deformed >= 1.0: print( 'Structure Deformed = %f exceed the limit, stop at %d.' % (self.Deformed, self.step)) elif np.isnan(epot_): print('potential energy is NAN, stop at %d.' % self.step) else: print('unknown reason, stop at %d.' % self.step) self.dyn.max_steps = self.dyn.nsteps - 1 self.dyn.attach(check, interval=1) self.dyn.run(0.00001, self.totstep) return self.Deformed, self.zmats, self.zv, self.zvlo, self.zvhi def checkBond(self, bonds): newbond = False for bd in bonds: bd_ = (bd[1], bd[0]) if (bd not in self.InitBonds) and (bd_ not in self.InitBonds): newbond = True return newbond return newbond def logout(self): with open('md.log', 'w') as fmd: fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n- Energies From Machine Learning MD Iteration %4d -\n' % self.Iter) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write('- Ebond=%f ' % self.atoms.calc.Ebond) fmd.write('- Elone=%f ' % self.atoms.calc.Elone) fmd.write('- Eover=%f ' % self.atoms.calc.Eover) fmd.write('- Eunder=%f \n' % self.atoms.calc.Eunder) fmd.write('- Eang=%f ' % self.atoms.calc.Eang) fmd.write('- Epen=%f ' % self.atoms.calc.Epen) fmd.write('- Etcon=%f \n' % self.atoms.calc.Etcon) fmd.write('- Etor=%f ' % self.atoms.calc.Etor) fmd.write('- Efcon=%f ' % self.atoms.calc.Efcon) fmd.write('- Evdw=%f ' % self.atoms.calc.Evdw) fmd.write('- Ecoul=%f \n' % self.atoms.calc.Ecoul) fmd.write('- Ehb=%f ' % self.atoms.calc.Ehb) fmd.write('- Eself=%f ' % self.atoms.calc.Eself) fmd.write('- Ezpe=%f \n' % self.atoms.calc.zpe) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n- Atomic Information (Delta and Bond order) -\n' ) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n AtomID Sym Delta NLP DLPC Bond-Order \n') for i in range(self.natom): fmd.write( '%6d %2s %9.6f %9.6f %9.6f' % (i, self.atoms.calc.atom_name[i], self.atoms.calc.Delta[i], self.atoms.calc.nlp[i], self.atoms.calc.Delta_lpcorr[i])) for j in range(self.natom): if self.atoms.calc.bo0[i][j] > self.atoms.calc.botol: fmd.write(' %3d %2s %9.6f' % (j, self.atoms.calc.atom_name[j], self.atoms.calc.bo0[i][j])) fmd.write(' \n') fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n- Atomic Energies & Forces -\n' ) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n AtomID Sym Delta_lp Elone Eover Eunder Fx Fy Fz\n' ) for i in range(self.natom): fmd.write( '%6d %2s %9.6f %9.6f %9.6f %9.6f ' % (i, self.atoms.calc.atom_name[i], self.atoms.calc.Delta_lp[i], self.atoms.calc.elone[i], self.atoms.calc.eover[i], self.atoms.calc.eunder[i])) for f in self.atoms.calc.results['forces'][i]: fmd.write(' %9.6f ' % f) fmd.write(' \n') fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write('\n- Machine Learning MD Completed!\n') def close(self): self.logout() self.dyn = None self.atoms = None
if i == j: image.set_calculator(calc) image.set_constraint(constraint) images.append(image) images.append(final) neb = NEB(images, climb=True, parallel=True) neb.interpolate() dyn = BFGS(neb, logfile="logFile") #if rank % (size // ) == 0: # traj = PickleTrajectory('neb%d.traj' % j, 'w', images[j], master=True) # qn.attach(traj) for i in range(0, numOfImages): dyn.attach(PickleTrajectory('neb-%d.traj' % i, 'w', images[i]), master=True) dyn.run(fmax=0.014) #writes the coordinates for each image in NEB path in .xyz format string = 'structure' path = os.getcwd() path = path + '/neb-scratch' if not os.path.exists(path): os.makedirs(path) outFileName = 'NEB-trajectory.xyz' if os.path.exists(outFileName): os.remove(outFileName) for i in range(0, neb.nimages): string = 'structure%03d' % (i, ) + '.xyz'
for i in range(3): ranks = range(i * n, (i + 1) * n) image = initial.copy() if rank in ranks: calc = GPAW(h=0.3, kpts=(2, 2, 1), txt='neb%d.txt' % j, communicator=ranks) image.set_calculator(calc) image.set_constraint(constraint) images.append(image) images.append(final) neb = NEB(images, parallel=True) neb.interpolate() qn = BFGS(neb, logfile='qn.log') traj = PickleTrajectory('neb%d.traj' % j, 'w', images[j], master=(rank % n == 0)) qn.attach(traj) qn.run(fmax=0.05)
class IRMD(object): ''' Intelligent Reactive Molecular Dynamics ''' def __init__(self, atoms=None, gen='poscar.gen', ffield='ffield.json', index=-1, totstep=100, vdwnn=False, nn=True, initT=300, Tmax=25000, time_step=0.1, ro=None, rtole=0.6, Iter=0, bondTole=1.3, CheckDE=False, dEstop=0.5): self.Epot = [] self.epot = 0.0 self.ekin = 0.0 self.T = 0.0 self.initT = initT self.Tmax = Tmax self.totstep = totstep self.ro = ro self.rtole = rtole self.Iter = Iter self.atoms = atoms self.time_step = time_step self.step = 0 self.bondTole = bondTole self.CheckDE = CheckDE self.dEstop = dEstop if self.atoms is None: self.atoms = read(gen, index=index) self.atoms.calc = IRFF(atoms=self.atoms, libfile=ffield, rcut=None, nn=nn, vdwnn=vdwnn) self.natom = len(self.atoms) self.re = self.atoms.calc.re self.dyn = None self.atoms.calc.calculate(atoms=self.atoms) self.InitBonds = getBonds(self.natom, self.atoms.calc.r, self.bondTole * self.re) if (self.atoms is None) and gen.endswith('.gen'): MaxwellBoltzmannDistribution(self.atoms, self.initT * units.kB) else: temp = self.atoms.get_temperature() if temp > 0.0000001: scale = np.sqrt(self.initT / temp) p = self.atoms.get_momenta() p = scale * p self.atoms.set_momenta(p) else: MaxwellBoltzmannDistribution(self.atoms, self.initT * units.kB) def run(self): self.dyn = VelocityVerlet(self.atoms, self.time_step * units.fs, trajectory='md.traj') def printenergy(a=self.atoms): epot_ = a.get_potential_energy() r = a.calc.r.detach().numpy() i_ = np.where(np.logical_and(r < self.rtole * self.ro, r > 0.0001)) n = len(i_[0]) if len(self.Epot) == 0: dE_ = 0.0 else: dE_ = abs(epot_ - self.Epot[-1]) self.Epot.append(epot_) self.epot = epot_ / self.natom self.ekin = a.get_kinetic_energy() / self.natom self.T = self.ekin / (1.5 * units.kB) self.step = self.dyn.nsteps print('Step %d Epot = %.3feV Ekin = %.3feV (T=%3.0fK) ' 'Etot = %.3feV' % (self.step, self.epot, self.ekin, self.T, self.epot + self.ekin)) try: if self.CheckDE: assert n == 0 and dE_ < self.dEstop, 'Atoms too closed or Delta E too high!' else: assert n == 0 and self.T < self.Tmax, 'Atoms too closed or Temperature goes too high!' except: # for _ in i_: # print('atoms pair',_) print( 'Atoms too closed or Temperature goes too high, stop at %d.' % self.step) self.dyn.max_steps = self.dyn.nsteps - 1 # traj = Trajectory('md.traj', 'w', self.atoms) self.dyn.attach(printenergy, interval=1) # self.dyn.attach(traj.write,interval=1) self.dyn.run(self.totstep) # bonds = getBonds(self.natom,self.atoms.calc.r,self.bondTole*self.re) # bondBroken = self.checkBond(bonds) # return bondBroken def opt(self): self.dyn = BFGS(self.atoms, trajectory='md.traj') def check(a=self.atoms): epot_ = a.get_potential_energy() r = a.calc.r.detach().numpy() i_ = np.where(np.logical_and(r < self.rtole * self.ro, r > 0.0001)) n = len(i_[0]) self.Epot.append(epot_) self.epot = epot_ / self.natom self.step = self.dyn.nsteps try: assert n == 0 and (not np.isnan(epot_)), 'Atoms too closed!' except: for _ in i_: print('atoms pair', _) print('Atoms too closed or temperature too high, stop at %d.' % self.step) self.dyn.max_steps = self.dyn.nsteps - 1 # raise ValueError('- Energy is NaN!' ) self.dyn.attach(check, interval=1) self.dyn.run(0.00001, self.totstep) bonds = getBonds(self.natom, self.atoms.calc.r, self.bondTole * self.re) bondBroken = self.checkBond(bonds) return bondBroken def checkBond(self, bonds): bondBroken = False for bd in self.InitBonds: bd_ = (bd[1], bd[0]) if (bd not in bonds) and (bd_ not in bonds): bondBroken = True return bondBroken return bondBroken def logout(self): with open('md.log', 'w') as fmd: fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n- Energies From Machine Learning MD Iteration %4d -\n' % self.Iter) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write('- Ebond=%f ' % self.atoms.calc.Ebond) fmd.write('- Elone=%f ' % self.atoms.calc.Elone) fmd.write('- Eover=%f ' % self.atoms.calc.Eover) fmd.write('- Eunder=%f \n' % self.atoms.calc.Eunder) fmd.write('- Eang=%f ' % self.atoms.calc.Eang) fmd.write('- Epen=%f ' % self.atoms.calc.Epen) fmd.write('- Etcon=%f \n' % self.atoms.calc.Etcon) fmd.write('- Etor=%f ' % self.atoms.calc.Etor) fmd.write('- Efcon=%f ' % self.atoms.calc.Efcon) fmd.write('- Evdw=%f ' % self.atoms.calc.Evdw) fmd.write('- Ecoul=%f \n' % self.atoms.calc.Ecoul) fmd.write('- Ehb=%f ' % self.atoms.calc.Ehb) fmd.write('- Eself=%f ' % self.atoms.calc.Eself) fmd.write('- Ezpe=%f \n' % self.atoms.calc.zpe) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n- Atomic Information (Delta and Bond order) -\n' ) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n AtomID Sym Delta NLP DLPC Bond-Order \n') for i in range(self.natom): fmd.write( '%6d %2s %9.6f %9.6f %9.6f' % (i, self.atoms.calc.atom_name[i], self.atoms.calc.Delta[i], self.atoms.calc.nlp[i], self.atoms.calc.Delta_lpcorr[i])) for j in range(self.natom): if self.atoms.calc.bo0[i][j] > self.atoms.calc.botol: fmd.write(' %3d %2s %9.6f' % (j, self.atoms.calc.atom_name[j], self.atoms.calc.bo0[i][j])) fmd.write(' \n') fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n- Atomic Energies & Forces -\n' ) fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write( '\n AtomID Sym Delta_lp Elone Eover Eunder Fx Fy Fz\n' ) for i in range(self.natom): fmd.write( '%6d %2s %9.6f %9.6f %9.6f %9.6f ' % (i, self.atoms.calc.atom_name[i], self.atoms.calc.Delta_lp[i], self.atoms.calc.elone[i], self.atoms.calc.eover[i], self.atoms.calc.eunder[i])) for f in self.atoms.calc.results['forces'][i]: fmd.write(' %9.6f ' % f) fmd.write(' \n') fmd.write( '\n------------------------------------------------------------------------\n' ) fmd.write('\n- Machine Learning MD Completed!\n') def close(self): self.logout() self.dyn = None self.atoms = None
kp2 = [1 for i in range(3)] for i in range(3): kp2[i] = int(np.ceil(20 / np.linalg.norm(atoms.cell[i, :]))) vdW = 'BEEF-vdW' calc = GPAW(xc=vdW, mode=PW(700, dedecut='estimate'), kpts={ 'size': kp2, 'gamma': True }, occupations=FermiDirac(width=0.05)) atoms.set_calculator(calc) name = atoms.get_chemical_formula(mode='hill') atoms.calc.set(txt=name + '_final.txt') atoms.calc.attach(atoms.calc.write, 5, name + '_final.gpw') uf = ExpCellFilter(atoms, constant_volume=True) relax = BFGS(uf) traj = Trajectory(name + '_final.traj', 'w', atoms) relax.attach(traj) relax.run(fmax=0.03) atoms.calc.write(name + '_final.gpw') #Writing ensemble energies to file if atoms.calc.get_xc_functional() == 'BEEF-vdW': ens = BEEFEnsemble(atoms.calc) ens_material = ens.get_ensemble_energies() np.savetxt(str(name) + '_Ensemble_Energies.txt', ens_material)
def test_emt1(testdir): a = 3.6 b = a / 2 cu = Atoms('Cu2Ag', positions=[(0, 0, 0), (b, b, 0), (a, a, b)], calculator=EMT()) e0 = cu.get_potential_energy() print(e0) d0 = cu.get_distance(0, 1) cu.set_constraint(FixBondLength(0, 1)) def f(): print(cu.get_distance(0, 1)) qn = BFGS(cu) with Trajectory('cu2ag.traj', 'w', cu) as t: qn.attach(t.write) qn.attach(f) qn.run(fmax=0.001) assert abs(cu.get_distance(0, 1) - d0) < 1e-14