예제 #1
0
def test_H2():
    h2 = Atoms('H2', positions=[(0, 0, 0), (0, 0, 1)])
    nl = NeighborList([0.5, 0.5],
                      skin=0.1,
                      sorted=True,
                      self_interaction=False)
    nl2 = NeighborList([0.5, 0.5],
                       skin=0.1,
                       sorted=True,
                       self_interaction=False,
                       primitive=NewPrimitiveNeighborList)
    assert nl2.update(h2)
    assert nl.update(h2)
    assert not nl.update(h2)
    assert (nl.get_neighbors(0)[0] == [1]).all()
    m = np.zeros((2, 2))
    m[0, 1] = 1
    assert np.array_equal(nl.get_connectivity_matrix(sparse=False), m)
    assert np.array_equal(nl.get_connectivity_matrix(sparse=True).todense(), m)
    assert np.array_equal(nl.get_connectivity_matrix().todense(),
                          nl2.get_connectivity_matrix().todense())

    h2[1].z += 0.09
    assert not nl.update(h2)
    assert (nl.get_neighbors(0)[0] == [1]).all()

    h2[1].z += 0.09
    assert nl.update(h2)
    assert (nl.get_neighbors(0)[0] == []).all()
    assert nl.nupdates == 2
def test_neighborlist_initialization():

    atoms = bulk('Al', 'fcc', a=4)

    nl = NeighborList([8] * len(atoms), skin=0, self_interaction=False)
    with pytest.raises(Exception, match="Must call update"):
        nl.get_neighbors(0)

    with pytest.raises(Exception, match="Must call update"):
        nl.get_connectivity_matrix()

    nl.update(atoms)
    indices, offsets = nl.get_neighbors(0)
예제 #3
0
def ase_connectivity(atoms, cutoffs=None, count_bonds=True):
    """Return a connectivity matrix calculated of an atoms object.

    If no neighborlist or connectivity matrix is attached to the atoms object,
    a new one will be generated. Multiple connections are counted.

    Parameters
    ----------
    atoms : object
        An ase atoms object.
    cutoffs : list
        A list of cutoff radii for the atoms, ordered by atom index.

    Returns
    -------
    conn : array
        An n by n, where n is len(atoms).
    """
    if hasattr(atoms, 'neighborlist'):
        nl = atoms.neighborlist
    else:
        nl = NeighborList(cutoffs=cutoffs, bothways=True)
        nl.update(atoms)
        conn_mat = nl.get_connectivity_matrix(sparse=False)
        np.fill_diagonal(conn_mat, 0)

    return np.asarray(conn_mat, dtype=int)
예제 #4
0
def _get_neighbours(atoms, buffer_factor = 1.0,
    radii_dct ={'H': 0.37, 'C': 0.77, 'N': 0.75, 'O': 0.73,
               'F': 0.71, 'B': 0.88, 'P': 1.036, 'S': 1.02,
               'X': 0.77}, from_ase = True):
    """Helper function for place_and_preoptimize_adsorbates

    Args:
        atoms (ase.Atoms)   :   adsorbate molecule
        buffer_factor (float) : factor by which the atomic radii get scaled
        radii_dct (dict) :      atomic radii to determine neighbors. Is 
                                ignored if from_ase is True
        from_ase (bool) :   If set to True, ase makes an educated guess
                            of the neigbors using sensible atomic radii

    Returns:
        tuple :     list of neigbours (tuples of bond distances and pairs of atom indices),
                    ase.neighborlist.NeighborList object
    """
    cutoffs = _determine_cutoffs(atoms, buffer_factor=buffer_factor, radii_dct = radii_dct, from_ase = from_ase)
    nl = NeighborList(cutoffs=cutoffs, bothways=True, self_interaction=False, skin=0.0)
    nl.update(atoms)
    cmat = nl.get_connectivity_matrix(sparse=False)
    cmat = np.triu(cmat)
    nb_lst = np.transpose(np.nonzero(cmat))
    return nb_lst, nl
예제 #5
0
def find_molecules(struct, mult=1.05):
    """ 
    Identify molecular fragments in struct
    
    Returns
    -------
    List of lists for atom index of each molecule
    
    """
    atoms = struct.get_ase_atoms()
    cutOff = natural_cutoffs(atoms, mult=mult)
    ## Skin=0.3 is not a great parameter, but it seems to work pretty well
    ## for mulicule identification. In addition, it's not the same affect as
    ## change the mult value because it's a constant addition to all
    ## covalent bonds.
    neighborList = NeighborList(cutOff, skin=0.0)
    neighborList.update(atoms)
    matrix = neighborList.get_connectivity_matrix()
    n_components, component_list = sparse.csgraph.connected_components(matrix)
    molecule_list = [
        np.where(component_list == x)[0] for x in range(n_components)
    ]
    return molecule_list
