int qdpack_matrix_eigen_hermv(qdpack_matrix_t *m, qdpack_matrix_t *eval, qdpack_matrix_t *evec, int sort_order) { int i; gsl_vector *eval_vector; if (hermv_workspace == NULL) { hermv_workspace = gsl_eigen_hermv_alloc(m->m); } eval_vector = gsl_vector_alloc(eval->m); gsl_eigen_hermv(m->data, eval_vector, evec->data, hermv_workspace); gsl_eigen_hermv_sort(eval_vector, evec->data, sort_order); for (i = 0; i < eval->m; i++) { gsl_complex z; GSL_SET_COMPLEX(&z, gsl_vector_get(eval_vector, i), 0.0); qdpack_matrix_set(eval, i, 0, z); } return 0; }
void test_eigen_herm_matrix(const gsl_matrix_complex * m, size_t count, const char * desc) { const size_t N = m->size1; gsl_matrix_complex * A = gsl_matrix_complex_alloc(N, N); gsl_vector * eval = gsl_vector_alloc(N); gsl_vector * evalv = gsl_vector_alloc(N); gsl_vector * x = gsl_vector_alloc(N); gsl_vector * y = gsl_vector_alloc(N); gsl_matrix_complex * evec = gsl_matrix_complex_alloc(N, N); gsl_eigen_herm_workspace * w = gsl_eigen_herm_alloc(N); gsl_eigen_hermv_workspace * wv = gsl_eigen_hermv_alloc(N); gsl_matrix_complex_memcpy(A, m); gsl_eigen_hermv(A, evalv, evec, wv); test_eigen_herm_results(m, evalv, evec, count, desc, "unsorted"); gsl_matrix_complex_memcpy(A, m); gsl_eigen_herm(A, eval, w); /* sort eval and evalv */ gsl_vector_memcpy(x, eval); gsl_vector_memcpy(y, evalv); gsl_sort_vector(x); gsl_sort_vector(y); test_eigenvalues_real(y, x, desc, "unsorted"); gsl_eigen_hermv_sort(evalv, evec, GSL_EIGEN_SORT_VAL_ASC); test_eigen_herm_results(m, evalv, evec, count, desc, "val/asc"); gsl_eigen_hermv_sort(evalv, evec, GSL_EIGEN_SORT_VAL_DESC); test_eigen_herm_results(m, evalv, evec, count, desc, "val/desc"); gsl_eigen_hermv_sort(evalv, evec, GSL_EIGEN_SORT_ABS_ASC); test_eigen_herm_results(m, evalv, evec, count, desc, "abs/asc"); gsl_eigen_hermv_sort(evalv, evec, GSL_EIGEN_SORT_ABS_DESC); test_eigen_herm_results(m, evalv, evec, count, desc, "abs/desc"); gsl_matrix_complex_free(A); gsl_vector_free(eval); gsl_vector_free(evalv); gsl_vector_free(x); gsl_vector_free(y); gsl_matrix_complex_free(evec); gsl_eigen_herm_free(w); gsl_eigen_hermv_free(wv); } /* test_eigen_herm_matrix() */
/* computes the svd of a complex matrix. Missing in gsl. */ int svd(gsl_matrix_complex *A, gsl_matrix_complex *V, gsl_vector *S) { int n = A->size1; gsl_eigen_hermv_workspace *gsl_work = gsl_eigen_hermv_alloc(n); gsl_matrix_complex *Asq = gsl_matrix_complex_alloc(n, n); gsl_complex zero = gsl_complex_rect(0., 0.); gsl_complex one = gsl_complex_rect(1., 0.); gsl_vector *e = gsl_vector_alloc(n); gsl_matrix_complex *U = gsl_matrix_complex_alloc(n, n); gsl_blas_zgemm(CblasNoTrans, CblasConjTrans, one, A, A, zero, Asq); gsl_eigen_hermv(Asq, e, U, gsl_work); gsl_eigen_hermv_sort(e, U, GSL_EIGEN_SORT_VAL_DESC); gsl_blas_zgemm(CblasConjTrans, CblasNoTrans, one, A, A, zero, Asq); gsl_eigen_hermv(Asq, e, V, gsl_work); gsl_eigen_hermv_sort(e, V, GSL_EIGEN_SORT_VAL_DESC); gsl_blas_zgemm(CblasNoTrans, CblasNoTrans, one, A, V, zero, Asq); gsl_blas_zgemm(CblasConjTrans, CblasNoTrans, one, U, Asq, zero, A); for(int i=0; i<n; i++){ gsl_complex x = gsl_matrix_complex_get(A, i, i); double phase = gsl_complex_arg(gsl_complex_mul_real(x, 1./sqrt(e->data[i]))); gsl_vector_complex_view U_col = gsl_matrix_complex_column(U, i); gsl_vector_complex_scale(&U_col.vector, gsl_complex_polar(1., phase)); gsl_vector_set(S, i, sqrt(gsl_vector_get(e, i))); } gsl_matrix_complex_memcpy(A, U); gsl_vector_free(e); gsl_matrix_complex_free(U); gsl_matrix_complex_free(Asq); gsl_eigen_hermv_free(gsl_work); return 0; }
/* --- * Process the density matrix for time t (calc. expectations values, * store to file, etc.) */ int rho_store_cb(qdpack_operator_t *rho_t, double t, qdpack_hilbert_space_t *qs, qdpack_simulation_t *sp) { int i, j, ri; qdpack_complex N_expt, op1_expt, op2_expt; char filename[1024], row[16384]; qdpack_operator_t *dm_part; if (USE_EIGENBASIS == 1) { gsl_eigen_hermv(sp->H_t, sp->eval, sp->evec, sp->w); gsl_eigen_hermv_sort(sp->eval, sp->evec, GSL_EIGEN_SORT_VAL_ASC); gsl_blas_zgemm(CblasConjTrans, CblasNoTrans, QDPACK_COMPLEX_ONE, sp->evec, rho_t, QDPACK_COMPLEX_ZERO, rho_tmp_t); gsl_blas_zgemm(CblasNoTrans, CblasNoTrans, QDPACK_COMPLEX_ONE, rho_tmp_t, sp->evec, QDPACK_COMPLEX_ZERO, rho_eb_t); } else { qdpack_operator_memcpy(rho_eb_t, rho_t); } /* -- store expectation value of sigma z -- * / N_expt = qdpack_operator_expectation_value(rho_t, sp->N_op[i]); snprintf(filename, sizeof(filename), "%s/sigma_z_expt_%d%s_x_%.2f_y_%.2f.dat", DATADIR, i, sp->simsig, sp->x, sp->y); snprintf(row, sizeof(row), "%f\t%f\t%f", t, QDPACK_REAL(N_expt), QDPACK_IMAG(N_expt)); qdpack_file_row_add(filename, row); */ //if (1) // if ( abs(sin(p->h_td_w * t)) < 0.1 ) // close to bias point if (t > sp->Tf/2.0) { pe_expt_sum += QDPACK_REAL(qdpack_operator_get(rho_eb_t, 1, 1)); pe_expt_no++; } return 0; }
int ComputeUnitaryMatrix_GSL(gsl_matrix_complex * const M, gsl_matrix * const U) { int result; gsl_vector *eval, *order; gsl_matrix_complex *evec; gsl_eigen_hermv_workspace *w; unsigned int i, j; gsl_complex z; float real, imag; // Allocations eval = gsl_vector_alloc(M->size1); order = gsl_vector_alloc(M->size1); evec = gsl_matrix_complex_alloc(M->size1, M->size1); w = gsl_eigen_hermv_alloc(M->size1); #ifdef VERBOSE PrintGSLMatrixComplex(M, "Computing Unitary Matrix for M"); #endif result = gsl_eigen_hermv(M, eval, evec, w); #ifdef VERBOSE fprintf(stderr, "Result from gsl_eigen_hermv = %d\n", result); #endif if(result != GSL_SUCCESS) { fprintf(stderr, "ERROR %d when calling gsl_eigen_hermv()!\n", result); return -1; } if(HasNaN(evec) == true) return -1; // Get ascending order of values in eval // PrintGSLVector(eval, "eval (BEFORE)"); for(i = 0; i < order->size; i++) gsl_vector_set(order, i, i); QuickSort(eval, order, 0, order->size-1); #ifdef VERBOSE PrintGSLVector(eval, "eval (AFTER)"); PrintGSLVector(order, "order (AFTER)"); PrintGSLMatrixComplex(evec, "evec"); #endif for(i = 0; i < U->size1; i++) { for(j = 0; j < U->size2; j++) { z = gsl_matrix_complex_get(evec, i, gsl_vector_get(order,j)); real = GSL_REAL(z); imag = GSL_IMAG(z); gsl_matrix_set(U, i, j, sqrt(real*real + imag*imag)); } } // Free gsl_eigen_hermv_free(w); gsl_matrix_complex_free(evec); gsl_vector_free(order); gsl_vector_free(eval); return GSL_SUCCESS; }
int gsl_eigen_genhermv (gsl_matrix_complex * A, gsl_matrix_complex * B, gsl_vector * eval, gsl_matrix_complex * evec, gsl_eigen_genhermv_workspace * w) { const size_t N = A->size1; /* check matrix and vector sizes */ if (N != A->size2) { GSL_ERROR ("matrix must be square to compute eigenvalues", GSL_ENOTSQR); } else if ((N != B->size1) || (N != B->size2)) { GSL_ERROR ("B matrix dimensions must match A", GSL_EBADLEN); } else if (eval->size != N) { GSL_ERROR ("eigenvalue vector must match matrix size", GSL_EBADLEN); } else if (evec->size1 != evec->size2) { GSL_ERROR ("eigenvector matrix must be square", GSL_ENOTSQR); } else if (evec->size1 != N) { GSL_ERROR ("eigenvector matrix has wrong size", GSL_EBADLEN); } else if (w->size != N) { GSL_ERROR ("matrix size does not match workspace", GSL_EBADLEN); } else { int s; /* compute Cholesky factorization of B */ s = gsl_linalg_complex_cholesky_decomp(B); if (s != GSL_SUCCESS) return s; /* B is not positive definite */ /* transform to standard hermitian eigenvalue problem */ gsl_eigen_genherm_standardize(A, B); /* compute eigenvalues and eigenvectors */ s = gsl_eigen_hermv(A, eval, evec, w->hermv_workspace_p); if (s != GSL_SUCCESS) return s; /* backtransform eigenvectors: evec -> L^{-H} evec */ gsl_blas_ztrsm(CblasLeft, CblasLower, CblasConjTrans, CblasNonUnit, GSL_COMPLEX_ONE, B, evec); /* the blas call destroyed the normalization - renormalize */ genhermv_normalize_eigenvectors(evec); return GSL_SUCCESS; } } /* gsl_eigen_genhermv() */
/* --- * Program starts here. * */ int main(int argc, char **argv) { qdpack_hilbert_space_t *qs; qdpack_operator_t *rho_q, *rho_c; qdpack_operator_t *rho0, *rho_t; qdpack_operator_list_t dm_list; int qsn, i, noff, nsize, npeak; double Navg, fw, fA, phi, Gc, Gq, gqc, x, y, pDelta, G1, G2, T1, T2; double yi, yf, yd; qdpack_simulation_t param; qdpack_simulation_init(¶m); if (argc != 5) { printf("usage: %s x y-init y-delta y-final\n", argv[0]); exit(0); } snprintf(DATADIR, sizeof(DATADIR), DATADIR_TEMPLATE, argv[0]); // ---- PARAMETERS START // // frequency in units of GHz and time in units of ns // // // x = coefficient of sigma_z in qubit hamiltonian, in units of driving frequency // x = epsilon / (fw * 2 * M_PI) // // y = the driving amplitude in units of driving frequency // y = h_td_A / (fw * 2 * M_PI) // // get values from command line parameters x = strtod(argv[1], NULL); yi = strtod(argv[2], NULL); yd = strtod(argv[3], NULL); yf = strtod(argv[4], NULL); fw = 1.0; // driving frequency pDelta = fw/300.0; // coefficient of sigma_x in qubit hamiltonain T1 = 1000.0 / fw; // relaxation time T2 = 5.0 / fw; // dephasing time param.Ti = 0.0; param.Tf = T1 * 5.0; // must be large enough to reach the steady state param.dT = (param.Tf-param.Ti) / 1000.0; // ---- PARAMETERS END // // setup parameter vectors // param.epsilon = epsilon; param.delta = delta; simulation.ho_w = ho_w; param.x = x; for (i = 0; i < 10; i++) { param.epsilon[i] *= 2*M_PI; param.delta[i] *= 2*M_PI; simulation.ho_w[i] *= 2*M_PI; lambda[i] = (double *)calloc(10, sizeof(double)); } param.lambda = lambda; param.cont_basis_transform = 0; param.h_td_w = fw * 2 * M_PI; G1 = 1.0/T1; G2 = 1.0/T2; /* * create a new quantum system object */ qs = qdpack_hilbert_space_new(); qdpack_hilbert_space_add(qs, 2); qsn = qdpack_hilbert_space_nstates(qs); qdpack_hilbert_space_print(qs); param.qs = qs; // setup hamiltonian functions param.H0_func = (hamiltonian_func_t)hamiltonian_qubits; param.H1_func = (hamiltonian_func_t)hamiltonian_z_drive; param.Ht_func = (hamiltonian_td_func_t)hamiltonian_sd_t; // preallocate matrices param.H_t = qdpack_operator_alloc(qsn, qsn); param.H0 = qdpack_operator_alloc(qsn, qsn); param.H1 = qdpack_operator_alloc(qsn, qsn); param.N_op[0] = qdpack_operator_alloc(qsn, qsn); operator_ho_N(param.N_op[0], qs, 0, 0); /* * Set up dissipation * */ param.wT = 0.0 * 2 * M_PI; param.do_n = 0; Navg = 0; // zero temperature // relaxation param.do_a[param.do_n] = qdpack_operator_alloc(qsn, qsn); operator_ho_lowering(param.do_a[param.do_n], qs, 0, 0); param.do_ad[param.do_n] = qdpack_operator_alloc(qsn, qsn); operator_ho_raising(param.do_ad[param.do_n], qs, 0, 0); param.do_g1[param.do_n] = G1 * (1 + Navg); // relaxation rate param.do_g2[param.do_n] = G1 * Navg; // excitation rate param.do_n++; // dephasing param.do_a[param.do_n] = qdpack_operator_alloc(qsn, qsn); operator_sigma_z(param.do_a[param.do_n], qs, 0); param.do_ad[param.do_n] = qdpack_operator_alloc(qsn, qsn); operator_sigma_z(param.do_ad[param.do_n], qs, 0); param.do_g1[param.do_n] = G2 / 2; param.do_g2[param.do_n] = G2 / 2; param.do_n++; param.eval = gsl_vector_alloc(2); param.evec = qdpack_operator_alloc(2, 2); param.w = gsl_eigen_hermv_alloc(2); snprintf(param.simsig, sizeof(param.simsig), "_dDelta_%.3f_G1_%.3f_G2_%.4f_fw_%.3f", pDelta, G1, G2, fw); /* storage space for final rho */ param.rho_f = qdpack_operator_alloc(qsn, qsn); rho_eb_t = qdpack_operator_alloc(qsn, qsn); rho_tmp_t = qdpack_operator_alloc(qsn, qsn); /* * Setup initial state */ rho_q = qdpack_dm_pure_TLS(0.0); qdpack_operator_list_init(&dm_list); qdpack_operator_list_append(&dm_list, rho_q); rho0 = qdpack_operator_alloc(qsn, qsn); qdpack_operator_tensor(rho0, qs, &dm_list); delta[0] = pDelta * (2*M_PI); epsilon[0] = x * fw * (2*M_PI); for (y = yi; y <= yf; y += yd) { pe_expt_sum = 0.0; pe_expt_no = 0; param.y = y; param.h_td_A = y * fw * 2 * M_PI; printf("ITERATION: %s: x = %f, y = %f\n", param.simsig, param.x, param.y); if (USE_EIGENBASIS == 1) { param.H0_func(param.H0, qs, ¶m); gsl_eigen_hermv(param.H0, param.eval, param.evec, param.w); gsl_eigen_hermv_sort(param.eval, param.evec, GSL_EIGEN_SORT_VAL_ASC); // rho_0 = S rho_eb_0 S^{-1} gsl_blas_zgemm(CblasNoTrans, CblasNoTrans, QDPACK_COMPLEX_ONE, param.evec, rho_q, QDPACK_COMPLEX_ZERO, rho_tmp_t); gsl_blas_zgemm(CblasNoTrans, CblasConjTrans, QDPACK_COMPLEX_ONE, rho_tmp_t, param.evec, QDPACK_COMPLEX_ZERO, rho0); qdpack_operator_free(param.H0); } /* * Evolve the quantum system until time t = T, where the steady state * is assumed to be reached. * */ //if (qdpack_evolve_dm_lme_ib_t(qs, rho0, ¶m, rho_store_cb) != 0) if (qdpack_evolve_dm_lme_t(qs, rho0, ¶m, rho_store_cb) != 0) { fprintf(stderr, "Evolution of the quantum system failed.\n"); return -1; } rho_store_final_cb(param.rho_f, param.Tf, qs, ¶m); } return 0; }
static int mc_eigen(lua_State *L) /* (-1,+2,e) */ { mMatComplex *m = qlua_checkMatComplex(L, 1); gsl_matrix_complex_view mx; gsl_eigen_hermv_workspace *w; gsl_vector *ev; mVecReal *lambda; mMatComplex *trans; mMatComplex *tmp; int n; int i; int lo, hi; switch (lua_gettop(L)) { case 1: if (m->l_size != m->r_size) return luaL_error(L, "matrix:eigen() expects square matrix"); lo = 0; hi = m->l_size; break; case 2: lo = 0; hi = luaL_checkint(L, 2); if ((hi > m->l_size) || (hi > m->r_size)) return slice_out(L); break; case 3: lo = luaL_checkint(L, 2); hi = luaL_checkint(L, 3); if ((lo >= hi) || (lo > m->l_size) || (lo > m->r_size) || (hi > m->l_size) || (hi > m->r_size)) return slice_out(L); break; default: return luaL_error(L, "matrix:eigen(): illegal arguments"); } n = hi - lo; mx = gsl_matrix_complex_submatrix(m->m, lo, lo, n, n); tmp = qlua_newMatComplex(L, n, n); gsl_matrix_complex_memcpy(tmp->m, &mx.matrix); lambda = qlua_newVecReal(L, n); trans = qlua_newMatComplex(L, n, n); ev = new_gsl_vector(L, n); w = gsl_eigen_hermv_alloc(n); if (w == 0) { lua_gc(L, LUA_GCCOLLECT, 0); w = gsl_eigen_hermv_alloc(n); if (w == 0) luaL_error(L, "not enough memory"); } if (gsl_eigen_hermv(tmp->m, ev, trans->m, w)) luaL_error(L, "matrix:eigen() failed"); if (gsl_eigen_hermv_sort(ev, trans->m, GSL_EIGEN_SORT_VAL_ASC)) luaL_error(L, "matrix:eigen() eigenvalue ordering failed"); for (i = 0; i < n; i++) lambda->val[i] = gsl_vector_get(ev, i); gsl_vector_free(ev); gsl_eigen_hermv_free(w); return 2; }
int main(int argc, char *argv[]){ int i,j,k, c, N; int dflag=0, eflag=0, gflag=0, vflag=0, hflag=0; float w; /* frec */ //char *lvalue=NULL; double **M, // XYZ coordinates dos, lambda=0; while((c = getopt (argc, argv, "degvhl:")) != -1){ switch (c){ case 'd': dflag = 1; break; case 'e': eflag = 1; break; case 'g': gflag = 1; break; case 'v': vflag = 1; break; case 'h': hflag = 1; break; case 'l': lambda = atof(optarg); break; } } scanf("%d",&N); M = (double **) malloc (N*sizeof(double *)); // coordinate matrix // read coordinates (XYZ format file) for (int i=0; i<N; i++){ char null[5]; // discard element double *tmp = (double *) malloc (3 * sizeof(double)); // 3 coordinates scanf("%s%lf%lf%lf", null, &tmp[0], &tmp[1], &tmp[2]); M[i] = tmp; // printf("- %.2f %.2f\n",M[i][0], M[i][1]); // DEBUG } /* M: coordinate matrix, N: number of atoms, l: spin-orbit parameter (set to 0 to tight-binding)*/ gsl_matrix_complex * Hso = hamiltonian(M, N, lambda); /* print hamiltonial */ if (hflag){ printComMat(Hso,N*SPIN*ORB); return 0; } /* eigenvalues */ gsl_matrix_complex * evec = gsl_matrix_complex_alloc(N*SPIN*ORB, N*SPIN*ORB); gsl_vector * eval = gsl_vector_alloc(N*SPIN*ORB); gsl_eigen_hermv_workspace * ws = gsl_eigen_hermv_alloc(N*SPIN*ORB); gsl_matrix_complex * A = Hso; // gsl_eigen_hermv() destroys Hso matrix, use a copy instead gsl_eigen_hermv (A, eval, evec, ws); gsl_eigen_hermv_sort (eval, evec, GSL_EIGEN_SORT_VAL_ASC); gsl_eigen_hermv_free(ws); if (eflag){ for (int i=0; i<N*SPIN*ORB; i++) printf("%d %.4g \n", i, gsl_vector_get(eval,i)); return 0; } if (vflag){ printComMat(evec, N*SPIN*ORB); return 0; } /* calculate DoS * __ __ * \ \ Hij Hji * DOS(E) = -imag /_ /_ ---------------- * i j E - En + i*eta * * where H is the hamiltonian, and n is the state. * NOTE: i and j 0-indexed list. i*eta */ double eval_min = gsl_vector_min (eval), /* lower bound */ eval_max = gsl_vector_max (eval); /* upper bound */ if (dflag) for (w = eval_min; w < eval_max; w += 1e-3){ dos = 0; #pragma omp parallel num_threads(4) { int tid = omp_get_thread_num(); #pragma omp for private(i,k) reduction (+:dos) for (i=0; i<N*SPIN*ORB; i++) for (k=0; k<N*SPIN*ORB; k++){ gsl_complex h = gsl_matrix_complex_get (Hso, i, k); double l = gsl_vector_get (eval ,k); gsl_complex z = gsl_complex_rect(0,5e-3); /* parte imaginaria */ gsl_complex num = gsl_complex_mul(h,gsl_complex_conjugate(h)); /* numerador */ gsl_complex den = gsl_complex_add_real(z, w-l); /* denominador */ gsl_complex g = gsl_complex_div(num,den); dos += GSL_IMAG(g); } if (dflag && tid==0) printf("%.3g %g \n", w, -dos/PI); } } /* Green's function * * <i|n> <n|j> * Gij(E) = ---------------- * E - En + i*eta * * where i and j are atoms, and n is the state. * NOTE: i and j 0-indexed list. */ int list[]={0,1,2,5,6,7}; /* atoms to get conductance */ int NL = (int) sizeof(list)/sizeof(list[0]); gsl_matrix_complex * G = gsl_matrix_complex_alloc(NL*SPIN*ORB, NL*SPIN*ORB); // Green if (gflag) for (double E = eval_min; E < eval_max; E += 1e-3){ // energy gsl_matrix_complex_set_all(G, GSL_COMPLEX_ZERO); // init for (int n=0; n<N*SPIN*ORB; n++) // states for (i=0; i<NL; i++) // atoms for (j=0; j<NL; j++) // atoms for (int k0=0; k0<SPIN*ORB; k0++){ // orbitals for (int k1=0; k1<SPIN*ORB; k1++){ // orbitals gsl_complex in = gsl_matrix_complex_get (evec, n, list[i]*SPIN*ORB+k0); gsl_complex nj = gsl_matrix_complex_get (evec, n, list[j]*SPIN*ORB+k1); double En = gsl_vector_get (eval ,n); gsl_complex eta = gsl_complex_rect(0,5e-3); /* delta */ gsl_complex num = gsl_complex_mul(in, gsl_complex_conjugate(nj)); /* num */ gsl_complex den = gsl_complex_add_real(eta, E - En); /* den */ gsl_complex Gij = gsl_complex_div(num,den); gsl_complex tmp = gsl_matrix_complex_get(G, i*SPIN*ORB+k0, j*SPIN*ORB+k1); gsl_complex sum = gsl_complex_add(tmp, Gij); gsl_matrix_complex_set(G, i*SPIN*ORB+k0, j*SPIN*ORB+k1, sum); } } dos = 0 ; for(int i=0; i<NL*SPIN*ORB; i++) dos += GSL_IMAG( gsl_matrix_complex_get(G, i, i) ); printf("%.3g %g\n", E, -dos/PI); // printComMat(G, NL*SPIN*ORB); } gsl_matrix_complex_free(G); gsl_vector_free(eval); gsl_matrix_complex_free(evec); return 0; }