Esempio n. 1
0
    def optimize(self):
        prev_coords = self.coords[-1]
        prev_forces = self.forces[-1]

        step = bfgs_multiply(self.sigmas, self.grad_diffs, prev_forces)
        step = self.scale_by_max_step(step)

        new_coords = prev_coords + self.alpha * step

        coords_tmp = prev_coords.copy()
        forces_tmp = prev_forces.copy()

        self.geometry.coords = new_coords
        if self.is_cos and self.align:
            rot_vecs, rot_vec_lists, _ = fit_rigid(
                self.geometry, (prev_coords, prev_forces),
                vector_lists=(self.sigmas, self.grad_diffs))
            prev_coords, prev_forces = rot_vecs
            # self.sigmas, self.grad_diffs = rot_vec_lists
            rot_sigmas, rot_grad_diffs = rot_vec_lists
            # if sigs:
            # import pdb; pdb.set_trace()
            np.testing.assert_allclose(np.linalg.norm(rot_sigmas),
                                       np.linalg.norm(self.sigmas))
            np.testing.assert_allclose(np.linalg.norm(rot_grad_diffs),
                                       np.linalg.norm(self.grad_diffs))
            self.sigmas = rot_sigmas
            self.grad_diffs = rot_grad_diffs

        new_forces = self.geometry.forces
        new_energy = self.geometry.energy

        skip = self.backtrack(new_forces, prev_forces)
        print("alpha", self.alpha)
        if skip:
            self.geometry.coords = coords_tmp
            return None

        sigma = new_coords - prev_coords
        self.sigmas.append(sigma)
        grad_diff = prev_forces - new_forces
        self.grad_diffs.append(grad_diff)

        # if len(self.sigmas) == self.keep_last:
        # import pdb; pdb.set_trace()
        self.sigmas = self.sigmas[-self.keep_last:]
        self.grad_diffs = self.grad_diffs[-self.keep_last:]

        # Because we add the step later on we restore the original
        # coordinates and set the appropriate energies and forces.
        self.geometry.coords = prev_coords
        self.geometry.forces = new_forces
        self.geometry.energy = new_energy

        self.forces.append(new_forces)
        self.energies.append(new_energy)

        return step
Esempio n. 2
0
    def optimize(self):
        cur_forces = self.forces[-1]

        if not self.resetted and self.cur_cycle > 0:
            prev_forces = self.forces[-2]
            beta = self.get_beta(cur_forces, prev_forces)
            self.log(f"beta = {beta:.06f}")
            if np.isinf(beta):
                beta = 1.0
            step = cur_forces + beta * self.steps[-1]
        else:
            # Start with steepest descent in the first iteration
            step = cur_forces
            self.resetted = False

        step = self.alpha * step
        step = self.scale_by_max_step(step)

        cur_coords = self.geometry.coords
        new_coords = cur_coords + step
        self.geometry.coords = new_coords

        new_forces = self.geometry.forces
        new_energy = self.geometry.energy

        skip = self.backtrack(new_forces, cur_forces)
        # Imho backtracking gives bad results here, so only use it if
        # explicitly requested (self.dont_skip == False).
        if (not self.dont_skip) and skip:
            self.geometry.coords = cur_coords
            return None

        if self.align and self.is_cos:
            (new_forces, cur_forces,
             step), _, _ = fit_rigid(self.geometry,
                                     (new_forces, cur_forces, step))
            # Minus step???
            new_coords = self.geometry.coords - step
            self.geometry.coords = new_coords
            # Set the calculated properties on the rotated geometries
            self.geometry.energy = new_energy
            self.geometry.forces = new_forces

        self.forces[-1] = cur_forces
        self.forces.append(new_forces)
        self.energies.append(new_energy)

        return step