예제 #6
0
파일: molecules.py 프로젝트: logsdail/carmm
def calculate_molecules(atoms, print_output=False):
    '''
    Returns information on the molecules in the system. Needs refinement!
    
    
    Parameters:
    atoms: Atoms object
        Input structure from which to calculate molecular information 
    print_output: Boolean 
        Whether to print any information whilst working out molecules

    Returns:
    molecules: List of list of integers
        Indices of atoms involved in each molecule
        can view individual molecules vis atoms[molecules[0]] ect
    '''

    from ase.neighborlist import natural_cutoffs, NeighborList
    from scipy import sparse

    cutOff = natural_cutoffs(atoms)
    neighborList = NeighborList(cutOff, self_interaction=False, bothways=True)
    neighborList.update(atoms)
    matrix = neighborList.get_connectivity_matrix()
    n_molecules, component_list = sparse.csgraph.connected_components(matrix)

    molecules = []
    for n in range(n_molecules):
        atomsIdxs = [
            i for i in range(len(component_list)) if component_list[i] == n
        ]
        molecules.append(atomsIdxs)
        if (print_output):
            print("The following atoms are part of molecule {}: {}".format(
                n, atomsIdxs))

    return molecules
예제 #7
0
def process_image(image_number):

    traj = Trajectory(traj_file)

    Trajectory_Fragments = []
    Trajectory_Fragments_for_view = []

    atoms = traj[image_number]

    syms = atoms.get_chemical_symbols()

    cutoff_dict = {'Al': 1, 'Cl': 1.7, 'H': .37, 'O': 1, 'N': 1, 'C': 1}

    cutoffs = [cutoff_dict[s.symbol] for s in atoms]

    nl = NeighborList(cutoffs, skin=0, self_interaction=False, bothways=False)
    nl.update(atoms)
    mat = nl.get_connectivity_matrix(sparse=False)
    Cl_indices = np.array([a.index for a in atoms if a.symbol == 'Cl'])
    for i in Cl_indices:
        for j in range(len(atoms)):
            if syms[j] != 'Al':
                mat[i, j] = 0
                mat[j, i] = 0
 
    n_components, component_list = sparse.csgraph.connected_components(mat)
 
    All_fragments = []
    All_fragments_for_view = []
    for i in range(n_components):
    #   view(atoms[np.where(component_list == i)[0]])

        fragments_for_view = atoms[np.where(component_list == i)[0]]
        fragments = atoms[np.where(component_list == i)[0]].get_chemical_formula()
    
        All_fragments.append(fragments)
        All_fragments_for_view.append(fragments_for_view)
 
    Trajectory_Fragments.append(All_fragments)
    Trajectory_Fragments_for_view.append(All_fragments_for_view)

    dict_fragments = Counter(All_fragments)


    # N-Dimensional list of lists -> 1D list, so that counter works properly!
    flat_Trajectory_Fragments = [item for sublist in Trajectory_Fragments for item in sublist]
    flat_Trajectory_Fragments_for_view = [item for sublist in Trajectory_Fragments_for_view for item in sublist]

    # to remove duplicates:
    from collections import defaultdict
    formula_dct = defaultdict(list)
    All_chemical_formula_in_flat_Trajectory_Fragments_for_view = []
    for i in flat_Trajectory_Fragments_for_view:
        chemical_formula_in_flat_Trajectory_Fragments_for_view = i.get_chemical_formula()
        formula_dct[chemical_formula_in_flat_Trajectory_Fragments_for_view].append(i)
        All_chemical_formula_in_flat_Trajectory_Fragments_for_view.append(chemical_formula_in_flat_Trajectory_Fragments_for_view)

    """Save a trajectory of the fragments:  """
#   for formula, images in formula_dct.items():
#       traj = Trajectory(formula + ".traj", mode="w")
#       for img in images:
#           traj.write(img)

    u, indices = np.unique(All_chemical_formula_in_flat_Trajectory_Fragments_for_view, return_index=True)

    res_list = [flat_Trajectory_Fragments_for_view[i] for i in indices] 

    """Save a database:  """
#   if os.path.exists("./species.db"):
#       os.remove("./species.db")
#   else:
#       print('File does not exists')

#   outdb = connect('./species.db')
#   for i in res_list:
#       print ('i to view = ', i.get_chemical_formula())
#       outdb.write(i)
  
    """
    to show an overview of the database: 'ase db species.db'
    to view a fragment of the database:  'ase gui species.db@<id>'
    to show complete list: 'ase db species.db  --limit=0'
    """
    """ partition the trajectory:
        `ase convert R3-R19.traj@:1000 -o 1ps.traj`
        from t=209fs to t=210fs: `ase convert -n 209:211 R3-R19.traj   209-210ps.traj`
    """


    dict_Trajectory_Fragments = Counter(flat_Trajectory_Fragments)

    f = open('molecules_found.dat.%d' % image_number, 'w')
    total_fragments = sum(dict_Trajectory_Fragments.values())
    for chemical_symbol, number in sorted(dict_Trajectory_Fragments.items(), reverse=True, key=lambda item: item[1]):
         print("{:>15} = {:>2}  {:3.20f} %".format(chemical_symbol, number, (number/total_fragments)*100.), file=f)
    f.close()
    return dict_Trajectory_Fragments
