Example #1
0
    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
Example #2
0
 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
Example #3
0
    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'
Example #4
0
    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'
Example #5
0
    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