Exemple #1
0
def predict_on_structure(structure: Structure,
                         gp: GaussianProcess,
                         n_cpus: int = None) -> ('np.ndarray', 'np.ndarray'):
    """
    Return the forces/std. dev. uncertainty associated with each
    individual atom in a structure. Forces are stored directly to the
    structure and are also returned.

    :param structure: FLARE structure to obtain forces for, with N atoms
    :param gp: Gaussian Process model
    :return: N x 3 numpy array of foces, Nx3 numpy array of uncertainties
    :rtype: (np.ndarray, np.ndarray)
    """
    # Loop through individual atoms, cast to atomic environments,
    # make predictions

    for n in range(structure.nat):
        chemenv = AtomicEnvironment(structure, n, gp.cutoffs)
        for i in range(3):
            force, var = gp.predict(chemenv, i + 1)
            structure.forces[n][i] = float(force)
            structure.stds[n][i] = np.sqrt(np.abs(var))

    forces = np.array(structure.forces)
    stds = np.array(structure.stds)

    return forces, stds
Exemple #2
0
def predict_on_structure_par_en(structure: Structure,
                                gp: GaussianProcess,
                                no_cpus=None):

    if (no_cpus is 1):
        predict_on_structure_en(structure, gp)

    atom_list = [(structure, atom, gp) for atom in range(structure.nat)]
    local_energies = [0 for n in range(structure.nat)]

    results = []
    if (no_cpus is None):
        pool = mp.Pool(processes=mp.cpu_count())
    else:
        pool = mp.Pool(processes=no_cpus)
    for atom in range(structure.nat):
        results.append(
            pool.apply_async(predict_on_atom_en, args=[(structure, atom, gp)]))
    pool.close()
    pool.join()

    for i in range(structure.nat):
        r = results[i].get()
        structure.forces[i] = r[0]
        structure.stds[i] = r[1]
        local_energies[i] = r[2]

    forces = np.array(structure.forces)
    stds = np.array(structure.stds)
    return forces, stds, local_energies
Exemple #3
0
    def __init__(self, dt: float, number_of_steps: int, gp: GaussianProcess,
                 pos_init: np.ndarray, species, cell, masses,
                 prev_pos_init: np.ndarray=None, par: bool=False, skip: int=0,
                 output_name='otf_run.out'):

        self.dt = dt
        self.Nsteps = number_of_steps
        self.gp = gp

        self.structure = Structure(cell=cell, species=species,
                                   positions=pos_init,
                                   mass_dict=masses,
                                   prev_positions=prev_pos_init)

        self.noa = self.structure.positions.shape[0]
        self.atom_list = list(range(self.noa))
        self.curr_step = 0

        # choose prediction function
        if par is True:
            self.pred_func = self.predict_on_structure_par_en
        else:
            self.pred_func = self.predict_on_structure_en

        # initialize local energies
        self.local_energies = np.zeros(self.noa)

        self.pes = []
        self.kes = []

        self.output = Output(output_name)
Exemple #4
0
def test_from_pmg_structure():

    pmg_struc = pmgstruc.Structure(lattice= np.eye(3),
                                   species=['H'],
                                   coords=[[.25, .5, 0]],
                                   site_properties={
                                       'force': [np.array((1., 1.,  1.))],
                                        'std':[np.array((1., 1., 1.))]},
                                   coords_are_cartesian=True)

    new_struc = Structure.from_pmg_structure(pmg_struc)

    assert len(new_struc) == 1

    assert np.equal(new_struc.positions, np.array([.25, .5, 0])).all()
    assert new_struc.coded_species == [1]
    assert new_struc.species_labels[0] == 'H'
    assert np.equal(new_struc.forces, np.array([1., 1., 1.])).all()

    pmg_struc = pmgstruc.Structure(lattice= np.diag([1.2,0.8,1.5]),
                                   species=['H'],
                                   coords=[[.25, .5, 0]],
                                   site_properties={
                                       'force': [np.array((1., 1.,  1.))],
                                        'std':[np.array((1., 1., 1.))]},
                                   coords_are_cartesian=True)

    new_struc = Structure.from_pmg_structure(pmg_struc)

    assert len(new_struc) == 1

    assert np.equal(new_struc.positions, np.array([.25, .5, 0])).all()
    assert new_struc.coded_species == [1]
    assert new_struc.species_labels[0] == 'H'
    assert np.equal(new_struc.forces, np.array([1., 1., 1.])).all()
