def test_apply(): natoms = 5 masses = np.ones(natoms) equivalency = np.array([ [1, 1, 0, 0, 0], [0, 0, 1, 1, 0], [0, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], ], dtype=np.int32) clusters = np.array([ [1, 0, 1, 0, 0], [0, 1, 0, 1, 0], [0, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], ], dtype=np.int32) mapping = Mapping(masses, equivalency) mapping.update_clusters(clusters) assert mapping.update_identities() groups = [ (0, 1), ] reduction = Reduction(groups) assert reduction.check_equivalence(mapping) groups = [ (0, 2), ] reduction = Reduction(groups) assert not reduction.check_equivalence(mapping)
def test_manual_computation_nonperiodic(): natoms = 47 masses = np.random.uniform(3, 10, size=(natoms, )) mapping = Mapping(masses) group_sizes = [19, 10, 1, 5, 12] clusters = np.zeros((natoms, natoms)) for i, size in enumerate(group_sizes): start = sum(group_sizes[:i]) end = start + size clusters[i, start:end] = 1 mapping.update_clusters(clusters) positions = np.random.uniform(-5, 5, size=(natoms, 3)) positions_com = mapping.apply(positions) # manual computation positions_com_manual = np.zeros(positions_com.shape) for i, group in enumerate(mapping): mass = np.sum(masses[np.array(group)]) for j in group: positions_com_manual[i, :] += positions[j, :] * masses[j] / mass assert np.allclose(positions_com, positions_com_manual) positions_com_ = mapping.apply(positions + 2.3) assert np.allclose(positions_com, positions_com_ - 2.3)
def test_equivalency_toy(): natoms = 10 masses = np.ones(natoms) equivalency = np.eye(natoms, dtype=np.int32) mapping = Mapping(masses, equivalency=equivalency) assert len(mapping.atom_types) == natoms equivalency[0, 1] = 1 with pytest.raises(AssertionError): mapping = Mapping(masses, equivalency=equivalency) equivalency[0, 1] = 0 equivalency[natoms - 1, natoms - 1] = 0 equivalency[natoms - 2, natoms - 1] = 1 mapping = Mapping(masses, equivalency) assert np.max(mapping.atom_types) == natoms - 2
def test_identities(): natoms = 4 masses = np.ones(natoms) equivalency = np.array([ [1, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0], ], dtype=np.int32) clusters = np.array([ [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0], ], dtype=np.int32) mapping = Mapping(masses, equivalency) clusters = np.array([ [1, 0, 0, 0], [0, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0], ], dtype=np.int32) mapping.update_clusters(clusters) assert not mapping.update_identities()
def test_score_uio(): harmonic, equivalencies = get_harmonic('uio66_ff') mapping = Mapping(harmonic.atoms.get_masses(), equivalencies) # contains reference values on the number of reductions as a function of # the maximum number of equivalent clusters to be considered cutoff = 4 tol = 1e-1 reductions = generate_reductions( mapping, harmonic, cutoff=cutoff, tol=tol, max_num_equiv_clusters=6, ) reduction = reductions[0] reduction.apply(mapping) masses = np.repeat(harmonic.atoms.get_masses(), 3) mass_matrix = 1 / np.sqrt(np.outer(masses, masses)) hessian_mw = mass_matrix * harmonic.hessian smap = score(mapping, hessian_mw=hessian_mw, temperature=300) smap_ = score(mapping, harmonic=harmonic, temperature=300) assert smap == smap_ assert smap > 0 # construct mapping that groups all atoms into same bead clusters = np.zeros((mapping.natoms, mapping.natoms), dtype=np.int32) clusters[0, :] = 1 mapping.update_clusters(clusters) mapping.update_identities() entropy = score(mapping, harmonic=harmonic, temperature=300) print(entropy)
def test_generate_uio(): harmonic, equivalencies = get_harmonic('uio66_ff') mapping = Mapping(harmonic.atoms.get_masses(), equivalencies) cutoff = 3.0 tol = 1e-1 environments, radii = generate_environments(mapping, harmonic, cutoff, tol) # check whether each cluster receives precisely one environment _all = [] for _, envs in environments.items(): for env in envs: _all.append(env.indices[0]) # get index of central atom assert np.allclose(np.sort(np.array(_all)), np.arange(mapping.nclusters)) # verify that envs of the same cluster_type are 'equal' # verify that each env generates the same number of templates for cluster_type, envs in environments.items(): reference = envs[0] templates = reference.generate_templates() n = len(templates) for env in envs: assert reference.equals(env, tol) assert len(env.generate_templates()) == n # discard those which cannot be matched uniquely i = 0 while i < len(templates): if len(reference.match_template(templates[i], tol)) > 1: templates.pop(i) else: i += 1 for env in envs: for template in templates: assert len(env.match_template(template, tol)) == 1
def test_uio(): harmonic, equivalencies = get_harmonic('uio66_ff') mapping = Mapping(harmonic.atoms.get_masses(), equivalencies) #write('test.xyz', harmonic.atoms) # contains reference values on the number of reductions as a function of # the maximum number of equivalent clusters to be considered cutoff = 4 tol = 1e-1 reductions = generate_reductions( mapping, harmonic, cutoff=cutoff, tol=tol, max_num_equiv_clusters=1, ) assert len(reductions) == 10 reductions = generate_reductions( mapping, harmonic, cutoff=cutoff, tol=tol, max_num_equiv_clusters=2, ) assert len(reductions) == 18 reductions = generate_reductions( mapping, harmonic, cutoff=cutoff, tol=tol, max_num_equiv_clusters=3, ) assert len(reductions) == 21 reductions = generate_reductions( mapping, harmonic, cutoff=cutoff, tol=tol, max_num_equiv_clusters=4, ) assert len(reductions) == 24 reductions = generate_reductions( mapping, harmonic, cutoff=cutoff, tol=tol, max_num_equiv_clusters=5, ) assert len(reductions) == 24 reductions = generate_reductions( mapping, harmonic, cutoff=cutoff, tol=tol, max_num_equiv_clusters=6, ) assert len(reductions) == 27
def test_write_load(tmp_path): harmonic, equivalencies = get_harmonic('uio66_ff') mapping = Mapping(harmonic.atoms.get_masses(), equivalencies) clusters = Mapping.merge( mapping.clusters, [(0, 1, 2, 5), (4, 8, 33, 6, 100)], ) mapping.update_clusters(clusters) mapping.update_identities(validate=True) path_npz = tmp_path / 'mapping.npz' mapping.write(path_npz) loaded = Mapping.load(path_npz) assert np.allclose(loaded.masses, mapping.masses) for i in range(mapping.natoms): assert loaded.atom_types[i] == mapping.atom_types[i] assert np.allclose(loaded.clusters, mapping.clusters)
def test_merge(): clusters = np.eye(5, dtype=np.int32) groups = [(0, 1, 2), (3, 4)] clusters_ = np.array([ [1, 1, 1, 0, 0], [0, 0, 0, 1, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], ], dtype=np.int32) assert np.allclose(clusters_, Mapping.merge(clusters, groups))
def test_generate_toy(): natoms = 3 mapping = Mapping(np.ones(natoms), np.eye(natoms)) atoms = ase.Atoms( numbers=np.ones(natoms), positions=np.array([[0, 0, 0], [1, 0, 0], [2, 0, 0]]), pbc=False, ) harmonic = Harmonic(atoms, np.ones((3 * natoms, 3 * natoms))) cutoff = 2.001 tol = 1e-2 envs, radii = generate_environments(mapping, harmonic, cutoff, tol) assert tuple(envs.keys()) == ((0, ), (1, ), (2, )) assert radii[(1, )] == cutoff - 2 * tol # radius at default value assert radii[(2, )] == radii[(0, )]
def test_project_toy(): natoms = 5 masses = np.ones(natoms) mapping = Mapping(masses) assert np.all(mapping.clusters == np.eye(natoms, dtype=np.int32)) assert mapping.nclusters == natoms assert np.all(mapping.deltas == np.zeros((natoms, natoms), dtype=np.int32)) assert np.all(mapping.transform == np.eye(natoms)) clusters = np.array( [ [1, 1, 0, 0, 0], # first group [0, 0, 1, 1, 1], # second group [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], ], dtype=np.int32) deltas = np.array([ [0, 0, 0, 0, 0], [-1, 1, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, -1, 1, 0], [0, 0, -1, 0, 1], ], dtype=np.int32) transform = np.array([ [1 / 2, 1 / 2, 0, 0, 0], [0, 0, 1 / 3, 1 / 3, 1 / 3], ]) mapping.update_clusters(clusters) assert np.all(mapping.clusters == clusters) assert np.all(mapping.deltas == deltas) assert np.allclose(mapping.transform, transform) # try updating corrupt clusters clusters = np.array( [ [1, 1, 0, 0, 0], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 1, 0, 0, 0], # atom 1 appears in cluster 0 and cluster 4 ], dtype=np.int32) with pytest.raises(AssertionError): mapping.update_clusters(clusters)
def test_template_toy(): natoms = 6 equivalencies = np.array([[1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]) mapping = Mapping(np.ones(natoms), equivalencies) atoms = ase.Atoms( numbers=np.ones(natoms), positions=np.array([[0, 0, 0], [1, 0, 0], [2, 0, 0], [3, 0, 0], [4, 0, 0], [5, 0, 0]]), pbc=False, ) harmonic = Harmonic(atoms, np.ones((3 * natoms, 3 * natoms))) cutoff = 6.5 tol = 1e-2 envs, radii = generate_environments(mapping, harmonic, cutoff, tol) assert tuple(envs.keys()) == ((0, ), (1, )) # only two cluster types assert len(envs[(0, )]) == 3 assert len(envs[(1, )]) == 3 env = envs[(0, )][0] templates = env.generate_templates() assert len(templates) == 7 + 3 templates = env.generate_templates(max_num_equiv_clusters=2) assert len(templates) == 3 + 3 templates = env.generate_templates(max_num_equiv_clusters=1) assert len(templates) == 1 + 1 # decrease cutoff cutoff = 4.1 tol = 1e-2 envs, radii = generate_environments(mapping, harmonic, cutoff, tol) assert tuple(envs.keys()) == ((0, ), (1, )) # only two cluster types assert len(envs[(0, )]) == 3 assert len(envs[(1, )]) == 3 env = envs[(0, )][0] # env for 0, 0, 0 position templates = env.generate_templates() assert len(templates) == 3 + 3 env = envs[(0, )][2] # env for 2, 0, 0 position templates = env.generate_templates() assert len(templates) == 3 + 7
def test_algorithm_uio(): harmonic, equivalencies = get_harmonic('uio66_ff') mapping = Mapping(harmonic.atoms.get_masses(), equivalencies) min_neighbors = 3 max_num_equiv_clusters = 6 temperature = 300 algorithm = Algorithm( harmonic, mapping, temperature, min_neighbors, max_num_equiv_clusters, ) cutoff = 4 tol = 1e-1 threshold = 450 # performs only one reduction step algorithm.run(threshold, cutoff, tol)