def test_fp_match(): for i in range(100): # Tests whether the generated fingerprints are consistent with that of AMPs atoms = molecule("H2O") atoms.set_cell([10, 10, 10]) atoms.set_pbc = [True] * 3 atoms.set_calculator( sp(atoms=atoms, energy=-1, forces=np.array([[-1, -1, -1], [-1, -1, -1]])) ) Gs = {} images = [atoms] Gs["G2_etas"] = [0.005] * 2 Gs["G2_rs_s"] = [0] * 2 Gs["G4_etas"] = [0.005] * 2 Gs["G4_zetas"] = [1.0, 4.0] Gs["G4_gammas"] = [1.0, -1.0] Gs["cutoff"] = 6.5 elements = list( sorted(set([atom.symbol for atoms in images for atom in atoms])) ) G = make_symmetry_functions(elements=elements, type="G2", etas=Gs["G2_etas"]) G += make_symmetry_functions( elements=elements, type="G4", etas=Gs["G4_etas"], zetas=Gs["G4_zetas"], gammas=Gs["G4_gammas"], ) G = {"O": G, "H": G} hashes = stock_hash(images) amp_hash = list(hashes.keys())[0] make_amp_descriptors_simple_nn(images, Gs, cores=1, label='test', elements=elements) s_nn_hash = list(new_hash(images, Gs).keys())[0] with open("amp-data-fingerprints.ampdb/loose/" + s_nn_hash, "rb") as f: simple_nn = load(f) os.system("rm amp-data-fingerprints.ampdb/loose/" + s_nn_hash) descriptor = Gaussian(elements=elements, Gs=G, cutoff=Cosine(Gs["cutoff"])) descriptor.calculate_fingerprints(hashes, calculate_derivatives=True) with open("amp-data-fingerprints.ampdb/loose/" + amp_hash, "rb") as f: amp = load(f) os.system("rm amp-data-fingerprints.ampdb/loose/" + amp_hash) for s, am in zip(simple_nn, amp): for i, j in zip(s[1], am[1]): assert abs(i - j) <= 1e-5, "Fingerprints do not match!"
def test(): """Gaussian fingerprints consistency. Tests that pure-python and fortran, plus different number of cores give same results. """ images = make_images() images = hash_images(images, ordered=True) ref_fps = {} ref_fp_primes = {} count = 0 for fortran in [False, True]: for cores in range(1, 2): descriptor = Gaussian(fortran=fortran, dblabel='Gaussian-%s-%d' % (fortran, cores)) descriptor.calculate_fingerprints(images, parallel={'cores': cores}, log=None, calculate_derivatives=True) for hash, image in images.items(): if count == 0: ref_fps[hash] = descriptor.fingerprints[hash] ref_fp_primes[hash] = descriptor.fingerprintprimes[hash] else: fps = descriptor.fingerprints[hash] # Checking consistency between fingerprints for (element1, afp1), \ (element2, afp2) in zip(ref_fps[hash], fps): assert element1 == element2, \ 'fortran-python consistency for Gaussian ' 'fingerprints broken!' for _, __ in zip(afp1, afp2): assert (abs(_ - __) < 10 ** (-15.)), \ 'fortran-python consistency for Gaussian ' 'fingerprints broken!' # Checking consistency between fingerprint primes fpprime = descriptor.fingerprintprimes[hash] for key, value in ref_fp_primes[hash].items(): for _, __ in zip(value, fpprime[key]): assert (abs(_ - __) < 10 ** (-15.)), \ 'fortran-python consistency for Gaussian ' 'fingerprint primes broken!' count += 1
def test_fp_match(): slab = fcc100("Cu", size=(3, 3, 3)) ads = molecule("CO") add_adsorbate(slab, ads, 4, offset=(1, 1)) cons = FixAtoms(indices=[ atom.index for atom in slab if (atom.tag == 2 or atom.tag == 3) ]) slab.set_constraint(cons) slab.center(vacuum=13.0, axis=2) slab.set_pbc(True) slab.wrap(pbc=[True] * 3) slab.set_calculator(EMT()) images = [slab] Gs = {} Gs["G2_etas"] = [2] Gs["G2_rs_s"] = [0] Gs["G4_etas"] = [0.005] Gs["G4_zetas"] = [1.0] Gs["G4_gammas"] = [1.0] Gs["cutoff"] = 6.5 elements = np.array([atom.symbol for atoms in images for atom in atoms]) _, idx = np.unique(elements, return_index=True) elements = list(elements[np.sort(idx)]) G = make_symmetry_functions(elements=elements, type="G2", etas=Gs["G2_etas"]) G += make_symmetry_functions( elements=elements, type="G4", etas=Gs["G4_etas"], zetas=Gs["G4_zetas"], gammas=Gs["G4_gammas"], ) G = {"O": G, "C": G, "Cu": G} hashes = stock_hash(images) snn_hashes = new_hash(images, Gs=Gs) AtomsDataset(images, SNN_Gaussian, Gs, forcetraining=True, label="test", cores=10) descriptor = Gaussian(elements=elements, Gs=G, cutoff=Gs["cutoff"], dblabel='amp') descriptor.calculate_fingerprints(hashes, calculate_derivatives=True) for idx in range(len(images)): amp_hash = list(hashes.keys())[idx] s_nn_hash = list(snn_hashes.keys())[idx] # SimpleNN with open("amp-data-fingerprints.ampdb/loose/" + s_nn_hash, "rb") as f: simple_nn = load(f) os.system("rm amp-data-fingerprints.ampdb/loose/" + s_nn_hash) with open("amp-data-fingerprint-primes.ampdb/loose/" + s_nn_hash, "rb") as f: simple_nn_prime = load(f) os.system("rm amp-data-fingerprint-primes.ampdb/loose/" + s_nn_hash) # AMP with open("amp-fingerprints.ampdb/loose/" + amp_hash, "rb") as f: amp = load(f) os.system("rm amp-fingerprints.ampdb/loose/" + amp_hash) with open("amp-fingerprint-primes.ampdb/loose/" + amp_hash, "rb") as f: amp_prime = load(f) os.system("rm amp-fingerprint-primes.ampdb/loose/" + amp_hash) key = amp_prime.keys() for s, am in zip(simple_nn, amp): for i, j in zip(s[1], am[1]): assert abs(i - j) <= 1e-4, "Fingerprints do not match! %s, %s" % ( i, j) for idx in key: for s, am in zip(simple_nn_prime[idx], amp_prime[idx]): assert abs(s - am) <= 1e-4, "Fingerprint primes do not match!"
def test_calcs(): """Gaussian/Neural non-periodic standard. Checks that the answer matches that expected from previous Mathematica calculations. """ #: Making the list of non-periodic images images = [ Atoms( symbols="PdOPd2", pbc=np.array([False, False, False], dtype=bool), calculator=EMT(), cell=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), positions=np.array([[0.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 3.0], [1.0, 0.0, 0.0]]), ), Atoms( symbols="PdOPd2", pbc=np.array([False, False, False], dtype=bool), calculator=EMT(), cell=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), positions=np.array([[0.0, 1.0, 0.0], [1.0, 2.0, 1.0], [-1.0, 1.0, 2.0], [1.0, 3.0, 2.0]]), ), Atoms( symbols="PdO", pbc=np.array([False, False, False], dtype=bool), calculator=EMT(), cell=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), positions=np.array([[2.0, 1.0, -1.0], [1.0, 2.0, 1.0]]), ), Atoms( symbols="Pd2O", pbc=np.array([False, False, False], dtype=bool), calculator=EMT(), cell=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), positions=np.array([[-2.0, -1.0, -1.0], [1.0, 2.0, 1.0], [3.0, 4.0, 4.0]]), ), Atoms( symbols="Cu", pbc=np.array([False, False, False], dtype=bool), calculator=EMT(), cell=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), positions=np.array([[0.0, 0.0, 0.0]]), ), ] [a.get_potential_energy() for a in images] # Parameters hiddenlayers = {"O": (2, ), "Pd": (2, ), "Cu": (2, )} Gs = {} Gs["G2_etas"] = [0.2] Gs["G2_rs_s"] = [0] Gs["G4_etas"] = [0.4] Gs["G4_zetas"] = [1] Gs["G4_gammas"] = [1] Gs["cutoff"] = 6.5 elements = ["O", "Pd", "Cu"] G = make_symmetry_functions(elements=elements, type="G2", etas=Gs["G2_etas"]) G += make_symmetry_functions( elements=elements, type="G4", etas=Gs["G4_etas"], zetas=Gs["G4_zetas"], gammas=Gs["G4_gammas"], ) hashed_images = hash_images(images, Gs) descriptor = Gaussian(Gs=G, cutoff=Gs["cutoff"]) descriptor.calculate_fingerprints(hashed_images, calculate_derivatives=True) fingerprints_range = calculate_fingerprints_range(descriptor, hashed_images) weights = OrderedDict([ ( "O", OrderedDict([ ( 1, np.array([ [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], ]), ), (2, np.matrix([[0.5], [0.5], [0.5]])), ]), ), ( "Pd", OrderedDict([ ( 1, np.array([ [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], ]), ), (2, np.array([[0.5], [0.5], [0.5]])), ]), ), ( "Cu", OrderedDict([ ( 1, np.array([ [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], ]), ), (2, np.array([[0.5], [0.5], [0.5]])), ]), ), ]) scalings = OrderedDict([ ("O", OrderedDict([("intercept", 0), ("slope", 1)])), ("Pd", OrderedDict([("intercept", 0), ("slope", 1)])), ("Cu", OrderedDict([("intercept", 0), ("slope", 1)])), ]) calc = Amp( descriptor, model=NeuralNetwork( hiddenlayers=hiddenlayers, weights=weights, scalings=scalings, activation="linear", fprange=fingerprints_range, mode="atom-centered", fortran=False, ), logging=False, ) amp_energies = [calc.get_potential_energy(image) for image in images] amp_forces = [calc.get_forces(image) for image in images] amp_forces = np.concatenate(amp_forces) device = "cpu" dataset = AtomsDataset(images, descriptor=DummyGaussian, cores=1, label='test', Gs=Gs, forcetraining=True) fp_length = dataset.fp_length batch_size = len(dataset) dataloader = DataLoader(dataset, batch_size, collate_fn=collate_amp, shuffle=False) model = FullNN(elements, [fp_length, 2, 2], device, forcetraining=True) for name, layer in model.named_modules(): if isinstance(layer, Dense): layer.activation = None init.constant_(layer.weight, 0.5) init.constant_(layer.bias, 0.5) for batch in dataloader: input_data = [batch[0], len(batch[1]), batch[3]] for element in elements: input_data[0][element][0] = ( input_data[0][element][0].to(device).requires_grad_(True)) fp_primes = batch[4] energy_pred, force_pred = model(input_data, fp_primes) for idx, i in enumerate(amp_energies): assert round(i, 4) == round( energy_pred.tolist()[idx][0], 4), "The predicted energy of image %i is wrong!" % (idx + 1) print("Energy predictions are correct!") for idx, sample in enumerate(amp_forces): for idx_d, value in enumerate(sample): predict = force_pred.tolist()[idx][idx_d] assert abs(value - predict) < 0.00001, ( "The predicted force of image % i, direction % i is wrong! Values: %s vs %s" % (idx + 1, idx_d, value, force_pred.tolist()[idx][idx_d])) print("Force predictions are correct!")
def test_calcs(): """Gaussian/Neural non-periodic standard. Checks that the answer matches that expected from previous Mathematica calculations. """ #: Making the list of non-periodic images images = [ Atoms( symbols="PdOPd2", pbc=np.array([False, False, False], dtype=bool), calculator=EMT(), cell=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), positions=np.array([[0.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 3.0], [1.0, 0.0, 0.0]]), ), Atoms( symbols="PdOPd2", pbc=np.array([False, False, False], dtype=bool), calculator=EMT(), cell=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), positions=np.array([[0.0, 1.0, 0.0], [1.0, 2.0, 1.0], [-1.0, 1.0, 2.0], [1.0, 3.0, 2.0]]), ), Atoms( symbols="PdO", pbc=np.array([False, False, False], dtype=bool), calculator=EMT(), cell=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), positions=np.array([[2.0, 1.0, -1.0], [1.0, 2.0, 1.0]]), ), Atoms( symbols="Pd2O", pbc=np.array([False, False, False], dtype=bool), calculator=EMT(), cell=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), positions=np.array([[-2.0, -1.0, -1.0], [1.0, 2.0, 1.0], [3.0, 4.0, 4.0]]), ), Atoms( symbols="Cu", pbc=np.array([False, False, False], dtype=bool), calculator=EMT(), cell=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), positions=np.array([[0.0, 0.0, 0.0]]), ), ] # Parameters hiddenlayers = {"O": (2, ), "Pd": (2, ), "Cu": (2, )} Gs = {} Gs["G2_etas"] = [0.2] Gs["G2_rs_s"] = [0] Gs["G4_etas"] = [0.4] Gs["G4_zetas"] = [1] Gs["G4_gammas"] = [1] Gs["cutoff"] = 6.5 elements = ["O", "Pd", "Cu"] G = make_symmetry_functions(elements=elements, type="G2", etas=Gs["G2_etas"]) G += make_symmetry_functions( elements=elements, type="G4", etas=Gs["G4_etas"], zetas=Gs["G4_zetas"], gammas=Gs["G4_gammas"], ) amp_images = amp_hash(images) descriptor = Gaussian(Gs=G, cutoff=Gs["cutoff"]) descriptor.calculate_fingerprints(amp_images, calculate_derivatives=True) fingerprints_range = calculate_fingerprints_range(descriptor, amp_images) np.random.seed(1) O_weights_1 = np.random.rand(10, 2) O_weights_2 = np.random.rand(1, 3).reshape(-1, 1) np.random.seed(2) Pd_weights_1 = np.random.rand(10, 2) Pd_weights_2 = np.random.rand(1, 3).reshape(-1, 1) np.random.seed(3) Cu_weights_1 = np.random.rand(10, 2) Cu_weights_2 = np.random.rand(1, 3).reshape(-1, 1) weights = OrderedDict([ ("O", OrderedDict([(1, O_weights_1), (2, O_weights_2)])), ("Pd", OrderedDict([(1, Pd_weights_1), (2, Pd_weights_2)])), ("Cu", OrderedDict([(1, Cu_weights_1), (2, Cu_weights_2)])), ]) scalings = OrderedDict([ ("O", OrderedDict([("intercept", 0), ("slope", 1)])), ("Pd", OrderedDict([("intercept", 0), ("slope", 1)])), ("Cu", OrderedDict([("intercept", 0), ("slope", 1)])), ]) calc = Amp( descriptor, model=NeuralNetwork( hiddenlayers=hiddenlayers, weights=weights, scalings=scalings, activation="tanh", fprange=fingerprints_range, mode="atom-centered", fortran=False, ), logging=False, ) amp_energies = [calc.get_potential_energy(image) for image in images] amp_forces = [calc.get_forces(image) for image in images] amp_forces = np.concatenate(amp_forces) torch_O_weights_1 = torch.FloatTensor(O_weights_1[:-1, :]).t() torch_O_bias_1 = torch.FloatTensor(O_weights_1[-1, :]) torch_O_weights_2 = torch.FloatTensor(O_weights_2[:-1, :]).t() torch_O_bias_2 = torch.FloatTensor(O_weights_2[-1, :]) torch_Pd_weights_1 = torch.FloatTensor(Pd_weights_1[:-1, :]).t() torch_Pd_bias_1 = torch.FloatTensor(Pd_weights_1[-1, :]) torch_Pd_weights_2 = torch.FloatTensor(Pd_weights_2[:-1, :]).t() torch_Pd_bias_2 = torch.FloatTensor(Pd_weights_2[-1, :]) torch_Cu_weights_1 = torch.FloatTensor(Cu_weights_1[:-1, :]).t() torch_Cu_bias_1 = torch.FloatTensor(Cu_weights_1[-1, :]) torch_Cu_weights_2 = torch.FloatTensor(Cu_weights_2[:-1, :]).t() torch_Cu_bias_2 = torch.FloatTensor(Cu_weights_2[-1, :]) device = "cpu" dataset = AtomsDataset( images, descriptor=Gaussian, cores=1, label="consistency", Gs=Gs, forcetraining=True, ) fp_length = dataset.fp_length batch_size = len(dataset) dataloader = DataLoader(dataset, batch_size, collate_fn=collate_amp, shuffle=False) model = FullNN(elements, [fp_length, 2, 2], device, forcetraining=True) model.state_dict()["elementwise_models.O.model_net.0.weight"].copy_( torch_O_weights_1) model.state_dict()["elementwise_models.O.model_net.0.bias"].copy_( torch_O_bias_1) model.state_dict()["elementwise_models.O.model_net.2.weight"].copy_( torch_O_weights_2) model.state_dict()["elementwise_models.O.model_net.2.bias"].copy_( torch_O_bias_2) model.state_dict()["elementwise_models.Pd.model_net.0.weight"].copy_( torch_Pd_weights_1) model.state_dict()["elementwise_models.Pd.model_net.0.bias"].copy_( torch_Pd_bias_1) model.state_dict()["elementwise_models.Pd.model_net.2.weight"].copy_( torch_Pd_weights_2) model.state_dict()["elementwise_models.Pd.model_net.2.bias"].copy_( torch_Pd_bias_2) model.state_dict()["elementwise_models.Cu.model_net.0.weight"].copy_( torch_Cu_weights_1) model.state_dict()["elementwise_models.Cu.model_net.0.bias"].copy_( torch_Cu_bias_1) model.state_dict()["elementwise_models.Cu.model_net.2.weight"].copy_( torch_Cu_weights_2) model.state_dict()["elementwise_models.Cu.model_net.2.bias"].copy_( torch_Cu_bias_2) import torch.nn as nn for name, layer in model.named_modules(): if isinstance(layer, MLP): layer.model_net = nn.Sequential(layer.model_net, Tanh()) for batch in dataloader: x = to_tensor(batch[0], device) y = to_tensor(batch[1], device) energy_pred, force_pred = model(x) for idx, i in enumerate(amp_energies): assert round(i, 4) == round( energy_pred.tolist()[idx][0], 4), "The predicted energy of image %i is wrong!" % (idx + 1) print("Energy predictions are correct!") for idx, sample in enumerate(amp_forces): for idx_d, value in enumerate(sample): predict = force_pred.tolist()[idx][idx_d] assert abs(value - predict) < 0.0001, ( "The predicted force of image % i, direction % i is wrong! Values: %s vs %s" % (idx + 1, idx_d, value, force_pred.tolist()[idx][idx_d])) print("Force predictions are correct!")
nn1_.rotate([0, 0, 1], ang1) nn2_ = nn2.copy() nn2_.rotate([0, 0, 1], ang2) nn2_.positions = nn2_.positions + np.array([3.0, 0.0, 0.0]) for atom in nn2_: nn1_.append(atom) images.append(nn1_) view(images) # # Fingerprint using Amp. descriptor = Gaussian() images = hash_images(images, ordered=True) descriptor.calculate_fingerprints(images) def barplot(hash, name, title): """Makes a barplot of the fingerprint about the O atom.""" fp = descriptor.fingerprints[hash][0] fig, ax = pyplot.subplots() ax.bar(range(len(fp[1])), fp[1]) ax.set_title(title) ax.set_ylim(0., 2.) ax.set_xlabel('fingerprint') ax.set_ylabel('value') fig.savefig(name) for index, hash in enumerate(images.keys()):