Exemple #5
0
def varied_test_struc():
    struc = Structure(np.eye(3),
                      species=[1, 2, 2, 3, 3, 4, 4, 4, 4, 3],
                      positions=np.array(
                          [np.random.uniform(-1, 1, 3) for i in range(10)]))
    struc.forces = np.array([np.random.uniform(-1, 1, 3) for _ in range(10)])
    return struc
Exemple #6
0
def test_prev_positions_arg():
    np.random.seed(0)
    positions = []
    prev_positions = []
    species = [1] * 5
    cell = np.eye(3)
    for n in range(5):
        positions.append(np.random.uniform(-1, 1, 3))
        prev_positions.append(np.random.uniform(-1, 1, 3))

    test_structure1 = Structure(cell, species, positions)
    test_structure2 = Structure(cell,
                                species,
                                positions,
                                prev_positions=positions)
    test_structure3 = Structure(cell,
                                species,
                                positions,
                                prev_positions=prev_positions)

    assert np.equal(test_structure1.positions, test_structure2.positions).all()
    assert np.equal(test_structure1.prev_positions,
                    test_structure2.prev_positions).all()
    assert np.equal(test_structure2.positions,
                    test_structure2.prev_positions).all()
    assert not np.equal(test_structure3.positions,
                        test_structure3.prev_positions).all()
Exemple #7
0
def predict_on_structure_en(
        structure: Structure,
        gp: GaussianProcess,
        n_cpus: int = None) -> ('np.ndarray', 'np.ndarray', 'np.ndarray'):
    """
    Return the forces/std. dev. uncertainty / local energy associated with each
    individual atom in a structure. Forces are stored directly to the
    structure and are also returned.

    :param structure: FLARE structure to obtain forces for, with N atoms
    :param gp: Gaussian Process model
    :param n_cpus: Dummy parameter passed as an argument to allow for
        flexibility when the callable may or may not be parallelized
    :return: N x 3 array of forces, N x 3 array of uncertainties,
        N-length array of energies
    :rtype: (np.ndarray, np.ndarray, np.ndarray)
    """
    # Set up local energy array
    local_energies = np.array([0 for _ in range(structure.nat)])

    # Loop through atoms in structure and predict forces, uncertainties,
    # and energies
    for n in range(structure.nat):
        chemenv = AtomicEnvironment(structure, n, gp.cutoffs)
        for i in range(3):
            force, var = gp.predict(chemenv, i + 1)
            structure.forces[n][i] = float(force)
            structure.stds[n][i] = np.sqrt(np.abs(var))
        local_energies[n] = gp.predict_local_energy(chemenv)

    forces = np.array(structure.forces)
    stds = np.array(structure.stds)
    return forces, stds, local_energies
Exemple #8
0
    def otf_run(self, steps):
        """Perform a number of time steps."""
        # initialize gp by a dft calculation
        if not self.atoms.calc.gp_model.training_data:
            self.dft_count = 0
            self.std_in_bound = False
            self.target_atom = 0
            self.stds = []
            dft_forces = self.call_DFT()
            f = dft_forces

            # update gp model
            atom_struc = Structure(np.array(self.atoms.cell),
                                   self.atoms.get_atomic_numbers(),
                                   self.atoms.positions)
            self.atoms.calc.gp_model.update_db(atom_struc,
                                               dft_forces,
                                               custom_range=self.init_atoms)

            # train calculator
            self.train()
            print('mgp model:', self.atoms.calc.mgp_model)

        if self.md_engine == 'NPT':
            if not self.initialized:
                self.initialize()
            else:
                if self.have_the_atoms_been_changed():
                    raise NotImplementedError(
                        "You have modified the atoms since the last timestep.")

        for i in range(steps):
            print('step:', i)
            if self.md_engine == 'NPT':
                self.step()
            else:
                f = self.step(f)
            self.nsteps += 1
            self.stds = self.atoms.get_uncertainties()

            # figure out if std above the threshold
            self.call_observers()
            curr_struc = Structure.from_ase_atoms(self.atoms)
            curr_struc.stds = self.stds
            noise = self.atoms.calc.gp_model.hyps[-1]
            self.std_in_bound, self.target_atoms = is_std_in_bound(\
                    noise, self.std_tolerance, curr_struc, self.max_atoms_added)

            #self.is_std_in_bound([])

            if not self.std_in_bound:
                # call dft/eam
                print('calling dft')
                dft_forces = self.call_DFT()

                # update gp
                print('updating gp')
                self.update_GP(dft_forces)

        self.observers[0][0].run_complete()
