コード例 #1
0
ファイル: base.py プロジェクト: ryanabbit/horton
    def do_moments(self):
        if log.do_medium:
            log('Computing cartesian and pure AIM multipoles and radial AIM moments.'
                )

        ncart = get_ncart_cumul(self.lmax)
        cartesian_multipoles, new1 = self._cache.load(
            'cartesian_multipoles',
            alloc=(self._system.natom, ncart),
            tags='o')

        npure = get_npure_cumul(self.lmax)
        pure_multipoles, new1 = self._cache.load('pure_multipoles',
                                                 alloc=(self._system.natom,
                                                        npure),
                                                 tags='o')

        nrad = self.lmax + 1
        radial_moments, new2 = self._cache.load('radial_moments',
                                                alloc=(self._system.natom,
                                                       nrad),
                                                tags='o')

        if new1 or new2:
            self.do_partitioning()
            for i in xrange(self._system.natom):
                # 1) Define a 'window' of the integration grid for this atom
                center = self._system.coordinates[i]
                grid = self.get_grid(i)

                # 2) Compute the AIM
                aim = self.get_moldens(i) * self.cache.load('at_weights', i)

                # 3) Compute weight corrections (TODO: needs to be assessed!)
                wcor = self.get_wcor(i)

                # 4) Compute Cartesian multipole moments
                # The minus sign is present to account for the negative electron
                # charge.
                cartesian_multipoles[i] = -grid.integrate(
                    aim, wcor, center=center, lmax=self.lmax, mtype=1)
                cartesian_multipoles[i, 0] += self.system.pseudo_numbers[i]

                # 5) Compute Pure multipole moments
                # The minus sign is present to account for the negative electron
                # charge.
                pure_multipoles[i] = -grid.integrate(
                    aim, wcor, center=center, lmax=self.lmax, mtype=2)
                pure_multipoles[i, 0] += self.system.pseudo_numbers[i]

                # 6) Compute Radial moments
                # For the radial moments, it is not common to put a minus sign
                # for the negative electron charge.
                radial_moments[i] = grid.integrate(aim,
                                                   wcor,
                                                   center=center,
                                                   lmax=self.lmax,
                                                   mtype=3)
コード例 #2
0
ファイル: base.py プロジェクト: stevenvdb/horton
    def do_moments(self):
        ncart = get_ncart_cumul(self.lmax)
        cartesian_multipoles, new1 = self._cache.load('cartesian_multipoles', alloc=(self.natom, ncart), tags='o')

        npure = get_npure_cumul(self.lmax)
        pure_multipoles, new1 = self._cache.load('pure_multipoles', alloc=(self.natom, npure), tags='o')

        nrad = self.lmax+1
        radial_moments, new2 = self._cache.load('radial_moments', alloc=(self.natom, nrad), tags='o')

        if new1 or new2:
            self.do_partitioning()
            if log.do_medium:
                log('Computing cartesian and pure AIM multipoles and radial AIM moments.')

            for i in xrange(self.natom):
                # 1) Define a 'window' of the integration grid for this atom
                center = self.coordinates[i]
                grid = self.get_grid(i)

                # 2) Compute the AIM
                aim = self.get_moldens(i)*self.cache.load('at_weights', i)

                # 3) Compute weight corrections
                wcor = self.get_wcor(i)

                # 4) Compute Cartesian multipole moments
                # The minus sign is present to account for the negative electron
                # charge.
                cartesian_multipoles[i] = -grid.integrate(aim, wcor, center=center, lmax=self.lmax, mtype=1)
                cartesian_multipoles[i, 0] += self.pseudo_numbers[i]

                # 5) Compute Pure multipole moments
                # The minus sign is present to account for the negative electron
                # charge.
                pure_multipoles[i] = -grid.integrate(aim, wcor, center=center, lmax=self.lmax, mtype=2)
                pure_multipoles[i, 0] += self.pseudo_numbers[i]

                # 6) Compute Radial moments
                # For the radial moments, it is not common to put a minus sign
                # for the negative electron charge.
                radial_moments[i] = grid.integrate(aim, wcor, center=center, lmax=self.lmax, mtype=3)
