Beispiel #1
0
def SinglePointEnergies(traj,
                        label='aimd',
                        xcf='VDW',
                        xca='DRSLL',
                        basistype='DZP',
                        EngTole=0.0000001,
                        frame=50,
                        cpu=4,
                        dE=0.2,
                        d2E=0.1,
                        select=False):
    ''' get single point energy and labeling data '''
    images = Trajectory(traj)
    tframe = len(images)
    E, E_, dEs = [], [], []
    if tframe > frame:
        if frame > 1:
            ind_ = list(np.linspace(0, tframe - 1, num=frame, dtype=np.int32))
        else:
            ind_ = [tframe - 1]
    else:
        ind_ = [i for i in range(tframe)]

    if len(ind_) > 1 and 0 in ind_:
        ind_.pop(0)

    his = TrajectoryWriter(label + '.traj', mode='w')
    energies = []
    d2Es = []
    dE_ = 0.0
    d2E_ = 0.0

    for i, atoms in enumerate(images):
        energy = atoms.get_potential_energy()
        extreme_point = False

        if i > 0:
            if i < (tframe - 1):
                deltEl = energy - energies[-1]
                deltEr = images[i + 1].get_potential_energy() - energy
                dE_ = abs(deltEl)
                d2E_ = abs(deltEr - deltEl)
            else:
                deltEl = energy - energies[-1]
                deltEr = deltEl
                dE_ = abs(deltEl)

            if (deltEr > 0.0
                    and deltEl < 0.0) or (deltEr < 0.0
                                          and deltEl > 0.0) or dE_ < 0.00001:
                extreme_point = True

            if select:
                if dE_ > dE or extreme_point:
                    if i not in ind_:
                        if i - 1 not in ind_:
                            ind_.append(i)

        dEs.append(dE_)
        d2Es.append(d2E_)
        energies.append(energy)

    ide = np.argmax(dEs)
    id2e = np.argmax(d2Es)
    if (ide not in ind_) and (ide + 1 not in ind_) and (ide - 1 not in ind_):
        ind_.append(ide)
    if id2e not in ind_ and (id2e + 1 not in ind_) and (id2e - 1 not in ind_):
        ind_.append(id2e)
    ind_.sort()

    LabelDataLog = '         AtomicConfigure   E(ML)  E(DFT)   Diff    dE   d2E  \n'
    LabelDataLog += '      --------------------------------------------------------\n'

    for i in ind_:
        atoms = images[i]
        e_ = atoms.get_potential_energy()
        dE_ = dEs[i]
        d2E_ = d2Es[i]

        atoms_ = single_point(atoms,
                              xcf=xcf,
                              xca=xca,
                              basistype=basistype,
                              cpu=cpu)
        e = atoms_.get_potential_energy()
        E.append(e)
        E_.append(e_)

        diff_ = abs(e - e_)
        LabelDataLog += '     {:3d}   {:9.5f}  {:9.5f}  {:6.6f}  {:5.4f}   {:5.4f}\n'.format(
            i, e_, e, diff_, dE_, d2E_)
        with open('SinglePointEnergies.log', 'a') as fs:
            fs.write(
                '%d MLP: %9.5f DFT: %9.5f Diff: %6.6f dE: %5.4f d2E: %5.4f\n' %
                (i, e_, e, diff_, dE_, d2E_))

        if diff_ > EngTole:  # or i==ind_[-1]
            his.write(atoms=atoms_)

    his.close()
    images = None
    dEmax = dEs[ide]
    d2Emax = d2Es[id2e]
    return E, E_, dEmax, d2Emax, LabelDataLog
Beispiel #2
0
def dh(traj='siesta.traj', batch_size=1, nn=True, frame=7):
    ffield = 'ffield.json' if nn else 'ffield'
    images = Trajectory(traj)
    atoms = images[frame]
    his = TrajectoryWriter('tmp.traj', mode='w')
    his.write(atoms=atoms)
    his.close()

    from irff.irff import IRFF
    ir = IRFF(atoms=atoms, libfile=ffield, nn=nn, bo_layer=[9, 2])
    ir.get_potential_energy(atoms)

    from irff.reax import ReaxFF
    rn = ReaxFF(libfile=ffield,
                direcs={'tmp': 'tmp.traj'},
                dft='siesta',
                opt=[],
                optword='nocoul',
                batch_size=batch_size,
                atomic=True,
                clip_op=False,
                InitCheck=False,
                nn=nn,
                pkl=False,
                to_train=False)
    molecules = rn.initialize()
    rn.session(learning_rate=1.0e-10, method='AdamOptimizer')

    mol = 'tmp'
    hblab = rn.lk.hblab
    hbs = []

    for hb in ir.hbs:
        hbs.append(list(hb))

    eh_ = rn.get_value(rn.EHB)
    # eh     = ir.ehb.numpy()
    rhb_ = rn.get_value(rn.rhb)
    # rhb    = ir.rhb.numpy()

    frhb_ = rn.get_value(rn.frhb)
    # frhb   = ir.frhb.numpy()

    sin4_ = rn.get_value(rn.sin4)
    # sin4   = ir.sin4.numpy()

    # exphb1_= rn.get_value(rn.exphb1)
    # exphb2_= rn.get_value(rn.exphb2)

    # exphb1 = ir.exphb1.numpy()
    # exphb2 = ir.exphb2.numpy()

    # hbsum_ = rn.get_value(rn.hbsum)
    # hbsum  = ir.hbsum.numpy()

    for hb in rn.hbs:
        for a_ in range(rn.nhb[hb]):
            a = hblab[hb][a_][1:]
            i, j, k = a

            if a in hbs:
                ai = hbs.index(a)
                # if eh_[hb][a_][0]<-0.000001:
                print(
                    '-  %2d%s-%2d%s-%2d%s:' %
                    (i, ir.atom_name[i], j, ir.atom_name[j], k,
                     ir.atom_name[k]), 'ehb: %10.8f' % (eh_[hb][a_][0]),
                    'rhb: %10.8f' % (rhb_[hb][a_][0]),
                    'frhb: %10.8f' % (frhb_[hb][a_][0]),
                    'sin4: %10.8f' % (sin4_[hb][a_][0]))