Exemple #9
0
def predict_on_structure_en(
        structure: Structure,
        gp: GaussianProcess,
        n_cpus: int = None,
        write_to_structure: bool = True,
        selective_atoms: List[int] = None,
        skipped_atom_value=0) -> ('np.ndarray', 'np.ndarray', 'np.ndarray'):
    """
    Return the forces/std. dev. uncertainty / local energy associated with each
    individual atom in a structure. Forces are stored directly to the
    structure and are also returned.

    :param structure: FLARE structure to obtain forces for, with N atoms
    :param gp: Gaussian Process model
    :param n_cpus: Dummy parameter passed as an argument to allow for
        flexibility when the callable may or may not be parallelized
    :return: N x 3 array of forces, N x 3 array of uncertainties,
        N-length array of energies
    :rtype: (np.ndarray, np.ndarray, np.ndarray)
    """
    # Set up local energy array
    forces = np.zeros((structure.nat, 3))
    stds = np.zeros((structure.nat, 3))
    local_energies = np.zeros(structure.nat)
    forces = np.zeros(shape=(structure.nat, 3))
    stds = np.zeros(shape=(structure.nat, 3))

    if selective_atoms:
        forces.fill(skipped_atom_value)
        stds.fill(skipped_atom_value)
        local_energies.fill(skipped_atom_value)
    else:
        selective_atoms = []

    # Loop through atoms in structure and predict forces, uncertainties,
    # and energies
    for n in range(structure.nat):

        if selective_atoms and n not in selective_atoms:
            continue

        chemenv = AtomicEnvironment(structure,
                                    n,
                                    gp.cutoffs,
                                    cutoffs_mask=gp.hyps_mask)

        for i in range(3):
            force, var = gp.predict(chemenv, i + 1)
            forces[n][i] = float(force)
            stds[n][i] = np.sqrt(np.abs(var))

            if write_to_structure and structure.forces is not None:
                structure.forces[n][i] = float(force)
                structure.stds[n][i] = np.sqrt(np.abs(var))

        local_energies[n] = gp.predict_local_energy(chemenv)

    return forces, stds, local_energies
Exemple #10
0
def test_struc_to_ase():
    from ase import Atoms
    uc = Structure(species=['Pd' for i in range(10)]+['Ag' for i in range(10)],
                   positions=np.random.rand(20, 3),
                   cell=np.random.rand(3, 3))
    new_atoms = Structure.to_ase_atoms(uc)
    assert np.all(uc.species_labels == new_atoms.get_chemical_symbols())
    assert np.all(uc.positions == new_atoms.get_positions())
    assert np.all(uc.cell == new_atoms.get_cell())
Exemple #11
0
def predict_on_structure(structure: Structure, gp: GaussianProcess):
    for n in range(structure.nat):
        chemenv = AtomicEnvironment(structure, n, gp.cutoffs)
        for i in range(3):
            force, var = gp.predict(chemenv, i + 1)
            structure.forces[n][i] = float(force)
            structure.stds[n][i] = np.sqrt(np.abs(var))
    forces = np.array(structure.forces)
    stds = np.array(structure.stds)
    return forces, stds