예제 #8
0
class Detect(object):
    def __init__(self, traj, cutoff_dict,
                 saved_components_file=f"components_traj_{traj_name}.npz"):
        atoms = traj[0]
        self.cutoffs = [cutoff_dict[s.symbol] for s in atoms]
        self.save_file = saved_components_file
        self.syms = atoms.get_chemical_symbols()
        self.Cl_indices = np.array(
            [a.index for a in atoms if a.symbol == 'Cl'])
        self.Al_indices = np.array(
            [a.index for a in atoms if a.symbol == 'Al'])

        self.nl = NeighborList(self.cutoffs, skin=0,
                               self_interaction=False, bothways=True)

        self.initial_components = None
        self.traj = [a for a in traj]
        self.atoms = atoms
        self.molecule_information = {}
        self.open_reactions = {}
        self.closed_reactions = []
        self.reaction_indices = []
        self.distinct_indices = []
        self.distinct_strings = []
        self.distinct_counts = []
        self.broken_bonds = []

        self._initialize(atoms)
        self.parse_trajectory()

    def _initialize(self, atoms):
        cl = self.get_component_list(atoms)[0]
        self.initial_components = cl

        for Al_idx in self.Al_indices:
            fragment = self.get_fragment(Al_idx, cl)
            self.molecule_information[Al_idx] = [
                (0, self.get_formula(fragment))]

    def parse_trajectory(self):
        if os.path.isfile(self.save_file) and os.stat(self.save_file).st_size > 0:
            components, matrices = load_components_file(self.save_file)
            self.traj_components = components
            self.connectivity_matrices = matrices
        else:
            pool = multiprocessing.Pool(processes=24)
            pm = pool.map(self.get_component_list, self.traj)
            pool.close()
            pool.join()

            components, matrices = zip(*pm)

            self.traj_components = components
            self.connectivity_matrices = matrices
            save_components_file(self.save_file, components, matrices)

    def get_fragment(self, idx, component_list):
        return np.where(component_list == component_list[idx])[0]

    def get_formula(self, fragment):
        if self.atoms[fragment].get_chemical_formula() in dict_labels:
            return dict_labels[self.atoms[fragment].get_chemical_formula()]
        else:
            return self.atoms[fragment].get_chemical_formula()

    def get_component_list(self, atoms):
        self.nl.update(atoms)
        mat = self.nl.get_connectivity_matrix(sparse=False)

        for i in self.Cl_indices:
            for j in range(len(atoms)):
                if self.syms[j] != 'Al':
                    mat[i, j] = 0
                    mat[j, i] = 0

        return sparse.csgraph.connected_components(mat)[1], mat


    # for the visualization of the reaction:  
    def get_reaction(self, time, all_reaction_indices): #, bond):
        traj_file2 = f"{time}fs__bonds.traj"
        traj2 = Trajectory(traj_file2, 'w')

        initial = 0

        # Processing image = initial = 0:
        for i, image in enumerate(self.traj[:initial+1]):
            sub = image[all_reaction_indices]

            L1 = sub.get_cell()[0]
            L2 = sub.get_cell()[1]
            L3 = sub.get_cell()[2]

            center = 0.5 * (L1 + L2 + L3)
            dist_cum = np.zeros(len(sub))
            for j in range(len(sub)):
                pos_atom0 = sub.get_positions()[j]
                V = pos_atom0 - center
                sub.set_positions(sub.get_positions() - V)
                sub.wrap()
                for k in range(len(sub)):
                    if k != j:
                        C1 = L1/np.linalg.norm(L1)**2
                        C2 = L2/np.linalg.norm(L2)**2
                        C3 = L3/np.linalg.norm(L3)**2
                        vec = sub.get_positions()[k] - center
                        test = [np.abs(np.dot(vec,C1)), np.abs(np.dot(vec,C2)), np.abs(np.dot(vec,C3))]
                        num=np.amax(test)
                        if num > dist_cum[j]:
                            dist_cum[j]= num
            minimum=np.argmin(dist_cum)

            # using this minimum in image = initial = 0: In principle this is not needed
            sub = image[all_reaction_indices]
            pos_atom0 = sub.get_positions()[minimum]
            V = pos_atom0 - center
            sub.set_positions(sub.get_positions() - V)
            sub.wrap()


        # Processing all images: # restricting the visualization to the interval where reaction occurs:
        intial = time-70
        final = time+100
