def _update_propars_atom(self, index): # Prepare some things charges = self._cache.load('charges', alloc=self.natom, tags='o')[0] begin = self.hebasis.get_atom_begin(index) nbasis = self.hebasis.get_atom_nbasis(index) # Compute charge and delta aim density charge, delta_aim = self._get_charge_and_delta_aim(index) charges[index] = charge # Preliminary check if charges[index] > nbasis: raise RuntimeError('The charge on atom %i becomes too positive: %f > %i. (infeasible)' % (index, charges[index], nbasis)) # Define the least-squares system A, B, C = self._get_he_system(index, delta_aim) # preconditioning scales = np.sqrt(np.diag(A)) A = A/scales/scales.reshape(-1,1) B /= scales # resymmetrize A due to potential round-off errors after rescaling # (minor thing) A = 0.5*(A + A.T) # Find solution # constraint for total population of pro-atom qp_r = np.array([np.ones(nbasis)/scales]) qp_s = np.array([-charges[index]]) # inequality constraints to keep coefficients larger than -1 or 0. lower_bounds = np.zeros(nbasis) for j0 in xrange(nbasis): lower_bounds[j0] = self.hebasis.get_lower_bound(index, j0)*scales[j0] # call the quadratic solver with modified b due to non-zero lower bound qp_a = A qp_b = B - np.dot(A, lower_bounds) qp_s -= np.dot(qp_r, lower_bounds) qps = QPSolver(qp_a, qp_b, qp_r, qp_s) qp_x = qps.find_brute()[1] # convert back to atom_pars atom_propars = qp_x + lower_bounds rrms = np.dot(np.dot(A, atom_propars) - 2*B, atom_propars)/C + 1 if rrms > 0: rrmsd = np.sqrt(rrms) else: rrmsd = -0.01 # correct for scales atom_propars /= scales if log.do_high: log(' %10i (%.0f%%):&%s' % (index, rrmsd*100, ' '.join('% 6.3f' % c for c in atom_propars))) self.cache.load('propars')[begin:begin+nbasis] = atom_propars
def solve(self, dms_output, focks_output): # interpolation only makes sense if there are two points assert self.nused >= 2 # Fill in the missing commutators self._complete_edots_matrix() assert not np.isnan(self.edots[:self.nused,:self.nused]).any() # Setup the equations b, e = self._setup_equations() # Check if solving these equations makes sense. if b.max() - b.min() == 0 and e.max() - e.min() == 0: raise NoSCFConvergence('Convergence criteria too tight for EDIIS') # solve the quadratic programming problem qps = QPSolver(b, e, np.ones((1,self.nused)), np.array([1.0]), eps=1e-6) if self.nused < 10: energy, coeffs = qps.find_brute() guess = None else: guess = np.zeros(self.nused) guess[e.argmax()] = 1.0 energy, coeffs = qps.find_local(guess, 1.0) # for debugging purposes (negligible computational overhead) try: qps.check_solution(coeffs) except: qps.log(guess) raise cn = qps.compute_cn(coeffs != 0.0) # assign extrapolated fock error = self._build_combinations(coeffs, dms_output, focks_output) return energy, coeffs, cn, 'E', error
def solve(self, dm_output, fock_output): '''Extrapolate a new density and/or fock matrix that should have the smallest commutator norm. **Arguments:** dm_output The output for the density matrix. If set to None, this is argument is ignored. fock_output The output for the Fock matrix. If set to None, this is argument is ignored. ''' # interpolation only makes sense if there are two points assert self.nused >= 2 # Fill in the missing commutators self._complete_edots_matrix() assert not np.isnan(self.edots[:self.nused, :self.nused]).any() # Setup the equations b, e = self._setup_equations() # Check if solving these equations makes sense. if b.max() - b.min() == 0 and e.max() - e.min() == 0: raise NoSCFConvergence('Convergence criteria too tight for EDIIS') # solve the quadratic programming problem qps = QPSolver(b, e, np.ones((1, self.nused)), np.array([1.0]), eps=1e-6) if self.nused < 10: energy, coeffs = qps.find_brute() guess = None else: guess = np.zeros(self.nused) guess[e.argmax()] = 1.0 energy, coeffs = qps.find_local(guess, 1.0) # for debugging purposes try: qps.check_solution(coeffs) except: qps.log(guess) raise cn = qps.compute_cn(coeffs != 0.0) # assign extrapolated fock self._build_combinations(coeffs, dm_output, fock_output) return energy, coeffs, cn, 'E'
def solve(self, dm_output, fock_output): '''Extrapolate a new density and/or fock matrix that should have the smallest commutator norm. **Arguments:** dm_output The output for the density matrix. If set to None, this is argument is ignored. fock_output The output for the Fock matrix. If set to None, this is argument is ignored. ''' # interpolation only makes sense if there are two points assert self.nused >= 2 # Fill in the missing commutators self._complete_edots_matrix() assert not np.isnan(self.edots[:self.nused,:self.nused]).any() # Setup the equations b, e = self._setup_equations() # Check if solving these equations makes sense. if b.max() - b.min() == 0 and e.max() - e.min() == 0: raise NoSCFConvergence('Convergence criteria too tight for EDIIS') # solve the quadratic programming problem qps = QPSolver(b, e, np.ones((1,self.nused)), np.array([1.0]), eps=1e-6) if self.nused < 10: energy, coeffs = qps.find_brute() guess = None else: guess = np.zeros(self.nused) guess[e.argmax()] = 1.0 energy, coeffs = qps.find_local(guess, 1.0) # for debugging purposes try: qps.check_solution(coeffs) except: qps.log(guess) raise cn = qps.compute_cn(coeffs != 0.0) # assign extrapolated fock self._build_combinations(coeffs, dm_output, fock_output) return energy, coeffs, cn, 'E'
def _update_propars_atom(self, index): # Prepare some things charges = self._cache.load('charges', alloc=self.natom, tags='o')[0] begin = self.hebasis.get_atom_begin(index) nbasis = self.hebasis.get_atom_nbasis(index) # Compute charge and delta aim density charge, delta_aim = self._get_charge_and_delta_aim(index) charges[index] = charge # Preliminary check if charges[index] > nbasis: raise RuntimeError( 'The charge on atom %i becomes too positive: %f > %i. (infeasible)' % (index, charges[index], nbasis)) # Define the least-squares system A, B, C = self._get_he_system(index, delta_aim) # preconditioning scales = np.sqrt(np.diag(A)) A = A / scales / scales.reshape(-1, 1) B /= scales # resymmetrize A due to potential round-off errors after rescaling # (minor thing) A = 0.5 * (A + A.T) # Find solution # constraint for total population of pro-atom qp_r = np.array([np.ones(nbasis) / scales]) qp_s = np.array([-charges[index]]) # inequality constraints to keep coefficients larger than -1 or 0. lower_bounds = np.zeros(nbasis) for j0 in xrange(nbasis): lower_bounds[j0] = self.hebasis.get_lower_bound(index, j0) * scales[j0] # call the quadratic solver with modified b due to non-zero lower bound qp_a = A qp_b = B - np.dot(A, lower_bounds) qp_s -= np.dot(qp_r, lower_bounds) qps = QPSolver(qp_a, qp_b, qp_r, qp_s) qp_x = qps.find_brute()[1] # convert back to atom_pars atom_propars = qp_x + lower_bounds rrms = np.dot(np.dot(A, atom_propars) - 2 * B, atom_propars) / C + 1 if rrms > 0: rrmsd = np.sqrt(rrms) else: rrmsd = -0.01 # correct for scales atom_propars /= scales if log.do_high: log(' %10i (%.0f%%):&%s' % (index, rrmsd * 100, ' '.join('% 6.3f' % c for c in atom_propars))) self.cache.load('propars')[begin:begin + nbasis] = atom_propars