Exemple #12
0
def predict_on_structure(
    structure: Structure,
    gp: GaussianProcess,
    n_cpus: int = None,
    write_to_structure: bool = True,
    selective_atoms: List[int] = None,
    skipped_atom_value=0,
) -> ("np.ndarray", "np.ndarray"):
    """
    Return the forces/std. dev. uncertainty associated with each
    individual atom in a structure. Forces are stored directly to the
    structure and are also returned.

    :param structure: FLARE structure to obtain forces for, with N atoms
    :param gp: Gaussian Process model
    :param write_to_structure: Write results to structure's forces,
                            std attributes
    :param selective_atoms: Only predict on these atoms; e.g. [0,1,2] will
                                only predict and return for those atoms
    :param skipped_atom_value: What value to use for atoms that are skipped.
            Defaults to 0 but other options could be e.g. NaN. Will NOT
            write this to the structure if write_to_structure is True.
    :return: N x 3 numpy array of foces, Nx3 numpy array of uncertainties
    :rtype: (np.ndarray, np.ndarray)
    """

    forces = np.zeros((structure.nat, 3))
    stds = np.zeros((structure.nat, 3))

    if selective_atoms:
        forces.fill(skipped_atom_value)
        stds.fill(skipped_atom_value)
    else:
        selective_atoms = []

    for n in range(structure.nat):

        # Skip the atoms which we aren't predicting on if
        # selective atoms is on.
        if n not in selective_atoms and selective_atoms:
            continue

        chemenv = AtomicEnvironment(structure, n, gp.cutoffs, cutoffs_mask=gp.hyps_mask)

        force, var = gp.predict_force_xyz(chemenv)
        std = np.sqrt(np.abs(var))

        forces[n] = force
        stds[n] = std

        if write_to_structure:
            structure.forces[n] = force
            structure.stds[n] = std

    return forces, stds
Exemple #13
0
def another_env(cutoffs, delt):

    cell = 10.0 * np.eye(3)

    # atomic structure 1
    pos_1 = np.vstack([[0, 0, 0], 0.1*random([3, 3])])
    pos_1[1, 1] += 1
    pos_1[2, 0] += 1
    pos_1[3, :2] += 1
    pos_2 = deepcopy(pos_1)
    pos_2[0][0] = delt
    pos_3 = deepcopy(pos_1)
    pos_3[0][0] = -delt


    species_1 = [1, 1, 1, 1]

    test_structure_1 = Structure(cell, species_1, pos_1)
    test_structure_2 = Structure(cell, species_1, pos_2)
    test_structure_3 = Structure(cell, species_1, pos_3)

    # atom 0, original position
    env1_1_0 = AtomicEnvironment(test_structure_1, 0, cutoffs)
    # atom 0, 0 perturbe along x
    env1_2_0 = AtomicEnvironment(test_structure_2, 0, cutoffs)
    # atom 1, 0 perturbe along x
    env1_2_1 = AtomicEnvironment(test_structure_2, 1, cutoffs)
    # atom 2, 0 perturbe along x
    env1_2_2 = AtomicEnvironment(test_structure_2, 2, cutoffs)

    # atom 0, 0 perturbe along -x
    env1_3_0 = AtomicEnvironment(test_structure_3, 0, cutoffs)
    # atom 1, 0 perturbe along -x
    env1_3_1 = AtomicEnvironment(test_structure_3, 1, cutoffs)
    # atom 2, 0 perturbe along -x
    env1_3_2 = AtomicEnvironment(test_structure_3, 2, cutoffs)

    # create env 2
    pos_1 = np.vstack([[0, 0, 0], 0.1*random([3, 3])])
    pos_1[1, 1] += 1
    pos_1[2, 0] += 1
    pos_1[3, :2] += 1
    pos_2 = deepcopy(pos_1)
    pos_2[0][0] = delt
    pos_3 = deepcopy(pos_1)
    pos_3[0][0] = -delt

    species_2 = [1, 2, 2, 1]

    test_structure_1 = Structure(cell, species_2, pos_1)

    env2_1_0 = AtomicEnvironment(test_structure_1, 0, cutoffs)

    return env1_1_0, env1_2_0, env1_3_0, \
           env1_2_1, env1_3_1, env1_2_2, env1_3_2, env2_1_0
Exemple #14
0
def predict_on_structure_par(structure: Structure, gp: GaussianProcess):
    n = 0
    atom_list = [(structure, atom, gp) for atom in range(structure.nat)]
    with concurrent.futures.ProcessPoolExecutor() as executor:
        for res in executor.map(predict_on_atom, atom_list):
            for i in range(3):
                structure.forces[n][i] = res[0][i]
                structure.stds[n][i] = res[1][i]
            n += 1
    forces = np.array(structure.forces)
    stds = np.array(structure.stds)
    return forces, stds
