Example #1
0
/*
 * If symm != 0, symmetrize rdm1 and rdm2
 * For spin density matrix, return rdm2 e.g.
 *      [beta alpha beta^+ alpha]
 * transpose(1,0,2,3) to get the right order [alpha^+ beta beta^+ alpha]
 * na, nb, nlinka, nlinkb label the intermediate determinants
 * see ades_bcre_t1 and acre_bdes_t1 of fci_spin.c
 *
 * Note: na counts the alpha strings of intermediate determinants
 * but nb counts the beta strings of ket
 */
void FCIspindm12_drv(void (*dm12kernel)(),
                     double *rdm1, double *rdm2, double *bra, double *ket,
                     int norb, int na, int nb, int neleca, int nelecb,
                     int *link_indexa, int *link_indexb, int symm)
{
        const int nnorb = norb * norb;
        int strk, i, j;
        double *pdm1, *pdm2;
        memset(rdm1, 0, sizeof(double) * nnorb);
        memset(rdm2, 0, sizeof(double) * nnorb*nnorb);

#pragma omp parallel default(none) \
        shared(dm12kernel, bra, ket, norb, na, nb, neleca, nelecb, \
               link_indexa, link_indexb, rdm1, rdm2), \
        private(strk, i, pdm1, pdm2)
{
        pdm1 = (double *)malloc(sizeof(double) * nnorb);
        pdm2 = (double *)malloc(sizeof(double) * nnorb*nnorb);
        memset(pdm1, 0, sizeof(double) * nnorb);
        memset(pdm2, 0, sizeof(double) * nnorb*nnorb);
#pragma omp for schedule(dynamic, 2)
        for (strk = 0; strk < na; strk++) {
                (*dm12kernel)(pdm1, pdm2, bra, ket,
                              strk, norb, na, nb, neleca, nelecb,
                              link_indexa, link_indexb);
        }
#pragma omp critical
{
        for (i = 0; i < nnorb; i++) {
                rdm1[i] += pdm1[i];
        }
        for (i = 0; i < nnorb*nnorb; i++) {
                rdm2[i] += pdm2[i];
        }
}
        free(pdm1);
        free(pdm2);
}
        if (symm) {
                for (i = 0; i < norb; i++) {
                        for (j = 0; j < i; j++) {
                                rdm1[j*norb+i] = rdm1[i*norb+j];
                        }
                }
                for (i = 0; i < nnorb; i++) {
                        for (j = 0; j < i; j++) {
                                rdm2[j*nnorb+i] = rdm2[i*nnorb+j];
                        }
                }
        }
        _transpose_jikl(rdm2, norb);
}
Example #2
0
/*
 * Note! The returned rdm2 from FCI*kern* function corresponds to
 *      [(p^+ q on <bra|) r^+ s] = [p q^+ r^+ s]
 * in FCIrdm12kern_sf, FCIrdm12kern_spin0, FCIrdm12kern_a, ...
 * t1 is calculated as |K> = i^+ j|0>. by doing dot(t1.T,t1) to get "rdm2",
 * The ket part (k^+ l|0>) will generate the correct order for the last
 * two indices kl of rdm2(i,j,k,l), But the bra part (i^+ j|0>)^dagger
 * will generate an order of (i,j), which is identical to call a bra of
 * (<0|i j^+).  The so-obtained rdm2(i,j,k,l) corresponds to the
 * operator sequence i j^+ k^+ l. 
 *
 * symm = 1: symmetrizes the 1pdm, and 2pdm.  This is true only if bra == ket,
 * and the operators on bra are equivalent to those on ket, like
 *      FCIrdm12kern_a, FCIrdm12kern_b, FCIrdm12kern_sf, FCIrdm12kern_spin0
 * sym = 2: consider the particle permutation symmetry:
 *      E^j_l E^i_k = E^i_k E^j_l - \delta_{il}E^j_k + \dleta_{jk}E^i_l
 */
void FCIrdm12_drv(void (*dm12kernel)(),
                  double *rdm1, double *rdm2, double *bra, double *ket,
                  int norb, int na, int nb, int nlinka, int nlinkb,
                  int *link_indexa, int *link_indexb, int symm)
{
        const int nnorb = norb * norb;
        int strk, i, j, k, l, ib, blen;
        double *pdm1, *pdm2;
        memset(rdm1, 0, sizeof(double) * nnorb);
        memset(rdm2, 0, sizeof(double) * nnorb*nnorb);

        _LinkT *clinka = malloc(sizeof(_LinkT) * nlinka * na);
        _LinkT *clinkb = malloc(sizeof(_LinkT) * nlinkb * nb);
        FCIcompress_link(clinka, link_indexa, norb, na, nlinka);
        FCIcompress_link(clinkb, link_indexb, norb, nb, nlinkb);

#pragma omp parallel default(none) \
        shared(dm12kernel, bra, ket, norb, na, nb, nlinka, \
               nlinkb, clinka, clinkb, rdm1, rdm2, symm), \
        private(strk, i, ib, blen, pdm1, pdm2)
{
        pdm1 = calloc(nnorb, sizeof(double));
        pdm2 = calloc(nnorb*nnorb, sizeof(double));
#pragma omp for schedule(dynamic, 40)
        for (strk = 0; strk < na; strk++) {
                for (ib = 0; ib < nb; ib += BUFBASE) {
                        blen = MIN(BUFBASE, nb-ib);
                        (*dm12kernel)(pdm1, pdm2, bra, ket, blen, strk, ib,
                                      norb, na, nb, nlinka, nlinkb,
                                      clinka, clinkb, symm);
                }
        }
#pragma omp critical
{
        for (i = 0; i < nnorb; i++) {
                rdm1[i] += pdm1[i];
        }
        for (i = 0; i < nnorb*nnorb; i++) {
                rdm2[i] += pdm2[i];
        }
}
        free(pdm1);
        free(pdm2);
}
        free(clinka);
        free(clinkb);
        switch (symm) {
        case BRAKETSYM:
                for (i = 0; i < norb; i++) {
                        for (j = 0; j < i; j++) {
                                rdm1[j*norb+i] = rdm1[i*norb+j];
                        }
                }
                for (i = 0; i < nnorb; i++) {
                        for (j = 0; j < i; j++) {
                                rdm2[j*nnorb+i] = rdm2[i*nnorb+j];
                        }
                }
                _transpose_jikl(rdm2, norb);
                break;
        case PARTICLESYM:
// right 2pdm order is required here,  which transposes the cre/des on bra
                for (i = 0; i < norb; i++) {
                for (j = 0; j < i; j++) {
                        pdm1 = rdm2 + (i*nnorb+j)*norb;
                        pdm2 = rdm2 + (j*nnorb+i)*norb;
                        for (k = 0; k < norb; k++) {
                        for (l = 0; l < norb; l++) {
                                pdm2[l*nnorb+k] = pdm1[k*nnorb+l];
                        } }
// E^j_lE^i_k = E^i_kE^j_l + \delta_{il}E^j_k - \dleta_{jk}E^i_l
                        for (k = 0; k < norb; k++) {
                                pdm2[i*nnorb+k] += rdm1[j*norb+k];
                                pdm2[k*nnorb+j] -= rdm1[i*norb+k];
                        }
                } }
                break;
        default:
                _transpose_jikl(rdm2, norb);
        }
}