#       final = len(self.traj)
        for i, image in enumerate(self.traj[initial+1:final+1]):
            sub2 = image[all_reaction_indices]
            for s in range(len(sub2)):
                dist = 1000
                stat = sub2.get_positions()[s]
                for h in [-1,0,1]:
                    for j in [-1,0,1]:
                        for k in [-1,0,1]:
                            tras =  sub2.get_positions()[s] - V
                            pos = tras + h*L1 + j*L2 + k*L3
                            curr_dist = np.linalg.norm(pos-sub.get_positions()[s])
                            if curr_dist < dist :
                                dist = curr_dist
                                stat = pos
                sub2[s].position = stat
            traj2.write(sub2)



    def follow(self):
        previous_components = self.initial_components
#       All_counts = []
#       All_distinct_R = []
#       All_distinct_s_R = []
#       All_distinct_P = []
#       All_distinct_s_P = []
        for count, component_list in enumerate(self.traj_components):
            diff = component_list - previous_components
            if any(diff):
                print('Reaction took place at', count)

                reactant_dict = {}
                for Al_idx in self.Al_indices:
                    fragment = self.get_fragment(
                        Al_idx, previous_components)
                    reactant_dict[Al_idx] = (
                        self.get_formula(fragment), fragment)

                product_dict = {}
                for Al_idx in self.Al_indices:
                    fragment = self.get_fragment(Al_idx, component_list)
                    product_dict[Al_idx] = (
                        self.get_formula(fragment), fragment)

                reacted_idx = []
                reactants = []
                products = []
                all_indices_of_reaction = set()
                all_indx_R = []
                all_indx_P = []
                for Al_idx in self.Al_indices:
                    reac = reactant_dict[Al_idx][0]
                    prod = product_dict[Al_idx][0]
                    if reac != prod:
                        print(Al_idx, f'changed from {reac} to {prod}')
                        self.molecule_information[Al_idx].append((count, prod))
                        reactants.append(reac)
                        products.append(prod)
                        reacted_idx.append(Al_idx)
                        # Add the indices from the fragment belonging
                        # to this Al index to all the indices of all
                        # the fragments in this reaction
                        all_indices_of_reaction |= set(
                            reactant_dict[Al_idx][1])

                        alla_R = reactant_dict[Al_idx]#[1]
                        all_indx_R.append(alla_R)

                        alla_P = product_dict[Al_idx]#[1]
                        all_indx_P.append(alla_P)
#                       print ('alla R = ', alla_R)
#                       print ('alla P = ', alla_P)
                        all_indices_of_reaction |= set(product_dict[Al_idx][1])
                all_reaction_idx = sorted(all_indices_of_reaction)
                print('All indices of this reaction: ',
                      all_reaction_idx)
#               print ('all_indices_of_reaction_R = ', all_indx_R)
#               print ('all_indices_of_reaction_P = ', all_indx_P)

                np.set_printoptions(threshold=sys.maxsize) # print all np arrays

################### specific indices for reactants : distinct_R
#                   specific reactants string: distinct_s_R. for strings you may have same formula for two different array indices, so:
                ns_R = [i[1] for i in all_indx_R]

                distinct_R_strs_indx = list()
                distinct_R = list()
                for indx_M, M in enumerate(ns_R):
                    if any(np.array_equal(M, N) for N in distinct_R):
                        continue
                    distinct_R.append(M)
                    distinct_R_strs_indx.append(indx_M)
                print ('distinct indices Reactants = ', distinct_R)

                distinct_s_R = [all_indx_R[j][0] for j in distinct_R_strs_indx]
                print ('distinct strings Reactants = ', distinct_s_R)


################### specific indices for products:
#                   specific products string: distinct_s_P:

                ns_P = [i[1] for i in all_indx_P]

                distinct_P_strs_indx = list()
                distinct_P = list()
                for indx_M, M in enumerate(ns_P):
                    if any(np.array_equal(M, N) for N in distinct_P):
                        continue
                    distinct_P.append(M)
                    distinct_P_strs_indx.append(indx_M)
                print ('distinct indices Products = ', distinct_P)

                distinct_s_P = [all_indx_P[j][0] for j in distinct_P_strs_indx]
                print ('distinct strings Products = ', distinct_s_P)

                cm = self.connectivity_matrices

#               np.set_printoptions(threshold=sys.maxsize)

                diff_cm = cm[count] - cm[count - 1]

                # Is diff_cm symmetric ?
                # diff_cm is symmetric if all elements of (diff_cm - diff_cm.T) are zero. (T=transpose)
                # If not, the matrix is not symmetric.
                if not np.all(diff_cm - diff_cm.T == 0):
                    print(f"diff_cm between {count}fs and {count -1}fs is not symmetric. Either cm[count] or cm[count- 1], of both, are non symmetric. Use bothways=True")
                    sys.exit()