Exemple #15
0
def test_uncertainty_threshold(fake_gp):
    tt = TrajectoryTrainer([], fake_gp, rel_std_tolerance=.5,
                           abs_std_tolerance=.01)

    fake_structure = Structure(cell=np.eye(3), species=["H"],
                               positions=np.array([[0, 0, 0]]))

    # Test a structure with no variance passes
    fake_structure.stds = np.array([[0, 0, 0]])

    res1, res2 = tt.is_std_in_bound(fake_structure)
    assert res1 is True
    assert res2 == [-1]

    # Test that the absolute criteria trips the threshold
    fake_structure.stds = np.array([[.02, 0, 0]])

    res1, res2 = tt.is_std_in_bound(fake_structure)
    assert res1 is False
    assert res2 == [0]

    tt.abs_std_tolerance = 100

    # Test that the relative criteria trips the threshold
    fake_structure.stds = np.array([[.6, 0, 0]])

    res1, res2 = tt.is_std_in_bound(fake_structure)
    assert res1 is False
    assert res2 == [0]

    # Test that 'test mode' works, where no GP modification occurs
    tt.abs_std_tolerance = 0
    tt.rel_std_tolerance = 0

    res1, res2 = tt.is_std_in_bound(fake_structure)
    assert res1 is True
    assert res2 == [-1]

    # Test permutations of one / another being off
    tt.abs_std_tolerance = 1
    tt.rel_std_tolerance = 0

    res1, res2 = tt.is_std_in_bound(fake_structure)
    assert res1 is True
    assert res2 == [-1]

    tt.abs_std_tolerance = 0
    tt.rel_std_tolerance = 1

    res1, res2 = tt.is_std_in_bound(fake_structure)
    assert res1 is True
    assert res2 == [-1]
Exemple #16
0
def test_to_from_methods(varied_test_struc):
    test_dict = varied_test_struc.as_dict()

    assert isinstance(test_dict, dict)
    assert (test_dict["forces"] == varied_test_struc.forces).all()

    new_struc_1 = Structure.from_dict(test_dict)
    new_struc_2 = Structure.from_dict(loads(varied_test_struc.as_str()))

    for new_struc in [new_struc_1, new_struc_2]:
        assert np.equal(varied_test_struc.positions, new_struc.positions).all()
        assert np.equal(varied_test_struc.cell, new_struc.cell).all()
        assert np.equal(varied_test_struc.forces, new_struc.forces).all()
Exemple #17
0
def test_struc_from_ase():
    from ase import Atoms
    from ase.calculators.singlepoint import SinglePointCalculator

    results = {
        "forces": np.random.randn(20, 3),
        "energy": np.random.rand(),
        "stress": np.random.randn(6),
    }

    uc = Atoms(
        ["Pd" for i in range(10)] + ["Ag" for i in range(10)],
        positions=np.random.rand(20, 3),
        cell=np.random.rand(3, 3),
    )

    calculator = SinglePointCalculator(uc, **results)
    uc.set_calculator(calculator)

    new_struc = Structure.from_ase_atoms(uc)

    assert np.all(new_struc.species_labels == uc.get_chemical_symbols())
    assert np.all(new_struc.positions == uc.get_positions())
    assert np.all(new_struc.cell == uc.get_cell())
    assert np.all(new_struc.forces == results["forces"])
    assert np.all(new_struc.energy == results["energy"])
    assert np.all(new_struc.stress == results["stress"])
Exemple #18
0
def test_auto_sweep():
    """Test that the number of neighbors inside the local environment is
        correctly computed."""

    # Make an arbitrary non-cubic structure.
    cell = np.array([[1.3, 0.5, 0.8], [-1.2, 1, 0.73], [-0.8, 0.1, 0.9]])
    positions = np.array([[1.2, 0.7, 2.3], [3.1, 2.5, 8.9], [-1.8, -5.8, 3.0],
                          [0.2, 1.1, 2.1], [3.2, 1.1, 3.3]])
    species = np.array([1, 2, 3, 4, 5])
    arbitrary_structure = Structure(cell, species, positions)

    # Construct an environment.
    cutoffs = np.array([4., 3.])
    arbitrary_environment = \
        AtomicEnvironment(arbitrary_structure, 0, cutoffs)

    # Count the neighbors.
    n_neighbors_1 = len(arbitrary_environment.etypes)

    # Reduce the sweep value, and check that neighbors are missing.
    sweep_val = arbitrary_environment.sweep_val
    arbitrary_environment.sweep_array = \
        np.arange(-sweep_val + 1, sweep_val, 1)
    arbitrary_environment.compute_env()
    n_neighbors_2 = len(arbitrary_environment.etypes)
    assert (n_neighbors_1 > n_neighbors_2)

    # Increase the sweep value, and check that the count is the same.
    arbitrary_environment.sweep_array = \
        np.arange(-sweep_val - 1, sweep_val + 2, 1)
    arbitrary_environment.compute_env()
    n_neighbors_3 = len(arbitrary_environment.etypes)
    assert (n_neighbors_1 == n_neighbors_3)