Beispiel #3
0
    def _find_one_transition_path(self,
                                  path_length=1000,
                                  trajfile="default.traj",
                                  target="both",
                                  nsteps=None):
        """
        Finds a transition path by running random samples

        :param int path_length: Number of MC sweep in path
        :param str trajfile: Trajectory file where path will be stored
        :param str target: Target basins (reactant, product or both)
        :param nsteps: Number of MC steps in one sweep
        :type nsteps: int or None
        """
        supported_targets = ["reactant", "product", "both"]
        if target not in supported_targets:
            raise ValueError("Target has to be one of {}"
                             "".format(supported_targets))

        # Check if a snapshot tracker is attached
        traj = TrajectoryWriter(trajfile, mode="w")
        result = {}
        symbs = []
        unique_symbols = []
        for atom in self.atoms:
            if atom.symbol not in unique_symbols:
                unique_symbols.append(atom.symbol)

        output_every_sec = 30
        now = time.time()
        energies = []
        result = {}
        sizes = []
        for sweep in range(int(path_length)):
            self.network.reset()
            if time.time() - now > output_every_sec:
                self.log("Sweep {} of {}".format(sweep, path_length))
                now = time.time()
            self.sweep(nsteps=nsteps)

            # Explicitly enforce a construction of the network
            self.network(None)
            energies.append(self.current_energy)
            symbs.append([atom.symbol for atom in self.atoms])
            atoms = self.network.get_atoms_with_largest_cluster(
                prohibited_symbols=unique_symbols)
            sizes.append(self.network.max_size)
            self._add_info_to_atoms(atoms)
            calc = SinglePointCalculator(atoms, energy=self.current_energy)
            atoms.set_calculator(calc)
            if atoms is None:
                traj.write(self.atoms)
            else:
                traj.write(atoms)

            if target == "reactant":
                if self.is_product():
                    # Terminate before the desired path length is reached
                    result["type"] = "product"
                    result["symbols"] = symbs
                    result["energy"] = energies
                    result["sizes"] = sizes
                    return result
            elif target == "product":
                if self.is_reactant():
                    result["type"] = "reactant"
                    result["symbols"] = symbs
                    result["energy"] = energies
                    result["sizes"] = sizes
                    # Terminate before the desired path length is reached
                    return result

        traj.close()
        if self.is_reactant():
            result["type"] = "reactant"
        elif self.is_product():
            result["type"] = "product"
        else:
            stat = self.network.get_statistics()
            max_size = stat["max_size"]
            msg = "State did not end up in product or reactant region. "
            msg += "Increase the number of sweeps.\n"
            msg += "Max. cluster size {}.".format(max_size)
            msg += "Max cluster size reactants {}".format(
                self.max_size_reactant)
            msg += "Min cluster size products {}".format(self.min_size_product)
            raise DidNotReachProductOrReactantError(msg)

        result["symbols"] = symbs
        result["energy"] = energies
        result["sizes"] = sizes
        return result