#               broken_indices = np.ravel(np.where(diff_cm < 0))
                # which indices are broken in the lower trianguar of diff_cm ?
                broken_indices = np.argwhere(np.tril(diff_cm) < 0)
                print('The bond between the following indices broke: ',
                      broken_indices)

#               broken_indices_vis = [[all_reaction_idx.index(i) for i in elmt]\
#                                     for elmt in broken_indices] # sometimes breaks. commented
#               print('.... for visualization: ',
#                     broken_indices_vis)

#               formed_indices = np.ravel(np.where(diff_cm > 0))
                # which indices are broken in the lower trianguar of diff_cm ?
                formed_indices = np.argwhere(np.tril(diff_cm) > 0)
                print('The bond between the following indices formed: ',
                      formed_indices)

#               formed_indices_vis = [[all_reaction_idx.index(i) for i in elmt]\
#                                     for elmt in formed_indices] # sometimes breaks. commented.
#               print('.... for visualization: ',
#                     formed_indices_vis)

                # Save the time of reaction, all indices and broken
                # indices to easier process the specific reaction
                # later
                self.reaction_indices.append((count, all_reaction_idx,
                                              broken_indices, formed_indices))
                self.distinct_indices.append((distinct_R, distinct_P)) 
                self.distinct_strings.append((distinct_s_R, distinct_s_P)) 
                self.distinct_counts.append((count)) 
                # visualize the reaction (expensive part):
#               self.get_reaction(count, all_reaction_idx) #, broken_indices)

                reactant_str = ', '.join(sorted(list(set(reactants))))
                product_str = ', '.join(sorted(list(set(products))))
                reaction_str = f'{reactant_str} -> {product_str}'
                opposite_reaction = f'{product_str} -> {reactant_str}'
                # A reaction should be identified by both Aluminium
                # indices and reaction species.
                reacts = tuple(reacted_idx + [opposite_reaction])
#               print ('self.open_reactions.keys() = ', self.open_reactions.keys())
#               print ('self.open_reactions  = ', self.open_reactions)
#               print ('reacts = ', reacts)
#               print ('self.reaction_indices = ', self.reaction_indices)
                if reacts in self.open_reactions.keys():
                    # It is now a closed reaction!?!
                    lifetime = count - self.open_reactions[reacts][0]
                    tot_reaction_str = opposite_reaction + ' -> ' + \
                        reaction_str.split(' -> ')[-1]

                    lst = [i[0] for i in self.reaction_indices]
                    indx = lst.index(self.open_reactions[reacts][0])

