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
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
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
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
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