Beispiel #4
0
def da(traj='opt.traj', batch_size=50, ef=3, nn=True, frame=44):
    ffield = 'ffield.json' if nn else 'ffield'
    images = Trajectory(traj)
    atoms = images[frame]
    his = TrajectoryWriter('tmp.traj', mode='w')
    his.write(atoms=atoms)
    # his.write(atoms=images[frame+1])
    his.close()

    ir = IRFF(atoms=atoms, libfile=ffield, nn=nn, autograd=False)
    ir.calculate(atoms)

    rn = MPNN(libfile=ffield,
              direcs={'tmp': 'tmp.traj'},
              dft='siesta',
              opt=[],
              optword='nocoul',
              batch_size=batch_size,
              atomic=True,
              clip_op=False,
              InitCheck=False,
              nn=nn,
              bo_layer=[9, 2],
              EnergyFunction=ef,
              pkl=False)
    molecules = rn.initialize()
    rn.session(learning_rate=1.0e-10, method='AdamOptimizer')

    mol = 'tmp'
    anglab = rn.lk.anglab
    angs = []
    for ang in ir.angs:
        angs.append(list(ang))

    ea_ = rn.get_value(rn.EANG)
    ea = ir.eang.numpy()
    f7_ = rn.get_value(rn.f_7)
    f7 = ir.f_7.numpy()
    f8_ = rn.get_value(rn.f_8)
    f8 = ir.f_8.numpy()
    expang_ = rn.get_value(rn.expang)
    expang = ir.expang.numpy()

    theta_ = rn.get_value(rn.theta)
    theta = ir.theta.numpy()
    theta0_ = rn.get_value(rn.theta0)
    theta0 = ir.thet0.numpy()

    sbo3_ = rn.get_value(rn.SBO3)
    sbo3 = ir.SBO3.numpy()

    fa = open('ang.txt', 'w')
    for ang in rn.angs:
        for a_ in range(rn.nang[ang]):
            a = anglab[ang][a_][1:]

            if a not in angs:
                a.reverse()
            i, j, k = a
            if a in angs:
                ai = angs.index(a)
                print(
                    ' * %2d%s-%2d%s-%2d%s:' %
                    (i, ir.atom_name[i], j, ir.atom_name[j], k,
                     ir.atom_name[k]),
                    #'eang: %10.8f  %10.8f' %(ea_[ang][a_][0],ea[ai]),
                    'f7: %10.8f  %10.8f' % (f7_[ang][a_][0], f7[ai]),
                    'f8: %10.8f  %10.8f' % (f8_[ang][a_][0], f8[ai]),
                    'expang: %10.8f  %10.8f' %
                    (expang_[ang][a_][0], expang[ai]),
                    'theta: %10.8f  %10.8f' % (theta_[ang][a_][0], theta[ai]),
                    # 'sbo3: %10.8f  %10.8f' %(sbo3_[ang][a_][0],sbo3[ai]),
                    'theta0: %10.8f  %10.8f' %
                    (theta0_[ang][a_][0], theta0[ai]),
                    file=fa)
            else:
                print(
                    ' * %2d%s-%2d%s-%2d%s:' %
                    (i, ir.atom_name[i], j, ir.atom_name[j], k,
                     ir.atom_name[k]),
                    #'eang: %10.8f' %(ea_[ang][a_][0]),
                    'f7: %10.8f' % (f7_[ang][a_][0]),
                    'f8: %10.8f' % (f8_[ang][a_][0]),
                    'expang: %10.8f' % (expang_[ang][a_][0]),
                    'expang: %10.8f' % (expang_[ang][a_][0]),
                    'theta: %10.8f' % (theta_[ang][a_][0]),
                    # 'sbo3: %10.8f' %(sbo3_[ang][a_][0]),
                    'theta0: %10.8f' % (theta0_[ang][a_][0]))
    fa.close()
    epen = rn.get_value(rn.epen)
    eang = rn.get_value(rn.eang)
    print(' * penalty energy:', ir.Epen.numpy(), epen[mol][0])
    print(' * angel energy:', ir.Eang.numpy(), eang[mol][0])
Beispiel #5
0
def dt(traj='siesta.traj', batch_size=1, nn=True, frame=0):
    ffield = 'ffield.json' if nn else 'ffield'
    images = Trajectory(traj)
    atoms = images[frame]
    his = TrajectoryWriter('tmp.traj', mode='w')
    his.write(atoms=atoms)
    his.close()

    from irff.irff import IRFF
    ir = IRFF(atoms=atoms, libfile=ffield, nn=nn)
    ir.get_potential_energy(atoms)
    eb = ir.Ebond.numpy()

    et = ir.etor.numpy()
    ef = ir.efcon.numpy()
    f10 = ir.f_10.numpy()
    f11 = ir.f_11.numpy()

    sijk = ir.s_ijk.numpy()
    sjkl = ir.s_jkl.numpy()

    f = ir.fijkl.numpy()
    v1 = ir.v1.numpy()
    v2 = ir.v2.numpy()
    v3 = ir.v3.numpy()

    expv2 = ir.expv2.numpy()

    boij = ir.botij.numpy()
    bojk = ir.botjk.numpy()
    bokl = ir.botkl.numpy()

    cosw = ir.cos_w.numpy()
    cos2w = ir.cos2w.numpy()
    w = ir.w.numpy()

    Etor = ir.Etor.numpy()
    del IRFF

    from irff.reax import ReaxFF
    rn = ReaxFF(libfile=ffield,
                direcs={'tmp': 'tmp.traj'},
                dft='siesta',
                opt=[],
                optword='nocoul',
                batch_size=batch_size,
                atomic=True,
                clip_op=False,
                InitCheck=False,
                nn=nn,
                bo_layer=[9, 2],
                pkl=False,
                to_train=False)
    molecules = rn.initialize()
    # rn.calculate(rn.p,rn.m)
    rn.session(learning_rate=3.0 - 4, method='AdamOptimizer')

    mol = 'tmp'
    torlab = rn.lk.torlab
    tors = []
    for tor in ir.tors:
        tors.append(list(tor))
        print(tor)

    eb_ = rn.get_value(rn.ebond[mol])
    et_ = rn.get_value(rn.ETOR)
    ef_ = rn.get_value(rn.Efcon)
    f10_ = rn.get_value(rn.f_10)
    f11_ = rn.get_value(rn.f_11)

    sijk_ = rn.get_value(rn.s_ijk)
    sjkl_ = rn.get_value(rn.s_jkl)

    f_ = rn.get_value(rn.fijkl)

    boij_ = rn.get_value(rn.BOtij)
    bojk_ = rn.get_value(rn.BOtjk)
    bokl_ = rn.get_value(rn.BOtkl)

    v1_ = rn.get_value(rn.v1)
    v2_ = rn.get_value(rn.v2)
    v3_ = rn.get_value(rn.v3)

    expv2_ = rn.get_value(rn.expv2)

    cosw_ = rn.get_value(rn.cos_w)
    cos2w_ = rn.get_value(rn.cos2w)
    w_ = rn.get_value(rn.w)

    for tor in rn.tors:
        for a_ in range(rn.ntor[tor]):
            a = torlab[tor][a_][1:]

            if a not in tors:
                a.reverse()
            i, j, k, l = a
            if a in tors:
                ai = tors.index(a)
                # if abs(et_[tor][a_][0]-et[ai])>0.0001:
                print(
                    '-  %2d%s-%2d%s-%2d%s-%2d%s:' %
                    (i, ir.atom_name[i], j, ir.atom_name[j], k,
                     ir.atom_name[k], l, ir.atom_name[l]),
                    'etor: %10.8f  %10.8f' % (et_[tor][a_][0], et[ai]),
                    'sijk: %10.8f  %10.8f' % (sijk_[tor][a_][0], sijk[ai]),
                    'sjkl: %10.8f  %10.8f' % (sjkl_[tor][a_][0], sjkl[ai]),
                    'boij: %10.8f  %10.8f' % (boij_[tor][a_][0], boij[ai]),
                    'bojk: %10.8f  %10.8f' % (bojk_[tor][a_][0], bojk[ai]),
                    'bokl: %10.8f  %10.8f' % (bokl_[tor][a_][0], bokl[ai]),
                    'fijkl: %10.8f  %10.8f' % (f_[tor][a_][0], f[ai]),
                    'v1: %10.8f  %10.8f' % (v1_[tor][a_][0], v1[ai]),
                    'v2: %10.8f  %10.8f' % (v2_[tor][a_][0], v2[ai]),
                    'v3: %10.8f  %10.8f' % (v3_[tor][a_][0], v3[ai]),
                    'expv2: %10.8f  %10.8f' % (expv2_[tor][a_][0], expv2[ai]),
                    'ptor1: %10.8f  %10.8f' %
                    (rn.p_['tor1_' + tor], ir.P['tor1'][ai]),
                    # 'cosw: %10.8f  %10.8f' %(cosw_[tor][a_][0],cosw[ai]),
                    # 'cos2w: %10.8f  %10.8f' %(cos2w_[tor][a_][0],cos2w[ai]),
                    #  'v1: %10.8f  %10.8f' %(0.5*rn.p_['V1_'+tor]*(1.0+cosw_[tor][a_][0]),
                    #                         0.5*ir.P['V1'][ai]*(1.0+cosw[ai])),
                    #  'w: %10.8f  %10.8f' %(w_[tor][a_][0],w[ai]),
                    # 'efcon: %10.8f  %10.8f' %(ef_[tor][a_][0],ef[ai]),
                    #  'f_10: %10.8f  %10.8f' %(f10_[tor][a_][0],f10[ai]),
                    #  'f_11: %10.8f  %10.8f' %(f11_[tor][a_][0],f11[ai]),
                )
    Etor_ = rn.get_value(rn.etor)
    print('\n-  torsion energy:', Etor, Etor_[mol][0], end='\n')
    print('\n-  Bond energy:', eb, eb_, end='\n')
    del ReaxFF