################### BEGIN calculating distances for closed reactions, parallelized:
                    iterable = self.traj[self.open_reactions[reacts][0]-1 : count+1]
                    pool = multiprocessing.Pool()

                    broken_past = self.reaction_indices[indx][2]
                    if np.array_equal(broken_past, formed_indices):
                        if formed_indices.size != 0 :
                            max_fr_v = []
                            min_fr_v = []
                            func = partial(calculate_distances, formed_indices)
                            res = pool.map(func, iterable)

                            pool.close()
                            pool.join()
                            for i in range(np.shape(res)[1]):
                                aux_max = max([row[i] for row in res])
                                aux_min = min([row[i] for row in res])
                                max_fr_v.append(aux_max)
                                min_fr_v.append(aux_min)
                            max_br = max_fr_v
                            min_br = min_fr_v
                        else:
                            max_fr_v = []
                            min_fr_v = []
                            max_br = max_fr_v
                            min_br = min_fr_v


                    if not np.array_equal(broken_past, formed_indices):
                        print ("broken_past and formed_indices are different")
                        if formed_indices.size != 0:
                            max_fr_v = []
                            min_fr_v = []
                            all_res = []
                            for image in iterable:
                                res = [image.get_distance(row[0], row[1], mic=True) \
                                       for row in formed_indices]
                                all_res.append(res)

                            for i in range(np.shape(all_res)[1]):
                                aux_max = max([row[i] for row in all_res])
                                aux_min = min([row[i] for row in all_res])
                                max_fr_v.append(aux_max)
                                min_fr_v.append(aux_min)
                        if formed_indices.size == 0:
                            max_fr_v = []
                            min_fr_v = []

                        if broken_past.size != 0:
                            max_br = []
                            min_br = []
                            all_res = []
                            for image in iterable:
                                res = [image.get_distance(row[0], row[1], mic=True) \
                                       for row in broken_past]
                                all_res.append(res)

                            for i in range(np.shape(all_res)[1]):
                                aux_max = max([row[i] for row in all_res])
                                aux_min = min([row[i] for row in all_res])
                                max_br.append(aux_max)
                                min_br.append(aux_min)
                        if broken_past.size == 0:
                            max_br = []
                            min_br = []

                    formed_past = self.reaction_indices[indx][3]
                    if np.array_equal(formed_past, broken_indices):
                        if broken_indices.size != 0 :
                            max_br_v = []
                            min_br_v = []
                            func = partial(calculate_distances, broken_indices)
                            res = pool.map(func, iterable)

                            pool.close()
                            pool.join()
                            for i in range(np.shape(res)[1]):
                                aux_max = max([row[i] for row in res])
                                aux_min = min([row[i] for row in res])
                                max_br_v.append(aux_max)
                                min_br_v.append(aux_min)
                            max_fr = max_br_v
                            min_fr = min_br_v
                        else:
                            max_br_v = []
                            min_br_v = []
                            max_fr = max_br_v
                            min_fr = min_br_v

                    if not np.array_equal(formed_past, broken_indices):
                        print ("formed_past and broken_indices are different")
                        if broken_indices.size != 0:
                            max_br_v = []
                            min_br_v = []
                            all_res = []
                            for image in iterable:
                                res = [image.get_distance(row[0], row[1], mic=True) \
                                       for row in broken_indices]
                                all_res.append(res)

                            for i in range(np.shape(all_res)[1]):
                                aux_max = max([row[i] for row in all_res])
                                aux_min = min([row[i] for row in all_res])
                                max_br_v.append(aux_max)
                                min_br_v.append(aux_min)
                        if broken_indices.size == 0:
                            max_br_v = []
                            min_br_v = []

                        if formed_past.size != 0:
                            max_fr = []
                            min_fr = []
                            all_res = []
                            for image in iterable:
                                res = [image.get_distance(row[0], row[1], mic=True) \
                                       for row in formed_past]
                                all_res.append(res)

                            for i in range(np.shape(all_res)[1]):
                                aux_max = max([row[i] for row in all_res])
                                aux_min = min([row[i] for row in all_res])
                                max_fr.append(aux_max)
                                min_fr.append(aux_min)
                        if formed_past.size == 0:
                            max_fr = []
                            min_fr = []

                    pool.close()
                    pool.join()
################### END calculating distances for closed reactions, parallelized.
                    self.closed_reactions.append(
                        (reacts[:-1], f'{tot_reaction_str}',\
                        f':: lifetime: {lifetime}',\
                        f'(from {self.open_reactions[reacts][0]} to {count})',\

                        f' At {self.open_reactions[reacts][0]} we have:',\
#                       f' ; distinct indices R = {self.distinct_indices[indx][0]}',\ # If we want parsing_closed.py module to work, these
#                       f' ; distinct indices P = {self.distinct_indices[indx][1]}',\ # two lines have to be commented (we dont need this info in the Closed_reactions huge array

                        f' ; broken indices = {self.reaction_indices[indx][2]}',\
                        f' ; formed indices = {self.reaction_indices[indx][3]}',\

                        f'Max distance between {self.reaction_indices[indx][2]}: {max_br}',\
                        f'Min distance between {self.reaction_indices[indx][2]}: {min_br}',\

                        f'Max distance between {self.reaction_indices[indx][3]}: {max_fr}',\
                        f'Min distance between {self.reaction_indices[indx][3]}: {min_fr}',\

                        f' At {count} we have:',\
#                       f' ; distinct indices R = {distinct_R}',\ # If we want parsing_closed.py module to work, these
#                       f' ; distinct indices P = {distinct_P}',\ # two lines have to be commented (we dont need this info in the Closed_reactions huge array

                        f' ; broken indices = {broken_indices}',\
                        f' ; formed indices = {formed_indices}',\

                        f'Max distance between {broken_indices}: {max_br_v}',\
                        f'Min distance between {broken_indices}: {min_br_v}',\

                        f'Max distance between {formed_indices}: {max_fr_v}',\
                        f'Min distance between {formed_indices}: {min_fr_v}',\

                         ))

                    self.open_reactions.pop(reacts)
#                   print ('self.open_reactions  = ', self.open_reactions)

                else:

################### BEGIN calculating distances for open reactions, parallelized:
                    iterable = self.traj[count-1:]
                    pool = multiprocessing.Pool()

                    max_br = []
                    min_br = []
                    if broken_indices.size != 0:
                        func = partial(calculate_distances, broken_indices)
                        res = pool.map(func, iterable)

                        for i in range(np.shape(res)[1]):
                            aux_max = max([row[i] for row in res])
                            aux_min = min([row[i] for row in res])
                            max_br.append(aux_max)
                            min_br.append(aux_min)


                    max_fr = []
                    min_fr = []
                    if formed_indices.size != 0:
                        func = partial(calculate_distances, formed_indices)
                        res = pool.map(func, iterable)

                        for i in range(np.shape(res)[1]):
                            aux_max = max([row[i] for row in res])
                            aux_min = min([row[i] for row in res])
                            max_fr.append(aux_max)
                            min_fr.append(aux_min)