コード例 #3
0
def wpart_slow_analysis(wpart, mol):
    """An additional and optional analysis for horton-wpart.py

       This analysis is currently not included in horton/part because it would
       imply additional changes in the API.

       **Arguments:**

       wpart
            An instance of a WPart class

       mol
            An instance of IOData. This instance must at least contain an
            obasis, exp_alpha and exp_beta (in case of unrestricted spin) object.
    """

    # A) Compute AIM overlap operators
    # --------------------------------
    # These are not included in the output by default because they occupy too
    # much space.
    wpart.do_partitioning()
    npure = get_npure_cumul(wpart.lmax)
    for index in xrange(wpart.natom):
        if log.do_medium:
            log('Computing overlap matrices for atom %i.' % index)

        # Prepare solid harmonics on grids.
        grid = wpart.get_grid(index)
        if wpart.lmax > 0:
            work = np.zeros((grid.size, npure - 1), float)
            work[:, 0] = grid.points[:, 2] - wpart.coordinates[index, 2]
            work[:, 1] = grid.points[:, 0] - wpart.coordinates[index, 0]
            work[:, 2] = grid.points[:, 1] - wpart.coordinates[index, 1]
            if wpart.lmax > 1:
                fill_pure_polynomials(work, wpart.lmax)
        at_weights = wpart.cache.load('at_weights', index)

        # Convert the weight functions to AIM overlap operators.
        counter = 0
        overlap_operators = {}
        for l in xrange(wpart.lmax + 1):
            for m in xrange(-l, l + 1):
                if counter > 0:
                    tmp = at_weights * work[:, counter - 1]
                else:
                    tmp = at_weights
                op = mol.obasis.compute_grid_density_fock(
                    grid.points, grid.weights, tmp)
                overlap_operators['olp_%05i' % counter] = op
                counter += 1

        wpart.cache.dump(('overlap_operators', index), overlap_operators)

    # Correct the s-type overlap operators such that the sum is exactly
    # equal to the total overlap.
    error_overlap = mol.obasis.compute_overlap()
    for index in xrange(wpart.natom):
        atom_overlap = wpart.cache.load('overlap_operators',
                                        index)['olp_00000']
        error_overlap -= atom_overlap
    error_overlap /= wpart.natom
    for index in xrange(wpart.natom):
        atom_overlap = wpart.cache.load('overlap_operators',
                                        index)['olp_00000']
        atom_overlap += error_overlap

    # A') Construct the list of operators with a logical ordering
    #   * outer loop: s, pz, px, py, ...
    #   * inner loop: atoms
    operators = []
    for ipure in xrange(npure):
        for iatom in xrange(wpart.natom):
            operators.append(
                wpart.cache.load('overlap_operators',
                                 iatom)['olp_%05i' % ipure])

    # B) Compute Wiberg bond orders from the first-order density matrix
    # -----------------------------------------------------------------
    # This is inherently limited because the second-order density matrix is
    # required to compute a proper density matrix. For a pure single-reference
    # method like HF, this is fine. In case of DFT, the interpretation of the
    # bond-orders is dicy. In case of Post-HF, these bond orders are plain
    # wrong.
    if log.do_medium:
        log('Computing bond orders.')
    dm_full = mol.get_dm_full()
    dm_spin = mol.get_dm_spin()
    if dm_spin is None:
        # closed-shell case
        dm_alpha = dm_full * 0.5
        bond_orders, valences, free_valences = compute_bond_orders_cs(
            dm_alpha, operators)
    else:
        # open-shell case
        dm_alpha = 0.5 * (dm_full + dm_spin)
        dm_beta = 0.5 * (dm_full - dm_spin)
        dm_beta.iadd(dm_spin, -1.0)
        dm_beta.iscale(0.5)
        bond_orders, valences, free_valences = compute_bond_orders_os(
            dm_alpha, dm_beta, operators)
    wpart.cache.dump('bond_orders', bond_orders, tags='o')
    wpart.cache.dump('valences', valences, tags='o')
    wpart.cache.dump('free_valences', free_valences, tags='o')

    # C) Non-interacting response
    # ---------------------------
    # The current implementation is only sensible for a single-reference method
    # as it is based on HF/KS orbitals. The results are meaningful for both
    # HF and KS orbitals.
    if log.do_medium:
        log('Computing Xs response.')
    if dm_spin is None:
        if not hasattr(mol, 'exp_alpha'):
            return
        xs_response = 2 * compute_noninteracting_response(
            mol.exp_alpha, operators)
    else:
        if not (hasattr(mol, 'exp_alpha') and hasattr(mol, 'exp_beta')):
            return
        xs_response = compute_noninteracting_response(mol.exp_alpha, operators)
        xs_response += compute_noninteracting_response(mol.exp_beta, operators)
    wpart.cache.dump('noninteracting_response', xs_response, tags='o')
