int get_ixyz(double lat[3][3], double cutoff) { int i, j, ixyz; int n = 3, lda = 3, info, lwork; double* work; double wkopt, w[3], a[9], lat2[3][3]; lwork = -1; for (i=0; i < 3; i++) for (j=0; j < 3; j++) lat2[i][j] = lat[i][0]*lat[j][0] + lat[i][1]*lat[j][1] + lat[i][2]*lat[j][2]; for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) a[i*3+j] = lat2[j][i]; dsyev("V", "U", &n, a, &lda, w, &wkopt, &lwork, &info); lwork = (int)wkopt; work = (double*) malloc(lwork*sizeof(double)); dsyev("V", "U", &n, a, &lda, w, work, &lwork, &info); if (info > 0 ) { fprintf(stderr, "Error: DSYEV ixyz"); exit(1); } ixyz = (int)(sqrt(1.0/w[0])*cutoff + 1); free(work); return ixyz; }
void get_fp(int flag, int nat, int ntyp, int ixyz, int nx, int lseg, int l, double lat[3][3], double rxyz[][3], int types[], double rcov[], double cutoff, double **lfp, double **sfp) { int iat, jat, ix, iy, iz, il, i, j; int n_sphere, ityp_sphere, nid, nids = l*(ntyp+1); int n_sphere_min = 1000000; int n_sphere_max = 0; int ind[nx*lseg]; double xi, yi, zi, xj, yj, zj, d2; double cutoff2 = cutoff*cutoff; double rxyz_sphere[nx][3]; double rcov_sphere[nx]; double amp[nx]; double fc, wc; double **om, *pvec; double omx[nids][nids], omy[nids][nids]; int lda, info, lwork; double wkopt; double *work, *w, *a; wc = cutoff / sqrt(2.0 * NC); fc = 1.0 / (2.0 * NC * wc * wc); for (iat = 0; iat < nat; iat++) { xi = rxyz[iat][0]; yi = rxyz[iat][1]; zi = rxyz[iat][2]; n_sphere = 0; for (jat = 0; jat < nat; jat++) { for (ix = -ixyz; ix <= ixyz; ix++) { for (iy = -ixyz; iy <= ixyz; iy++) { for (iz = -ixyz; iz <= ixyz; iz++) { xj = rxyz[jat][0] + ix*lat[0][0] + iy*lat[1][0] + iz*lat[2][0]; yj = rxyz[jat][1] + ix*lat[0][1] + iy*lat[1][1] + iz*lat[2][1]; zj = rxyz[jat][2] + ix*lat[0][2] + iy*lat[1][2] + iz*lat[2][2]; d2 = (xj-xi)*(xj-xi) + (yj-yi)*(yj-yi) + (zj-zi)*(zj-zi); if (d2 <= cutoff2) { n_sphere++; if (n_sphere > nx) { fprintf(stderr, "Error: cutoff is too large."); exit(1); } amp[n_sphere-1] = pow((1.0 - d2*fc), NC); rxyz_sphere[n_sphere-1][0] = xj; rxyz_sphere[n_sphere-1][1] = yj; rxyz_sphere[n_sphere-1][2] = zj; rcov_sphere[n_sphere-1] = rcov[jat]; if (jat == iat && ix == 0 && iy == 0 && iz == 0) { ityp_sphere = 0; } else { ityp_sphere = types[jat]; } for (il = 0; il < lseg; il++) { if (il == 0){ ind[il+lseg*(n_sphere-1)] = ityp_sphere * l + 0; } else { ind[il+lseg*(n_sphere-1)] = ityp_sphere * l + 1; } } } } } } } n_sphere_min = MIN(n_sphere_min, n_sphere); n_sphere_max = MAX(n_sphere_max, n_sphere); // big overlap matrix nid = lseg * n_sphere; if ( (om = (double **) malloc(sizeof(double)*nid)) == NULL) { fprintf(stderr, "Memory could not be allocated."); exit(1); } for (i = 0; i < nid; i++){ if ( (om[i] = (double *) malloc(sizeof(double)*nid)) == NULL) { fprintf(stderr, "Memory could not be allocated."); exit(1); } } if ( (pvec = (double *) malloc(sizeof(double)*nid)) == NULL ){ fprintf(stderr, "Memory could not be allocated."); exit(1);} creat_om( lseg, n_sphere, rxyz_sphere, rcov_sphere, amp, om ); if ( (a = (double *) malloc(sizeof(double)*nid*nid)) == NULL) { fprintf(stderr, "Memory could not be allocated."); exit(1);} if ( (w = (double *) malloc(sizeof(double)*nid)) == NULL) { fprintf(stderr, "Memory could not be allocated."); exit(1);} for (i = 0; i < nid; i++) for (j = 0; j< nid; j++) a[i*nid + j] = om[j][i]; lda = nid; lwork = -1; /// for (i = 0; i< nid*nid; i++) /// printf("a[%d]= %g\n", i, a[i]); dsyev("V", "U", &nid, a, &lda, w, &wkopt, &lwork, &info); lwork = (int)wkopt; work = (double*) malloc(lwork*sizeof(double)); dsyev("V", "U", &nid, a, &lda, w, work, &lwork, &info); if (info > 0 ) { fprintf(stderr, "Error: DSYEV 1"); exit(1); } if (w[0] < -1E-12) { printf("w[0] = %g\n", w[0]); fprintf(stderr, "Error: Negative w"); exit(1); } for (i = 0; i < nid; i++) pvec[i] = a[i + (nid-1)*nid]; if (flag <= 0 ) { for (i = 0; i < nid; i++) lfp[iat][i] = w[nid-1-i]; for (i = nid; i < nx; i++) lfp[iat][i] = 0.0; } free(w); free(a); free(work); if (flag >= 0 ){ /* contract */ nids = l*(ntyp+1); for (i = 0; i < nids; i++) { for (j = 0; j < nids; j++) { omx[i][j] = 0.0; omy[i][j] = 0.0; } } for (i = 0; i < nid; i++) for (j = 0; j < nid; j++) omx[ind[i]][ind[j]] = omx[ind[i]][ind[j]] + pvec[i] * om[i][j] * pvec[j]; if ( (a = (double *) malloc(sizeof(double)*nids*nids)) == NULL) { fprintf(stderr, "Memory could not be allocated."); exit(1);} if ( (w = (double *) malloc(sizeof(double)*nids)) == NULL) { fprintf(stderr, "Memory could not be allocated."); exit(1);} for (i = 0; i < nids; i++){ for (j = 0; j< nids; j++){ a[i*nids + j] = omx[j][i]; } } lda = nids; lwork = -1; dsyev("V", "U", &nids, a, &lda, w, &wkopt, &lwork, &info); lwork = (int)wkopt; work = (double*) malloc(lwork*sizeof(double)); dsyev("V", "U", &nids, a, &lda, w, work, &lwork, &info); for (i = 0; i < nids; i++) sfp[iat][i] = w[nids-1-i]; /* printf("iat = %d\n", iat); for (i = 0; i < nids; i++) printf(" %e ", sfp[iat][i]); printf("\n"); */ free(a); free(w); } free(work); for (i = 0; i < n_sphere; i++) free(om[i]); free(om); free(pvec); } printf("min %d, max %d\n", n_sphere_min, n_sphere_max); }
void toast::lapack::syev ( char * JOBZ, char * UPLO, int * N, double * A, int * LDA, double * W, double * WORK, int * LWORK, int * INFO ) { dsyev ( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO ); return; }