################### END calculating distances for open reactions, parallelized:


                    # key is Al_idx and forward reaction
                    # when checking for a closed reaction we need to
                    # use the backward/opposite reaction
                    self.open_reactions[tuple (
                        reacted_idx + [reaction_str])] = (count,\
                        f'broken indices = {broken_indices}',\

#                       f' ; distinct indices R = {distinct_R}',\ # If we want parsing_open.py module to work, these
#                       f' ; distinct indices P = {distinct_P}',\ # two lines have to be commented (we dont need this info in the Open_reactions huge array

                        f'Max distance between {broken_indices}: {max_br}',\
                        f'Min distance between {broken_indices}: {min_br}',\

                        f'formed indices = {formed_indices}',\

                        f'Max distance between {formed_indices}: {max_fr}',\
                        f'Min distance between {formed_indices}: {min_fr}')

                    pool.close()  # uncomment these two if distance is calculated.
                    pool.join()

            previous_components = component_list
예제 #9
0
                assert not (c2 - c).any()

h2 = Atoms('H2', positions=[(0, 0, 0), (0, 0, 1)])
nl = NeighborList([0.5, 0.5], skin=0.1, sorted=True, self_interaction=False)
nl2 = NeighborList([0.5, 0.5],
                   skin=0.1,
                   sorted=True,
                   self_interaction=False,
                   primitive=NewPrimitiveNeighborList)
assert nl2.update(h2)
assert nl.update(h2)
assert not nl.update(h2)
assert (nl.get_neighbors(0)[0] == [1]).all()
m = np.zeros((2, 2))
m[0, 1] = 1
assert np.array_equal(nl.get_connectivity_matrix(sparse=False), m)
assert np.array_equal(nl.get_connectivity_matrix(sparse=True).todense(), m)
assert np.array_equal(nl.get_connectivity_matrix().todense(),
                      nl2.get_connectivity_matrix().todense())

h2[1].z += 0.09
assert not nl.update(h2)
assert (nl.get_neighbors(0)[0] == [1]).all()

h2[1].z += 0.09
assert nl.update(h2)
assert (nl.get_neighbors(0)[0] == []).all()
assert nl.nupdates == 2