コード例 #4
0
ファイル: wpart.py プロジェクト: QuantumElephant/horton
def wpart_slow_analysis(wpart, mol):
    """An additional and optional analysis for horton-wpart.py

       This analysis is currently not included in horton/part because it would
       imply additional changes in the API.

       **Arguments:**

       wpart
            An instance of a WPart class

       mol
            An instance of IOData. This instance must at least contain an
            obasis, exp_alpha and exp_beta (in case of unrestricted spin) object.
    """

    # A) Compute AIM overlap operators
    # --------------------------------
    # These are not included in the output by default because they occupy too
    # much space.
    wpart.do_partitioning()
    npure = get_npure_cumul(wpart.lmax)
    for index in xrange(wpart.natom):
        if log.do_medium:
            log('Computing overlap matrices for atom %i.' % index)

        # Prepare solid harmonics on grids.
        grid = wpart.get_grid(index)
        if wpart.lmax > 0:
            work = np.zeros((grid.size, npure - 1), float)
            work[:, 0] = grid.points[:, 2] - wpart.coordinates[index, 2]
            work[:, 1] = grid.points[:, 0] - wpart.coordinates[index, 0]
            work[:, 2] = grid.points[:, 1] - wpart.coordinates[index, 1]
            if wpart.lmax > 1:
                fill_pure_polynomials(work, wpart.lmax)
        at_weights = wpart.cache.load('at_weights', index)

        # Convert the weight functions to AIM overlap operators.
        counter = 0
        overlap_operators = {}
        for l in xrange(wpart.lmax + 1):
            for m in xrange(-l, l + 1):
                if counter > 0:
                    tmp = at_weights * work[:, counter - 1]
                else:
                    tmp = at_weights
                op = mol.obasis.compute_grid_density_fock(grid.points, grid.weights, tmp)
                overlap_operators['olp_%05i' % counter] = op
                counter += 1

        wpart.cache.dump(('overlap_operators', index), overlap_operators)

    # Correct the s-type overlap operators such that the sum is exactly
    # equal to the total overlap.
    error_overlap = mol.obasis.compute_overlap()
    for index in xrange(wpart.natom):
        atom_overlap = wpart.cache.load('overlap_operators', index)['olp_00000']
        error_overlap -= atom_overlap
    error_overlap /= wpart.natom
    for index in xrange(wpart.natom):
        atom_overlap = wpart.cache.load('overlap_operators', index)['olp_00000']
        atom_overlap += error_overlap

    # A') Construct the list of operators with a logical ordering
    #   * outer loop: s, pz, px, py, ...
    #   * inner loop: atoms
    operators = []
    for ipure in xrange(npure):
        for iatom in xrange(wpart.natom):
            operators.append(wpart.cache.load('overlap_operators', iatom)['olp_%05i' % ipure])

    # B) Compute Wiberg bond orders from the first-order density matrix
    # -----------------------------------------------------------------
    # This is inherently limited because the second-order density matrix is
    # required to compute a proper density matrix. For a pure single-reference
    # method like HF, this is fine. In case of DFT, the interpretation of the
    # bond-orders is dicy. In case of Post-HF, these bond orders are plain
    # wrong.
    if log.do_medium:
        log('Computing bond orders.')
    dm_full = mol.get_dm_full()
    dm_spin = mol.get_dm_spin()
    if dm_spin is None:
        # closed-shell case
        dm_alpha = dm_full*0.5
        bond_orders, valences, free_valences = compute_bond_orders_cs(dm_alpha, operators)
    else:
        # open-shell case
        dm_alpha = 0.5*(dm_full + dm_spin)
        dm_beta = 0.5*(dm_full - dm_spin)
        dm_beta.iadd(dm_spin, -1.0)
        dm_beta.iscale(0.5)
        bond_orders, valences, free_valences = compute_bond_orders_os(dm_alpha, dm_beta, operators)
    wpart.cache.dump('bond_orders', bond_orders, tags='o')
    wpart.cache.dump('valences', valences, tags='o')
    wpart.cache.dump('free_valences', free_valences, tags='o')

    # C) Non-interacting response
    # ---------------------------
    # The current implementation is only sensible for a single-reference method
    # as it is based on HF/KS orbitals. The results are meaningful for both
    # HF and KS orbitals.
    if log.do_medium:
        log('Computing Xs response.')
    if dm_spin is None:
        if not hasattr(mol, 'exp_alpha'):
            return
        xs_response = 2 * compute_noninteracting_response(mol.exp_alpha, operators)
    else:
        if not (hasattr(mol, 'exp_alpha') and hasattr(mol, 'exp_beta')):
            return
        xs_response = compute_noninteracting_response(mol.exp_alpha, operators)
        xs_response += compute_noninteracting_response(mol.exp_beta, operators)
    wpart.cache.dump('noninteracting_response', xs_response, tags='o')