Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
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)
Exemple #9
0
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)))
Exemple #11
0
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
Exemple #12
0
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]
Exemple #13
0
                    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]))
Exemple #14
0
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))
Exemple #15
0
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))
Exemple #16
0
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()
Exemple #17
0
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)
Exemple #18
0
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
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()
Exemple #20
0
    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'
Exemple #21
0
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)
Exemple #23
0
    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'
Exemple #24
0
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
Exemple #25
0
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)
Exemple #26
0
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
Exemple #27
0
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
Exemple #28
0
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'