Beispiel #6
0
def dl(traj='siesta.traj', batch_size=1, nn=False, frame=0):
    ffield = 'ffield.json' if nn else 'ffield'
    images = Trajectory(traj)
    atoms = images[frame]
    his = TrajectoryWriter('tmp.traj', mode='w')
    his.write(atoms=atoms)
    his.close()

    ir = IRFF(atoms=atoms, libfile=ffield, nn=False, bo_layer=[8, 4])

    ir.get_potential_energy(atoms)
    el = ir.elone.numpy()
    Dle = ir.Delta_e.numpy()
    Dlp = ir.Delta_lp.numpy()
    de = ir.DE.numpy()
    nlp = ir.nlp.numpy()
    elp = ir.explp.numpy()
    eu = ir.eunder.numpy()
    eu1 = ir.eu1.numpy()
    eu2 = ir.eu2.numpy()
    eu3 = ir.expeu3.numpy()

    rn = ReaxFF(libfile=ffield,
                direcs={'tmp': 'tmp.traj'},
                dft='siesta',
                opt=[],
                optword='nocoul',
                batch_size=batch_size,
                atomic=True,
                clip_op=False,
                InitCheck=False,
                nn=nn,
                pkl=False,
                to_train=False)
    molecules = rn.initialize()
    rn.session(learning_rate=1.0e-10, method='AdamOptimizer')

    mol = 'tmp'
    el_ = rn.get_value(rn.EL)
    Dle_ = rn.get_value(rn.Delta_e)
    Dlp_ = rn.get_value(rn.Delta_lp)
    de_ = rn.get_value(rn.DE)
    nlp_ = rn.get_value(rn.nlp)
    elp_ = rn.get_value(rn.explp)

    eu_ = rn.get_value(rn.EUN)
    eu1_ = rn.get_value(rn.eu1)
    eu2_ = rn.get_value(rn.eu2)
    eu3_ = rn.get_value(rn.expeu3)

    alab = rn.lk.atlab
    bosi = ir.bosi.numpy()

    for i in range(ir.natom):
        a = ir.atom_name[i]
        al = [mol, i]
        na = alab[a].index(al)
        print(
            '-  %d %s:' % (i, ir.atom_name[i]),
            'elone: %10.8f  %10.8f' % (el_[a][na], el[i]),
            #  'Delta_e: %10.8f  %10.8f' %(Dle_[a][na],Dle[i]),
            # 'Delta_lp: %10.8f  %10.8f' %(Dlp_[a][na],Dlp[i]),
            #      'nlp: %10.8f  %10.8f' %(nlp_[a][na],nlp[i]),
            'eunder: %10.8f  %10.8f' % (eu_[a][na], eu[i]),
            #    'eu1: %10.8f  %10.8f' %(eu1_[a][na],eu1[i]),
            'eu2: %10.8f  %10.8f' % (eu2_[a][na], eu2[i]),
            'eu3: %10.8f  %10.8f' % (eu3_[a][na], eu3[i]))
    print('\n-  under energy:',
          ir.Eunder.numpy(),
          rn.eunder[mol].numpy()[0],
          end='\n')
