Beispiel #1
1
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
Beispiel #2
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
Beispiel #3
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
Beispiel #4
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
Beispiel #5
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
Beispiel #6
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)
Beispiel #8
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)))
Beispiel #10
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
Beispiel #11
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]
Beispiel #12
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]))
Beispiel #13
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))
Beispiel #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.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))
Beispiel #15
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'
Beispiel #16
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
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()
Beispiel #18
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
Beispiel #19
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()
Beispiel #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'
Beispiel #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
Beispiel #22
0
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)
Beispiel #23
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
Beispiel #24
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'
Beispiel #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)
Beispiel #26
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
Beispiel #27
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)
Beispiel #28
-1
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