Esempio n. 3
0
    def optimize(self):
        if self.is_cos and self.align:
            rot_vecs, rot_vec_lists, _ = fit_rigid(
                self.geometry,
                vector_lists=(self.steps, self.forces, self.coord_diffs,
                              self.grad_diffs))
            rot_steps, rot_forces, rot_coord_diffs, rot_grad_diffs = rot_vec_lists
            self.steps = rot_steps
            self.forces = rot_forces
            self.coord_diffs = rot_coord_diffs
            self.grad_diffs = rot_grad_diffs

        forces = self.geometry.forces
        self.forces.append(forces)
        energy = self.geometry.energy
        self.energies.append(energy)
        norm = np.linalg.norm(forces)
        self.log(f"norm(forces)={norm:.6f}")

        if self.cur_cycle > 0:
            y = self.forces[-2] - forces
            s = self.steps[-1]
            if self.double_damp:
                s, y = double_damp(s,
                                   y,
                                   s_list=self.coord_diffs,
                                   y_list=self.grad_diffs)
            self.grad_diffs.append(y)
            self.coord_diffs.append(s)

            # Drop superfluous oldest vectors
            self.coord_diffs = self.coord_diffs[-self.keep_last:]
            self.grad_diffs = self.grad_diffs[-self.keep_last:]

        step = bfgs_multiply(self.coord_diffs,
                             self.grad_diffs,
                             forces,
                             beta=self.beta,
                             gamma_mult=self.gamma_mult,
                             logger=self.logger)
        step = scale_by_max_step(step, self.max_step)

        return step
Esempio n. 4
0
    def optimize(self):
        if self.is_cos and self.align:
            (self.v, ), _, _ = fit_rigid(self.geometry, (self.v, ))

        self.forces.append(self.geometry.forces)
        self.energies.append(self.geometry.energy)
        forces = self.forces[-1]
        mixed_v = (
            # As 'a' gets bigger we keep less old v.
            (1.0 - self.a) * self.v +
            # As 'a' gets bigger we use more new v
            # from the current forces.
            self.a * np.sqrt(np.dot(self.v, self.v) / np.dot(forces, forces)) *
            forces)
        last_v = self.velocities[-1]
        # Check if forces are still aligned with the last velocity
        if (self.cur_cycle > 0) and (np.dot(last_v, forces) > 0):
            if self.n_reset > self.N_acc:
                self.dt = min(self.dt * self.f_inc, self.dt_max)
                self.a *= self.f_acc
            self.n_reset += 1
        else:
            # Reset everything when 'forces' and 'last_v' aren't
            # aligned anymore.
            mixed_v = np.zeros_like(forces)
            self.log("resetted velocities")
            self.a = self.a_start
            self.dt *= self.f_acc
            self.n_reset = 0

        v = mixed_v + self.dt * forces
        self.velocities.append(v)
        self.time_deltas.append(self.dt)
        steps = self.dt * v
        steps = self.scale_by_max_step(steps)

        velo_norm = np.linalg.norm(v)
        self.log(f"dt = {self.dt:.4f}, norm(v) {velo_norm:.4f}")

        return steps
Esempio n. 5
0
    def optimize(self):
        if self.align and self.is_cos:
            (self.velocities[-1], ), _, _ = fit_rigid(self.geometry,
                                                      (self.velocities[-1], ))

        prev_velocities = self.velocities[-1]
        cur_forces = self.geometry.forces
        self.forces.append(cur_forces)
        self.energies.append(self.geometry.energy)

        norm = np.linalg.norm(cur_forces)
        if not self.is_cos:
            self.log(f"Current energy={self.energies[-1]:.6f}")
        self.log(f"norm(forces)={norm:.6f}")

        if self.cur_cycle == 0:
            tmp_velocities = np.zeros_like(prev_velocities)
        else:
            overlap = prev_velocities.dot(cur_forces)
            self.log(f"Overlap of previous and current forces: {overlap:.6f}")
            if overlap > 0:
                tmp_velocities = (overlap * cur_forces /
                                  cur_forces.dot(cur_forces))
            else:
                tmp_velocities = np.zeros_like(prev_velocities)
                self.log("Zeroed velocities")

        accelerations = cur_forces / self.geometry.masses_rep
        cur_velocities = tmp_velocities + self.dt * accelerations
        steps = cur_velocities * self.dt + 1 / 2 * accelerations * self.dt**2
        steps = self.scale_by_max_step(steps)
        self.velocities.append(cur_velocities)
        velo_norm = np.linalg.norm(cur_velocities)
        acc_norm = np.linalg.norm(accelerations)
        self.log(f"norm(v) = {velo_norm:.4f}, norm(a) = {acc_norm:.4f}")

        return steps