h2 = Atoms('H2', positions=[(0, 0, 0), (0, 0, 1)])
nl = NeighborList([0.1, 0.1], skin=0.1, bothways=True, self_interaction=False)
예제 #10
0
def test_neighbor():
    atoms = Atoms(numbers=range(10),
                  cell=[(0.2, 1.2, 1.4), (1.4, 0.1, 1.6), (1.3, 2.0, -0.1)])
    atoms.set_scaled_positions(3 * random.random((10, 3)) - 1)

    for sorted in [False, True]:
        for p1 in range(2):
            for p2 in range(2):
                for p3 in range(2):
                    # print(p1, p2, p3)
                    atoms.set_pbc((p1, p2, p3))
                    nl = NeighborList(atoms.numbers * 0.2 + 0.5,
                                      skin=0.0,
                                      sorted=sorted)
                    nl.update(atoms)
                    d, c = count(nl, atoms)
                    atoms2 = atoms.repeat((p1 + 1, p2 + 1, p3 + 1))
                    nl2 = NeighborList(atoms2.numbers * 0.2 + 0.5,
                                       skin=0.0,
                                       sorted=sorted)
                    nl2.update(atoms2)
                    d2, c2 = count(nl2, atoms2)
                    c2.shape = (-1, 10)
                    dd = d * (p1 + 1) * (p2 + 1) * (p3 + 1) - d2
                    assert abs(dd) < 1e-10
                    assert not (c2 - c).any()

    h2 = Atoms('H2', positions=[(0, 0, 0), (0, 0, 1)])
    nl = NeighborList([0.5, 0.5],
                      skin=0.1,
                      sorted=True,
                      self_interaction=False)
    nl2 = NeighborList([0.5, 0.5],
                       skin=0.1,
                       sorted=True,
                       self_interaction=False,
                       primitive=NewPrimitiveNeighborList)
    assert nl2.update(h2)
    assert nl.update(h2)
    assert not nl.update(h2)
    assert (nl.get_neighbors(0)[0] == [1]).all()
    m = np.zeros((2, 2))
    m[0, 1] = 1
    assert np.array_equal(nl.get_connectivity_matrix(sparse=False), m)
    assert np.array_equal(nl.get_connectivity_matrix(sparse=True).todense(), m)
    assert np.array_equal(nl.get_connectivity_matrix().todense(),
                          nl2.get_connectivity_matrix().todense())

    h2[1].z += 0.09
    assert not nl.update(h2)
    assert (nl.get_neighbors(0)[0] == [1]).all()

    h2[1].z += 0.09
    assert nl.update(h2)
    assert (nl.get_neighbors(0)[0] == []).all()
    assert nl.nupdates == 2

    h2 = Atoms('H2', positions=[(0, 0, 0), (0, 0, 1)])
    nl = NeighborList([0.1, 0.1],
                      skin=0.1,
                      bothways=True,
                      self_interaction=False)
    assert nl.update(h2)
    assert nl.get_neighbors(0)[1].shape == (0, 3)
    assert nl.get_neighbors(0)[1].dtype == int

    x = bulk('X', 'fcc', a=2**0.5)

    nl = NeighborList([0.5], skin=0.01, bothways=True, self_interaction=False)
    nl.update(x)
    assert len(nl.get_neighbors(0)[0]) == 12

    nl = NeighborList([0.5] * 27,
                      skin=0.01,
                      bothways=True,
                      self_interaction=False)
    nl.update(x * (3, 3, 3))
    for a in range(27):
        assert len(nl.get_neighbors(a)[0]) == 12
    assert not np.any(nl.get_neighbors(13)[1])

    c = 0.0058
    for NeighborListClass in [PrimitiveNeighborList, NewPrimitiveNeighborList]:
        nl = NeighborListClass([c, c],
                               skin=0.0,
                               sorted=True,
                               self_interaction=False,
                               use_scaled_positions=True)
        nl.update([True, True, True],
                  np.eye(3) * 7.56, np.array([[0, 0, 0], [0, 0, 0.99875]]))
        n0, d0 = nl.get_neighbors(0)
        n1, d1 = nl.get_neighbors(1)
        # != is xor
        assert (np.all(n0 == [0]) and np.all(d0 == [0, 0, 1])) != \
            (np.all(n1 == [1]) and np.all(d1 == [0, 0, -1]))

    # Test empty neighbor list
    nl = PrimitiveNeighborList([])
    nl.update([True, True, True], np.eye(3) * 7.56, np.zeros((0, 3)))

    # Test hexagonal cell and large cutoff
    pbc_c = np.array([True, True, True])
    cutoff_a = np.array([8.0, 8.0])
    cell_cv = np.array([[0., 3.37316113, 3.37316113],
                        [3.37316113, 0., 3.37316113],
                        [3.37316113, 3.37316113, 0.]])
    spos_ac = np.array([[0., 0., 0.], [0.25, 0.25, 0.25]])

    nl = PrimitiveNeighborList(cutoff_a,
                               skin=0.0,
                               sorted=True,
                               use_scaled_positions=True)
    nl2 = NewPrimitiveNeighborList(cutoff_a,
                                   skin=0.0,
                                   sorted=True,
                                   use_scaled_positions=True)
    nl.update(pbc_c, cell_cv, spos_ac)
    nl2.update(pbc_c, cell_cv, spos_ac)

    a0, offsets0 = nl.get_neighbors(0)
    b0 = np.zeros_like(a0)
    d0 = np.dot(spos_ac[a0] + offsets0 - spos_ac[0], cell_cv)
    a1, offsets1 = nl.get_neighbors(1)
    d1 = np.dot(spos_ac[a1] + offsets1 - spos_ac[1], cell_cv)
    b1 = np.ones_like(a1)

    a = np.concatenate([a0, a1])
    b = np.concatenate([b0, b1])
    d = np.concatenate([d0, d1])
    _a = np.concatenate([a, b])
    _b = np.concatenate([b, a])
    a = _a
    b = _b
    d = np.concatenate([d, -d])

    a0, offsets0 = nl2.get_neighbors(0)
    d0 = np.dot(spos_ac[a0] + offsets0 - spos_ac[0], cell_cv)
    b0 = np.zeros_like(a0)
    a1, offsets1 = nl2.get_neighbors(1)
    d1 = np.dot(spos_ac[a1] + offsets1 - spos_ac[1], cell_cv)
    b1 = np.ones_like(a1)

    a2 = np.concatenate([a0, a1])
    b2 = np.concatenate([b0, b1])
    d2 = np.concatenate([d0, d1])
    _a2 = np.concatenate([a2, b2])
    _b2 = np.concatenate([b2, a2])
    a2 = _a2
    b2 = _b2
    d2 = np.concatenate([d2, -d2])

    i = np.argsort(d[:, 0] + d[:, 1] * 1e2 + d[:, 2] * 1e4 + a * 1e6)
    i2 = np.argsort(d2[:, 0] + d2[:, 1] * 1e2 + d2[:, 2] * 1e4 + a2 * 1e6)

    assert np.all(a[i] == a2[i2])
    assert np.all(b[i] == b2[i2])
    assert np.allclose(d[i], d2[i2])