Exemple #19
0
def test_update_L_alpha():
    # set up gp model
    kernel = mc_simple.two_plus_three_body_mc
    kernel_grad = mc_simple.two_plus_three_body_mc_grad
    cutoffs = [6.0, 5.0]
    hyps = np.array([0.001770, 0.183868, -0.001415, 0.372588, 0.026315])

    # get an otf traj from file for training data
    old_otf = OtfAnalysis('test_files/AgI_snippet.out')
    call_no = 1
    cell = old_otf.header['cell']
    gp_model = old_otf.make_gp(kernel=kernel,
                               kernel_grad=kernel_grad,
                               call_no=call_no,
                               cutoffs=cutoffs,
                               hyps=hyps)

    # update database & use update_L_alpha to get ky_mat
    for n in range(call_no, call_no + 1):
        positions = old_otf.gp_position_list[n]
        species = old_otf.gp_species_list[n]
        atoms = old_otf.gp_atom_list[n]
        forces = old_otf.gp_force_list[n]

        struc_curr = Structure(cell, species, positions)
        gp_model.update_db(struc_curr, forces, custom_range=atoms)
        gp_model.update_L_alpha()

    ky_mat_from_update = np.copy(gp_model.ky_mat)

    # use set_L_alpha to get ky_mat
    gp_model.set_L_alpha()
    ky_mat_from_set = np.copy(gp_model.ky_mat)

    assert (np.all(np.absolute(ky_mat_from_update - ky_mat_from_set)) < 1e-6)
Exemple #20
0
def test_load_one_frame_and_run():
    the_gp = GaussianProcess(
        kernel_name="2+3_mc",
        hyps=np.array([
            3.75996759e-06,
            1.53990678e-02,
            2.50624782e-05,
            5.07884426e-01,
            1.70172923e-03,
        ]),
        cutoffs=np.array([5, 3]),
        hyp_labels=["l2", "s2", "l3", "s3", "n0"],
        maxiter=1,
        opt_algorithm="L-BFGS-B",
    )

    with open(path.join(TEST_FILE_DIR, "methanol_frames.json"), "r") as f:
        frames = [Structure.from_dict(loads(s)) for s in f.readlines()]

    tt = TrajectoryTrainer(
        frames,
        gp=the_gp,
        shuffle_frames=True,
        print_as_xyz=True,
        rel_std_tolerance=0,
        abs_std_tolerance=0,
        skip=15,
    )

    tt.run()
    for f in glob(f"gp_from_aimd*"):
        remove(f)
Exemple #21
0
def test_subset_of_frame_by_element():
    spec_list = ["H", "H", "O", "O", "O", "C"]
    test_struc_1 = Structure(
        cell=np.eye(3), species=spec_list, positions=np.zeros(shape=(len(spec_list), 3))
    )

    assert np.array_equal(
        subset_of_frame_by_element(test_struc_1, {}), list(range(len(test_struc_1)))
    )

    assert np.array_equal(
        subset_of_frame_by_element(test_struc_1, {"H": 2, "O": 3}),
        list(range(len(test_struc_1))),
    )
    assert np.array_equal(
        subset_of_frame_by_element(test_struc_1, {"H": 2, "O": 15}),
        list(range(len(test_struc_1))),
    )

    assert set(subset_of_frame_by_element(test_struc_1, {"H": 1, "O": 1})).issubset(
        range(len(spec_list))
    )
    assert len(subset_of_frame_by_element(test_struc_1, {"H": 1, "O": 1, "C": 1})) == 3

    assert subset_of_frame_by_element(test_struc_1, {"H": 0, "O": 0, "C": 0}) == []

    assert subset_of_frame_by_element(test_struc_1, {"H": 0, "O": 0, "C": 1}) == [5]
