示例#1
0
def generate_subgraphs(atomsobject, unwrap=True, get_edge=False):

    from nff.io.ase import AtomsBatch

    atoms = AtomsBatch(atomsobject)
    z, adj, dmat,  threshold = adjdistmat(atoms, unwrap=unwrap)
    box_len = torch.Tensor(np.diag(atoms.get_cell()))
    G = nx.from_numpy_matrix(adj)

    for i, item in enumerate(z):
        G.nodes[i]['z'] = item

    sub_graphs = nx.connected_component_subgraphs(G)

    edge_list = []
    partitions = []

    for i, sg in enumerate(sub_graphs):
        partitions.append(list(sg.nodes))
        if get_edge:
            edge_list.append(list(sg.edges))
    if len(edge_list) != 0:
        return partitions, edge_list
    else:
        return partitions
示例#2
0
def neural_neb_ase(reactantxyzfile,
                   productxyzfile,
                   nff_dir,
                   rxn_name,
                   steps=500,
                   n_images=24,
                   fmax=0.004,
                   isclimb=False):

    #reactant and products as ase Atoms
    initial = AtomsBatch(xyz_to_ase_atoms(reactantxyzfile),
                         cutoff=5.5,
                         nbr_torch=True,
                         directed=True)

    final = AtomsBatch(xyz_to_ase_atoms(productxyzfile),
                       cutoff=5.5,
                       nbr_torch=True,
                       directed=True)

    # Make a band consisting of n_images:
    images = [initial]
    images += [initial.copy() for i in range(n_images)]
    images += [final]
    neb = SingleCalculatorNEB(images, k=0.02, climb=isclimb)
    neb.method = 'improvedtangent'

    # Interpolate linearly the potisions of the n_images:
    neb.interpolate()
    neb.idpp_interpolate(optimizer=BFGS, steps=steps)

    images = read('idpp.traj@-{}:'.format(str(n_images + 2)))

    # # Set calculators:
    nff_ase = NeuralFF.from_file(nff_dir, device='cuda:0')
    neb.set_calculators(nff_ase)

    # # Optimize:
    optimizer = BFGS(neb, trajectory='{}/{}.traj'.format(nff_dir, rxn_name))
    optimizer.run(fmax=fmax, steps=steps)

    # Read NEB images from File
    images = read('{}/{}.traj@-{}:'.format(nff_dir, rxn_name,
                                           str(n_images + 2)))

    return images
示例#3
0
    def _get_periodic_neighbor_list(self, cutoff, undirected=False):
        from nff.io.ase import AtomsBatch

        nbrlist = []
        offsets = []
        for nxyz, lattice in zip(self.props['nxyz'], self.props['lattice']):
            atoms = AtomsBatch(nxyz[:, 0].long(),
                               positions=nxyz[:, 1:],
                               cell=lattice,
                               pbc=True,
                               cutoff=cutoff)
            nbrs, offs = atoms.update_nbr_list()
            nbrlist.append(nbrs)
            offsets.append(offs)

        self.props['nbr_list'] = nbrlist
        self.props['offsets'] = offsets
        return
示例#4
0
def ev_run(ev_atoms,
           nff_dir,
           maxstepsize,
           maxstep,
           convergence,
           device,
           method='Powell'):
    rmslist = []
    maxlist = []

    nff = NeuralFF.from_file(nff_dir, device=device)

    for step in range(maxstep):
        if step == 0:
            xyz, grad, hessian, h = eigvec_following(ev_atoms, step,
                                                     maxstepsize, device,
                                                     method)
        else:
            xyz, grad, hessian, h = eigvec_following(ev_atoms, step,
                                                     maxstepsize, device,
                                                     method, hessian, grad, h)

        if step == 0:
            xyz_all = xyz
        else:
            xyz_all = torch.cat((xyz_all, xyz), dim=0)

        rmslist.append(grad.pow(2).sqrt().mean())
        maxlist.append(grad.pow(2).sqrt().max())
        print("RMS: {}, MAX: {}".format(
            grad.pow(2).sqrt().mean(),
            grad.pow(2).sqrt().max()))

        if grad.pow(2).sqrt().max() < convergence:
            print("Optimization converged!")
            break

        ev_atoms = Atoms(numbers=ev_atoms.numbers,
                         positions=xyz.reshape(-1, 3).cpu().numpy(),
                         pbc=False)

        ev_atoms = AtomsBatch(ev_atoms,
                              cutoff=5.5,
                              nbr_torch=True,
                              directed=True)

        ev_atoms.set_calculator(nff)

    return xyz, grad, xyz_all, rmslist, maxlist
