Ejemplo n.º 1
0
    def train_mgp(self, skip=True):
        t0 = time.time()

        if self.l_bound < self.grid_params['bounds_2'][0, 0]:
            self.grid_params['bounds_2'][0, 0] = self.l_bound - 0.01
            self.grid_params['bounds_3'][
                0, :2] = np.ones(2) * self.l_bound - 0.01

        if skip and (self.curr_step in self.non_mapping_steps):
            return 1

        # set svd rank based on the training set, grid number and threshold 1000
        train_size = len(self.gp.training_data)
        rank_2 = np.min([1000, self.grid_params['grid_num_2'], train_size * 3])
        rank_3 = np.min(
            [1000, self.grid_params['grid_num_3'][0]**3, train_size * 3])
        self.grid_params['svd_rank_2'] = rank_2
        self.grid_params['svd_rank_3'] = rank_3

        output.write_to_output('\ntraining set size: {}\n'.format(train_size),
                               self.output_name)
        output.write_to_output('lower bound: {}\n'.format(self.l_bound))
        output.write_to_output('mgp l_bound: {}\n'.format(
            self.grid_params['bounds_2'][0, 0]))
        output.write_to_output('Constructing mapped force field...\n',
                               self.output_name)
        self.mgp = MappedGaussianProcess(self.gp, self.grid_params,
                                         self.struc_params)
        output.write_to_output(
            'building mapping time: {}'.format(time.time() - t0),
            self.output_name)

        self.is_mgp_built = True
Ejemplo n.º 2
0
    def predict_on_structure_mgp(self):  # changed
        """
        Assign forces to self.structure based on self.gp
        """

        output.write_to_output('\npredict with mapping:\n', self.output_name)
        for n in range(self.structure.nat):
            chemenv = AtomicEnvironment(self.structure, n, self.gp.cutoffs)
            force, var = self.mgp.predict(chemenv)
            self.structure.forces[n][:] = force
            self.structure.stds[n][:] = np.sqrt(np.absolute(var))
        self.structure.dft_forces = False
Ejemplo n.º 3
0
    def update_gp(self, train_atoms, dft_frcs):
        output.write_to_output('\nAdding atom {} to the training set.\n'
                               .format(train_atoms),
                               self.output_name)
        output.write_to_output('Uncertainty: {}.\n'
                               .format(self.structure.stds[train_atoms[0]]),
                               self.output_name)

        # update gp model
        self.gp.update_db(self.structure, dft_frcs,
                          custom_range=train_atoms)

        self.gp.set_L_alpha()
Ejemplo n.º 4
0
 def write_mgp_header(self):
     output.write_to_output('bounds 2:' + str(self.mgp_model.bounds_2),
                            self.output_name)
     output.write_to_output('bounds 3:' + str(self.mgp_model.bounds_2),
                            self.output_name)
     output.write_to_output('grid num 2:' + str(self.mgp_model.grid_num_2),
                            self.output_name)
     output.write_to_output('grid num 3:' + str(self.mgp_model.grid_num_3),
                            self.output_name)
Ejemplo n.º 5
0
def predict_on_structure_mgp(structure,
                             mgp,
                             output=None,
                             output_name=None,
                             n_cpus=None,
                             write_to_structure=True,
                             selective_atoms: List[int] = None,
                             skipped_atom_value=0):  # changed
    """
    Assign forces to structure based on an mgp
    """
    if output and output_name:
        output.write_to_output('\npredict with mapping:\n', output_name)

    forces = np.zeros(shape=(structure.nat, 3))
    vars = np.zeros(shape=(structure.nat, 3))

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

    for n in range(structure.nat):

        if n not in selective_atoms and selective_atoms:
            continue

        chemenv = AtomicEnvironment(structure, n, mgp.cutoffs)
        force, var, _, _ = mgp.predict(chemenv)
        if write_to_structure:
            structure.forces[n][:] = force
            structure.stds[n][:] = np.sqrt(np.absolute(var))
        forces[n, :] = force
        vars[n, :] = var

    return forces, vars
Ejemplo n.º 6
0
    def run_dft(self):
        output.write_to_output('\nCalling Quantum Espresso...\n',
                               self.output_name)

        # calculate DFT forces
        forces = qe_util.run_espresso_par(self.qe_input, self.structure,
                                          self.pw_loc, self.no_cpus)
        self.structure.forces = forces

        # write wall time of DFT calculation
        self.dft_count += 1
        output.write_to_output('QE run complete.\n', self.output_name)
        time_curr = time.time() - self.start_time
        output.write_to_output('number of DFT calls: %i \n' % self.dft_count,
                               self.output_name)
        output.write_to_output('wall time from start: %.2f s \n' % time_curr,
                               self.output_name)
Ejemplo n.º 7
0
    def run(self):
        output.write_header(self.gp.cutoffs, self.gp.kernel_name, self.gp.hyps,
                            self.gp.algo, self.dt, self.number_of_steps,
                            self.structure, self.output_name,
                            self.std_tolerance)
        counter = 0
        self.start_time = time.time()

        while self.curr_step < self.number_of_steps:
            print('curr_step:', self.curr_step)
            # run DFT and train initial model if first step and DFT is on
            if self.curr_step == 0 and self.std_tolerance != 0:
                # call dft and update positions
                self.run_dft()
                dft_frcs = copy.deepcopy(self.structure.forces)
                new_pos = md.update_positions(self.dt, self.noa,
                                              self.structure)
                self.update_temperature(new_pos)
                self.record_state()

                # make initial gp model and predict forces
                self.update_gp(self.init_atoms, dft_frcs)
                if (self.dft_count-1) < self.freeze_hyps:
                    self.train_gp()

            # after step 1, try predicting with GP model
            else:
                self.pred_func()
                self.dft_step = False
                new_pos = md.update_positions(self.dt, self.noa,
                                              self.structure)

                # get max uncertainty atoms
                std_in_bound, target_atoms = self.is_std_in_bound()

                if not std_in_bound:
                    # record GP forces
                    self.update_temperature(new_pos)
                    self.record_state()
                    gp_frcs = copy.deepcopy(self.structure.forces)

                    # run DFT and record forces
                    self.dft_step = True
                    self.run_dft()
                    dft_frcs = copy.deepcopy(self.structure.forces)
                    new_pos = md.update_positions(self.dt, self.noa,
                                                  self.structure)
                    self.update_temperature(new_pos)
                    self.record_state()

                    # compute mae and write to output
                    mae = np.mean(np.abs(gp_frcs - dft_frcs))
                    mac = np.mean(np.abs(dft_frcs))

                    output.write_to_output('\nmean absolute error:'
                                           ' %.4f eV/A \n'
                                           % mae, self.output_name)
                    output.write_to_output('mean absolute dft component:'
                                           ' %.4f eV/A \n' % mac,
                                           self.output_name)

                    # add max uncertainty atoms to training set
                    self.update_gp(target_atoms, dft_frcs)
                    if (self.dft_count-1) < self.freeze_hyps:
                        self.train_gp()

            # write gp forces
            if counter >= self.skip and not self.dft_step:
                self.update_temperature(new_pos)
                self.record_state()
                counter = 0

            counter += 1
            self.update_positions(new_pos)
            self.curr_step += 1

        output.conclude_run(self.output_name)