Exemple #22
0
    def restart(self):
        # Recover atomic configuration: positions, velocities, forces
        positions, self.nsteps = self.read_frame('positions.xyz', -1)
        self.atoms.set_positions(positions)
        self.atoms.set_velocities(self.read_frame('velocities.dat', -1)[0])
        self.atoms.calc.results['forces'] = self.read_frame('forces.dat',
                                                            -1)[0]
        print('Last frame recovered')

        # Recover training data set
        gp_model = self.atoms.calc.gp_model
        atoms = deepcopy(self.atoms)
        nat = len(self.atoms.positions)
        dft_positions = self.read_all_frames('dft_positions.xyz', nat)
        dft_forces = self.read_all_frames('dft_forces.dat', nat)
        added_atoms = self.read_all_frames('added_atoms.dat', 1, 1, 'int')
        for i, frame in enumerate(dft_positions):
            atoms.set_positions(frame)
            curr_struc = Structure.from_ase_atoms(atoms)
            gp_model.update_db(curr_struc, dft_forces[i], added_atoms[i])
        gp_model.set_L_alpha()
        print('GP training set ready')

        # Recover FLARE calculator
        gp_model.ky_mat_inv = np.load(self.restart_from + '/ky_mat_inv.npy')
        gp_model.alpha = np.load(self.restart_from + '/alpha.npy')
        if self.atoms.calc.use_mapping:
            for map_3 in self.atoms.calc.mgp_model.maps_3:
                map_3.load_grid = self.restart_from + '/'
            self.atoms.calc.build_mgp(skip=False)
        print('GP and MGP ready')

        self.l_bound = 10
Exemple #23
0
def predict_on_structure_en(structure: Structure,
                            gp: GaussianProcess,
                            no_cpus=None):
    local_energies = [0 for _ in range(structure.nat)]

    for n in range(structure.nat):
        chemenv = AtomicEnvironment(structure, n, gp.cutoffs)
        for i in range(3):
            force, var = gp.predict(chemenv, i + 1)
            structure.forces[n][i] = float(force)
            structure.stds[n][i] = np.sqrt(np.abs(var))
        local_energies[n] = gp.predict_local_energy(chemenv)

    forces = np.array(structure.forces)
    stds = np.array(structure.stds)
    return forces, stds, local_energies
Exemple #24
0
def generate_mb_envs_pos(positions0, species_1, cutoffs, cell, delt, d1, mask=None):

    positions = [positions0]

    noa = len(positions0)

    positions_2 = deepcopy(positions0)
    positions_2[0][d1 - 1] = delt
    positions += [positions_2]

    positions_3 = deepcopy(positions[0])
    positions_3[0][d1 - 1] = -delt
    positions += [positions_3]

    test_struc = []
    for i in range(3):
        test_struc += [Structure(cell, species_1, positions[i])]

    env_0 = []
    env_p = []
    env_m = []
    for i in range(noa):
        env_0 += [AtomicEnvironment(test_struc[0], i, cutoffs, cutoffs_mask=mask)]
        env_p += [AtomicEnvironment(test_struc[1], i, cutoffs, cutoffs_mask=mask)]
        env_m += [AtomicEnvironment(test_struc[2], i, cutoffs, cutoffs_mask=mask)]
    return [env_0, env_p, env_m]
Exemple #25
0
    def update_GP(self, dft_forces):
        atom_count = 0
        atom_list = []
        calc = self.atoms.calc.gp_model
        while (not self.std_in_bound and atom_count < self.max_atoms_added):
            # build gp structure from atoms
            atom_struc = Structure(self.atoms.cell,
                                   ['A'] * len(self.atoms.positions),
                                   self.atoms.positions)

            # update gp model
            calc.update_db(atom_struc,
                           dft_forces,
                           custom_range=[self.target_atom])

            if calc.alpha is None:
                calc.set_L_alpha()
            else:
                calc.update_L_alpha()

            atom_list.append(self.target_atom)
            forces = self.atoms.get_forces()  # use this function to get k_v
            self.stds = self.atoms.get_uncertainties()

            # write added atom to the log file,
            # refer to ase.optimize.optimize.Dynamics
            self.observers[0][0].add_atom_info(self.target_atom,
                                               self.stds[self.target_atom])

            self.is_std_in_bound(atom_list)
            atom_count += 1

        if not self.freeze_hyps:
            calc.train()