示例#5
0
    def unwrap_xyz(self, mol_dic):
        """
        Unwrap molecular coordinates by displacing atoms by box vectors


        Args:
            mol_dic (dict): dictionary of nodes of each disconnected subgraphs
        """
        from nff.io.ase import AtomsBatch

        for i in range(len(self.props['nxyz'])):
            # makes atoms object

            atoms = AtomsBatch(positions=self.props['nxyz'][i][:, 1:4],
                               numbers=self.props['nxyz'][i][:, 0],
                               cell=self.props["cell"][i],
                               pbc=True)

            # recontruct coordinates based on subgraphs index
            if self.props['smiles']:
                mol_idx = mol_dic[self.props['smiles'][i]]
                atoms.set_positions(reconstruct_atoms(atoms, mol_idx))
                nxyz = atoms.get_nxyz()
            self.props['nxyz'][i] = torch.Tensor(nxyz)
示例#6
0
    def gen_bond_prior(self, cutoff, bond_len_dict=None):
        from nff.io.ase import AtomsBatch

        from nff.io.ase import AtomsBatch

        if not self.props:
            raise TypeError("the dataset has no data yet")

        bond_dict = {}
        bond_count_dict = {}
        mol_idx_dict = {}

        #---------This part can be simplified---------#
        for i in range(len(self.props['nxyz'])):
            z = self.props['nxyz'][i][:, 0]
            xyz = self.props['nxyz'][i][:, 1:4]

            # generate arguments for ase Atoms boject
            ase_param = {
                "numbers":
                z,
                "positions":
                xyz,
                "pbc":
                True,
                "cell":
                self.props['cell'][i] if 'cell' in self.props.keys() else None
            }

            atoms = Atoms(**ase_param)
            sys_name = self.props['smiles'][i]
            if sys_name not in bond_dict.keys():
                print(sys_name)
                i, j = neighbor_list("ij", atoms, DISTANCETHRESHOLDICT_Z)

                bond_list = torch.LongTensor(np.stack((i, j), axis=1)).tolist()
                bond_dict[sys_name] = bond_list

                # generate molecular graph
                # TODO: there is redundant code in generate_subgraphs
                subgraph_index = generate_subgraphs(atoms)
                mol_idx_dict[sys_name] = subgraph_index

        # generate topologies
        # TODO: include options to only generate bond topology
        self.generate_topologies(bond_dic=bond_dict)
        if 'cell' in self.props.keys():
            self.unwrap_xyz(mol_idx_dict)
        #---------This part can be simplified---------#

        # generate bond length dictionary if not given
        if not bond_len_dict:
            bond_len_dict = self.gen_bond_stats()

        # update bond len and offsets
        all_bond_len = []
        all_offsets = []
        all_nbr_list = []
        for i in range(len(self.props['nxyz'])):
            z = self.props['nxyz'][i][:, 0]
            xyz = self.props['nxyz'][i][:, 1:4]

            bond_list = self.props['bonds'][i]
            bond_type_list = torch.stack(
                (z[bond_list[:, 0]], z[bond_list[:, 1]])).t()
            bond_len_list = []
            for bond in bond_type_list:
                bond_type = tuple(torch.LongTensor(sorted(bond)).tolist())
                bond_len_list.append(bond_len_dict[bond_type])
            all_bond_len.append(torch.Tensor(bond_len_list).reshape(-1, 1))

            # update offsets
            ase_param = {
                "numbers": z,
                "positions": xyz,
                "pbc": True,
                "cutoff": cutoff,
                "cell":
                self.props['cell'][i] if 'cell' in self.props.keys() else None,
                "nbr_torch": False
            }

            # the coordinates have been unwrapped and try to results offsets
            atoms = AtomsBatch(**ase_param)
            atoms.update_nbr_list()
            all_offsets.append(atoms.offsets)
            all_nbr_list.append(atoms.nbr_list)

        # update
        self.props['bond_len'] = all_bond_len
        self.props['offsets'] = all_offsets
        self.props['nbr_list'] = all_nbr_list
        self._check_dictionary(deepcopy(self.props))