Beispiel #7
0
#!/usr/bin/env python
from irff.nwchem import decompostion
from ase.io.trajectory import Trajectory, TrajectoryWriter
from ase.calculators.singlepoint import SinglePointCalculator
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

# decompostion(gen='rdx.gen',ncpu=12)
images1 = Trajectory('stretch0.traj')
images2 = Trajectory('stretch.traj')

traj = TrajectoryWriter('decompostion.traj', mode='w')

rs, es = [], []

for image in images1:
    vr = image.positions[3] - image.positions[18]
    vr2 = np.square(vr)
    r = np.sqrt(np.sum(vr2))
    rs.append(r)

    e = image.get_potential_energy()
    es.append(e)
    #calc = SinglePointCalculator(A,energy=e)
    #image.set_calculator(calc)
    traj.write(atoms=image)

for image in images2:
    vr = image.positions[3] - image.positions[18]
Beispiel #8
0
def static_compress():
    traj = TrajectoryWriter('pre_opt.traj', mode='w')
    atoms = read('nm.gen')
    cell = atoms.get_cell()
    atoms_ = atoms.copy()
    configs = []

    GPa = 1.60217662 * 1.0e2
    s = 1.0
    i = 0
    ir = IRFF(atoms=atoms_, libfile='ffield.json', nn=True)

    v_, p = [], []
    v0 = atoms.get_volume()

    while s > 0.66:
        print(' * lattice step:', i)
        f = s**(1.0 / 3.0)
        cell_ = cell.copy()
        cell_ = cell * f
        ir.CalStress = False
        atoms_.set_cell(cell_)
        atoms_ = opt(atoms=atoms_, fmax=0.02, step=120, optimizer=FIRE)
        configs.append(atoms_)
        traj.write(atoms=atoms_)
        ir.CalStress = True
        ir.calculate(atoms=atoms_)
        stress = ir.results['stress']

        nonzero = 0
        stre_ = 0.0
        for _ in range(3):
            if abs(stress[_]) > 0.0000001:
                nonzero += 1
                stre_ += -stress[_]
        pressure = stre_ * GPa / nonzero

        p.append(pressure)
        v = atoms_.get_volume()
        v_.append(v / v0)
        print(' * V/V0', v_[-1], v, pressure)

        s = s * 0.98
        i += 1

    fig, ax = plt.subplots()
    plt.ylabel(r'$Pressure$ ($GPa$)')
    plt.xlabel(r'$V/V_0$')
    plt.plot(v_,
             p,
             label=r'$IRFF-MPNN$',
             color='blue',
             marker='o',
             markerfacecolor='none',
             markeredgewidth=1,
             ms=5,
             alpha=0.8,
             linewidth=1,
             linestyle='-')

    plt.legend(loc='best', edgecolor='yellowgreen')
    plt.savefig('pv.pdf')
    plt.close()
Beispiel #9
0
    def get_siesta_cart(self, label='siesta'):
        fin = open('in.fdf', 'r')
        lines = fin.readlines()
        fin.close()  # getting informations from input file

        for i, line in enumerate(lines):
            l = line.split()
            if len(l) > 0:
                if l[0] == 'NumberOfSpecies':
                    ns = int(l[1])
                if l[0] == 'NumberOfAtoms':
                    self.natom = int(l[1])
                if l[0] == '%block':
                    if l[1] == 'ChemicalSpeciesLabel':
                        spl = i + 1
                    if l[1] == 'AtomicCoordinatesAndAtomicSpecies':
                        atml = i + 1

        sp = []
        for isp in range(ns):
            l = lines[spl + isp].split()
            sp.append(l[2])

        for na in range(self.natom):
            l = lines[atml + na].split()
            self.atom_name.append(sp[int(l[3]) - 1])

        fe = open(label + '.MD_CAR', 'r')
        lines = fe.readlines()
        fe.close()
        nl = len(lines)
        if nl - (self.natom + 7) * self.nframe != 0:
            fra = (nl - (self.natom + 7) * self.nframe) / (self.natom + 7)
            print('-  %d frames more than expected, error case ... ... ...' %
                  fra)
            exit()

        lsp = lines[5].split()
        nsp = [int(l) for l in lsp]
        xs = []
        if self.traj:
            his = TrajectoryWriter(self.structure + '.traj', mode='w')
        for nf in range(self.nframe):
            block = self.natom + 7
            nl = block * nf
            la = lines[nl + 2].split()
            lb = lines[nl + 3].split()
            lc = lines[nl + 4].split()

            a = [float(la[0]), float(la[1]), float(la[2])]
            b = [float(lb[0]), float(lb[1]), float(lb[2])]
            c = [float(lc[0]), float(lc[1]), float(lc[2])]
            x = []
            il = 0
            for i, s in enumerate(nsp):
                for ns in range(s):
                    l = lines[nl + 7 + il].split()
                    xd = [float(l[0]), float(l[1]), float(l[2])]

                    x1 = xd[0] * a[0] + xd[1] * b[0] + xd[2] * c[0]
                    x2 = xd[0] * a[1] + xd[1] * b[1] + xd[2] * c[1]
                    x3 = xd[0] * a[2] + xd[1] * b[2] + xd[2] * c[2]

                    x.append([x1, x2, x3])
                    il += 1
            xs.append(x)
            if self.traj:
                A = Atoms(self.atom_name,
                          x,
                          cell=[a, b, c],
                          pbc=[True, True, True])
                his.write(atoms=A)

        self.cell = np.array([a, b, c])

        if self.traj:
            his.close()
        return xs