Exemple #26
0
def parse_dft_input(input: str):
    """
    Returns the positions, species, and cell of a POSCAR file.
    Outputs are specced for OTF module.

    :param input: POSCAR file input
    :return:
    """

    pmg_structure = Poscar.from_file(input).structure
    flare_structure = Structure.from_pmg_structure(pmg_structure)

    positions = flare_structure.positions
    species = flare_structure.species_labels
    cell = flare_structure.cell
    # TODO Allow for custom masses in POSCAR

    elements = set(species)

    # conversion from amu to md units
    mass_dict = {
        elt: Element(elt).atomic_mass * 0.000103642695727
        for elt in elements
    }

    return positions, species, cell, mass_dict
Exemple #27
0
def test_wrapped_coordinates():
    """Check that wrapped coordinates are equivalent to Cartesian coordinates
    up to lattice translations."""

    cell = np.random.rand(3, 3)
    positions = np.random.rand(10, 3)
    species = ["Al"] * len(positions)

    test_struc = Structure(cell, species, positions)

    wrap_diff = test_struc.positions - test_struc.wrapped_positions
    wrap_rel = test_struc.raw_to_relative(wrap_diff, test_struc.cell_transpose,
                                          test_struc.cell_dot_inverse)

    assert np.isclose(
        np.round(wrap_rel) - wrap_rel, np.zeros(positions.shape)).all()
Exemple #28
0
    def calculate_mgp_serial(self, atoms):
        nat = len(atoms)
        struc_curr = Structure(np.array(atoms.cell),
                               atoms.get_atomic_numbers(), atoms.positions)

        forces = np.zeros((nat, 3))
        stress = np.zeros((nat, 6))
        stds = np.zeros((nat, 3))
        for n in range(nat):
            chemenv = AtomicEnvironment(struc_curr, n, self.mgp_model.cutoffs)
            f, v, vir = self.mgp_model.predict(chemenv, mean_only=False)
            forces[n] = f
            stress[n] = vir
            stds[n] = np.sqrt(np.absolute(v))

        self.results['forces'] = forces
        self.results['stds'] = stds
        self.results['stresses'] = stress
        self.results['stress'] = np.sum(stress, axis=0)

        # TODO: implement energy mapping
        self.results['local_energies'] = np.zeros(forces.shape)
        self.results['energy'] = 0

        atoms.get_uncertainties = self.get_uncertainties
        return forces
Exemple #29
0
def test_espresso_input_edit():
    """
    Load a structure in from qe_input_1, change the position and cell,
    then edit and re-parse
    :return:
    """
    os.system('cp test_files/qe_input_1.in .')
    positions, species, cell, masses = parse_dft_input('./qe_input_1.in')
    _, coded_species = get_unique_species(species)
    structure = Structure(cell,
                          coded_species,
                          positions,
                          masses,
                          species_labels=species)

    structure.vec1 += np.random.randn(3)
    structure.positions[0] += np.random.randn(3)

    new_file = edit_dft_input_positions('./qe_input_1.in', structure=structure)

    positions, species, cell, masses = parse_dft_input(new_file)

    assert np.equal(positions[0], structure.positions[0]).all()
    assert np.equal(structure.vec1, cell[0, :]).all()

    os.remove('qe_input_1.in')
def test_cp2k_input_edit():
    """
    Load a structure in from cp2k_input_1, change the position and cell,
    then edit and re-parse
    :return:
    """
    positions, species, cell, masses = parse_dft_input(
        "./test_files/cp2k_input_1.in")
    _, coded_species = get_unique_species(species)
    structure = Structure(cell,
                          coded_species,
                          positions,
                          masses,
                          species_labels=species)

    structure.positions[0] += np.random.randn(3)

    newfilename = edit_dft_input_positions("./test_files/cp2k_input_1.in",
                                           structure=structure)

    positions, species, cell, masses = parse_dft_input(newfilename)

    assert np.isclose(positions[0], structure.positions[0]).all()
    assert np.isclose(structure.vec1, cell[0, :]).all()

    remove(newfilename)
    cleanup()