Beispiel #10
0
def cluster_GA(
    nPool,
    eleNames,
    eleNums,
    eleRadii,
    generations,
    calc,
    filename,
    log_file,
    CXPB=0.5,
    singleTypeCluster=False,
    use_dask=False,
    use_vasp=False,
    al_method=None,
    al_learner_params=None,
    train_config=None,
    optimizer=BFGS,
    use_vasp_inter=False,
    restart=False,
    gen_num=None,
):
    """
    DEAP Implementation of the GIGA Geneting Algorithm for nanoclusters

    nPool : Total number of clusters present in the initial pool
    eleNames : List of element symbols present in the cluster
    eleNums : List of the number of atoms of each element present in the cluster
    eleRadii : List of radii of each element present in the cluster
    generations : Total number of generations to run the genetic algorithm
    calc : The calculator used to perform relaxations (must be an ase calculator object)
    filename : Name of the file to be used to generate ase traj and db files
    log_file : Name of the log file
    CXPB : probability of a crossover operation in a given generation
    singleTypeCluster : Default = False, set to True if only 1 element is present in cluster
    use_Dask : Default = False, set to True if using dask (Refer examples on using dask)
    use_vasp : Default = False, set to True if using inbuilt vasp optimizer to run GA code (not supported with active learning)
    al_method : Default = None, accepts values 'online' or 'offline'
    al_learner_params : Default = None, refer examples or https://github.com/ulissigroup/al_mlp for sample set up
    trainer_config : Default = None, refer examples or https://github.com/ulissigroup/al_mlp for sample set up
    optimizer : Default = BFGS, ase optimizer to be used
    use_vasp_inter : Default = False, whether to use vasp interactive mode or not
    """
    def calculate(atoms):
        """
        Support function to assign the type of minimization to e performed (pure vasp, using ase optimizer or using active learning)
        """
        if al_method is not None:

            atoms_min, parent_calls = minimize_al(
                atoms,
                calc,
                eleNames,
                al_learner_params,
                train_config,
                dataset_parent,
                optimizer,
                al_method,
            )
        else:
            if use_vasp == True:
                atoms_min = minimize_vasp(atoms, calc)
            else:
                atoms_min = minimize(atoms, calc, optimizer, use_vasp_inter)
        return atoms_min, parent_calls

    if al_method is not None:
        al_method = al_method.lower()

    # Creating DEAP types
    creator.create("FitnessMax", base.Fitness, weights=(1.0, ))
    creator.create("Individual", list, fitness=creator.FitnessMax)

    # Registration of the evolutionary tools in the toolbox
    toolbox = base.Toolbox()
    toolbox.register("poolfill", fillPool, eleNames, eleNums, eleRadii, calc)
    toolbox.register("individual", tools.initRepeat, creator.Individual,
                     toolbox.poolfill, 1)
    toolbox.register("evaluate", fitness_func)
    toolbox.register("population", tools.initRepeat, list, toolbox.individual)

    # Registering mutations and crossover operators
    toolbox.register("mate", mate)
    toolbox.register("mutate_homotop", homotop)
    toolbox.register("mutate_rattle", rattle_mut)
    toolbox.register("mutate_rotate", rotate_mut)
    toolbox.register("mutate_twist", twist)
    toolbox.register("mutate_tunnel", tunnel)
    toolbox.register("mutate_partialinv", partialInversion)
    toolbox.register("mutate_skin", skin)
    toolbox.register("mutate_changecore", changeCore)

    # Registering selection operator
    toolbox.register("select", tools.selTournament)

    #Initialize the parent dataset
    dataset_parent = []
    # Creating a list of cluster atom objects from population
    if not restart:
        population = toolbox.population(n=nPool)
        pop_list = []
        for individual in population:
            pop_list.append(individual[0])
        write('init_pop_before_relax.traj', pop_list)

        if use_dask == True:
            # distribute and run the calculations (requires dask and needs to be set up correctly)
            clus_bag = db.from_sequence(pop_list, partition_size=1)
            clus_bag_computed = clus_bag.map(calculate)
            lst_clus_min = clus_bag_computed.compute()

        else:
            lst_clus_min = list(map(calculate, pop_list))

        for i, p in enumerate(population):
            p[0] = lst_clus_min[i][0]

        init_pop_list_after_relax = []
        for individual in population:
            init_pop_list_after_relax.append(individual[0])
        write('init_pop_after_relax.traj', init_pop_list_after_relax)
        with open(log_file, "a+") as fh:
            fh.write(
                f'Total clusters in the intital pool after relaxationi: {len(population)}'
                "\n")

        #parent_calls list if online learner
        total_parent_calls = []
        parent_calls_initial_pool = []
        for i in range(len(lst_clus_min)):
            parent_calls_initial_pool.append(lst_clus_min[i][1])
        total_parent_calls.extend(parent_calls_initial_pool)

        with open(log_file, "a+") as fh:
            fh.write(
                f'parent calls after initial pool relaxation: {parent_calls_initial_pool}'
                '\n')
            fh.write(
                f'Total parent calls after initial pool relaxation: {sum(parent_calls_initial_pool)}'
                '\n')

        # Fitnesses (or Energy) values of the initial random population
        fitnesses = list(map(toolbox.evaluate, population))

        for ind, fit in zip(population, fitnesses):
            ind.fitness.values = fit

        #Removing bad geometries
        population_filter = []
        for i, p in enumerate(population):
            if checkBonded(p[0]) == True:
                if checkOverlap(p[0]) == False:
                    population_filter.append(p)
        population = copy.deepcopy(population_filter)

        init_pop_list_after_filter = []
        for individual in population:
            init_pop_list_after_filter.append(individual[0])
        write('init_pop_after_filter.traj', init_pop_list_after_filter)
        with open(log_file, "a+") as fh:
            fh.write(
                f'Total clusters in the intital pool after filtering: {len(population)}'
                "\n")

        fitnesses_init_pool = list(map(toolbox.evaluate, population))
        with open(log_file, "a+") as fh:
            fh.write("Energies (fitnesses) of the initial pool" "\n")
            for value in fitnesses_init_pool:
                fh.write("{} \n".format(value[0]))

        # Evolution of the Genetic Algorithm
        with open(log_file, "a+") as fh:
            fh.write("\n")
            fh.write("Starting Evolution" "\n")

        g = 0  # Generation counter

        init_pop_db = ase.db.connect("init_pop_{}.db".format(filename))
        for cl in population:
            write_to_db(init_pop_db, cl[0])

        bi = []

    else:
        population = toolbox.population(n=nPool)
        restart_gen = 'best_n_clus_after_gen' + str(gen_num) + '.traj'
        restart_traj = Trajectory(restart_gen)
        for i, p in enumerate(population):
            p[0] = restart_traj[i]
        # Fitnesses (or Energy) values of the restart population from the gen_num
        fitnesses = list(map(toolbox.evaluate, population))

        for ind, fit in zip(population, fitnesses):
            ind.fitness.values = fit
        fitnesses_restart_pool = list(map(toolbox.evaluate, population))

        # Restarting the Evolution of the Genetic Algorithm from Restart Trajectory
        with open(log_file, "a+") as fh:
            fh.write("\n")
            fh.write("Restarting  Evolution" "\n")
            fh.write("Energies (fitnesses) of the Restarted pool" "\n")
            for value in fitnesses_restart_pool:
                fh.write("{} \n".format(value[0]))
            fh.write("\n")

        g = gen_num  # Generation counter -Restart gen number
        #parent_calls list if online learner
        total_parent_calls = []
        bi = []

        old_final_pop_db = "./final_pop_{}.db".format(filename)
        copy_final_pop_db = "final_pop_{}_{}.db".format(filename, gen_num)
        if os.path.exists(old_final_pop_db):
            subprocess.call(
                ['mv', old_final_pop_db, 'old_' + copy_final_pop_db])

    ##### Evolution of Generations ######

    while g < generations:
        mutType = None
        muttype_list = []
        g = g + 1
        with open(log_file, "a+") as fh:
            fh.write("{} {} \n".format("Generation", g))

        cm_pop = []
        if random.random() < CXPB:  # Crossover Operation
            mutType = "crossover"
            with open(log_file, "a+") as fh:
                fh.write("{} {} \n".format("mutType", mutType))

            # Crossover operation step.
            # The child clusters will be checked for bonding and similarity
            # between other child clusters.
            loop_count = 0
            while (
                    loop_count != 200
            ):  # Perform 200 possible crossovers or until unique crossovers match pool size
                clusters = toolbox.select(population, 2, 1)
                muttype_list.append(mutType)
                parent1 = copy.deepcopy(clusters[0])
                parent2 = copy.deepcopy(clusters[1])
                fit1 = clusters[0].fitness.values
                (f1, ) = fit1
                fit2 = clusters[1].fitness.values
                (f2, ) = fit2
                child_clus = toolbox.mate(parent1[0], parent2[0], f1, f2)
                parent1[0] = child_clus

                diff_list = []
                if checkBonded(parent1[0]) == True:
                    if loop_count == 0:
                        cm_pop.append(parent1)
                    else:
                        for c, cluster in enumerate(cm_pop):
                            diff = checkSimilar(cluster[0], parent1[0])
                            diff_list.append(diff)

                        if all(diff_list) == True:
                            cm_pop.append(parent1)
                loop_count = loop_count + 1

                if len(cm_pop) == nPool:
                    break

        else:  # Mutation Operation
            mutType = "mutations"
            with open(log_file, "a+") as fh:
                fh.write("{} {} \n".format("mutType", mutType))

                # Mutation opeation step
                # Each cluster in the population will undergo a randomly chosen mutation step
                # Mutated new clusters will be checked for bonding and similarity with other new clusters
            for m, mut in enumerate(population):
                mutant = copy.deepcopy(mut)
                if singleTypeCluster:
                    mutType = random.choice([
                        "rattle",
                        "rotate",
                        "twist",
                        "partialinv",
                        "tunnel",
                        "skin",
                        "changecore",
                    ])
                else:
                    mutType = random.choice([
                        "rattle",
                        "rotate",
                        "homotop",
                        "twist",
                        "partialinv",
                        "tunnel",
                        "skin",
                        "changecore",
                    ])

                muttype_list.append(mutType)

                if mutType == "homotop":
                    mutant[0] = toolbox.mutate_homotop(mutant[0])
                if mutType == "rattle":
                    mutant[0] = toolbox.mutate_rattle(mutant[0])
                if mutType == "rotate":
                    mutant[0] = toolbox.mutate_rotate(mutant[0])
                if mutType == "twist":
                    mutant[0] = toolbox.mutate_twist(mutant[0])
                if mutType == "tunnel":
                    mutant[0] = toolbox.mutate_tunnel(mutant[0])
                if mutType == "partialinv":
                    mutant[0] = toolbox.mutate_partialinv(mutant[0])
                if mutType == "skin":
                    mutant[0] = toolbox.mutate_skin(mutant[0])
                if mutType == "changecore":
                    mutant[0] = toolbox.mutate_changecore(mutant[0])

                diff_list = []
                if checkBonded(mutant[0]) == True:
                    for c, cluster in enumerate(cm_pop):
                        diff = checkSimilar(cluster[0], mutant[0])
                        diff_list.append(diff)

                    if all(diff_list) == True:
                        cm_pop.append(mutant)

            with open(log_file, "a+") as fh:
                fh.write("{} {} \n".format("mutType_list", muttype_list))

        mut_new_lst = []
        for mut in cm_pop:
            mut_new_lst.append(mut[0])
        write('mut_before_relax_gen' + str(g) + '.traj', mut_new_lst)

        # DASK Parallel relaxation of the crossover child/mutated clusters
        if use_dask == True:
            mut_bag = db.from_sequence(mut_new_lst, partition_size=1)
            mut_bag_computed = mut_bag.map(calculate)
            mut_new_lst_min = mut_bag_computed.compute()

        else:
            mut_new_lst_min = list(map(calculate, mut_new_lst))

        for i, mm in enumerate(cm_pop):
            mm[0] = mut_new_lst_min[i][0]

        mut_list_after_relax = []
        for individual in cm_pop:
            mut_list_after_relax.append(individual[0])
        write('mut_after_relax_gen' + str(g) + '.traj', mut_list_after_relax)
        with open(log_file, "a+") as fh:
            fh.write(
                f'Total clusters relaxed in  Generation {g}: {len(cm_pop)}'
                "\n")

        #parent calls list if online learner
        parent_calls_mut_list = []
        for i in range(len(mut_new_lst_min)):
            parent_calls_mut_list.append(mut_new_lst_min[i][1])

        total_parent_calls.extend(parent_calls_mut_list)

        with open(log_file, "a+") as fh:
            fh.write(
                f'Parent calls list after relaxtions in this generation: {parent_calls_mut_list} '
                '\n')
            fh.write(
                f'Total Parent calls  specific to this  generation: {sum(parent_calls_mut_list)} '
                '\n')
            fh.write(
                f'Total Parent calls  up  to this  generation: {sum(total_parent_calls)} '
                '\n')

        fitnesses_mut = list(map(toolbox.evaluate, cm_pop))

        for ind, fit in zip(cm_pop, fitnesses_mut):
            ind.fitness.values = fit

        new_population = copy.deepcopy(population)
        # Relaxed clusters will be checked for bonded and similarity with the other
        # clusters in the population. If dissimilar, they will be added to the new population.
        for cm1, cmut1 in enumerate(cm_pop):
            new_diff_list = []
            if checkBonded(cmut1[0]) == True:
                if checkOverlap(cmut1[0]) == False:
                    for c2, cluster1 in enumerate(population):
                        diff = checkSimilar(cluster1[0], cmut1[0])
                        new_diff_list.append(diff)
                    if all(new_diff_list) == True:
                        new_population.append(cmut1)
                    else:
                        pass

        mut_list_after_filter = []
        for individual in new_population:
            mut_list_after_filter.append(individual[0])
        write('mut_after_filter_gen' + str(g) + '.traj', mut_list_after_filter)
        with open(log_file, "a+") as fh:
            fh.write(
                f'Total clusters flitered out in  Generation {g}: {len(cm_pop) + len(population) - len(new_population)}'
                "\n")
            fh.write(
                f'Total clusters in the pool after filtering in Generation {g}: {len(new_population)}'
                "\n")

        fitnesses_pool = list(map(toolbox.evaluate, new_population))

        with open(log_file, "a+") as fh:
            fh.write(
                "Energies (fitnesses) of the present pool before best 10 are selected"
                "\n")
            for value in fitnesses_pool:
                fh.write("{} \n".format(value[0]))

        # Selecting the lowest energy npool clusters from the new_population
        len_new_pop = len(new_population)
        if len_new_pop > nPool:
            best_n_clus = tools.selWorst(new_population, nPool)
        else:
            best_n_clus = new_population

        best_n_clus_list = []
        for individual in best_n_clus:
            best_n_clus_list.append(individual[0])
        write('best_n_clus_after_gen' + str(g) + '.traj', best_n_clus_list)

        population = best_n_clus

        best_clus = tools.selWorst(population, 1)[0]
        with open(log_file, "a+") as fh:
            fh.write("{} {} \n".format("Lowest energy for this generation is",
                                       best_clus.fitness.values[0]))
            fh.write("\n Best cluster in this generation: \n")
            for atom in best_clus[0]:
                fh.write("{} {:12.8f} {:12.8f} {:12.8f} \n".format(
                    atom.symbol, atom.x, atom.y, atom.z))
            fh.write("\n")

        bi.append(best_clus[0])
        if g == 1:
            writer = TrajectoryWriter(filename + "_best.traj",
                                      mode="w",
                                      atoms=best_clus[0])
            writer.write()
        else:
            writer = TrajectoryWriter(filename + "_best.traj",
                                      mode="a",
                                      atoms=best_clus[0])
            writer.write()

    final_pop_db = ase.db.connect("final_pop_{}.db".format(filename))
    for clus in population:
        write_to_db(final_pop_db, clus[0])

    with open(log_file, "a+") as fh:
        fh.write("Global Minimum after {} Generations \n".format(g))
        for atom in best_clus[0]:
            fh.write("{} {:12.8f} {:12.8f} {:12.8f} \n".format(
                atom.symbol, atom.x, atom.y, atom.z))
    # Return the list of best clusters in every generations and the overall best cluster
    return bi, best_clus[0]