PyObject* scalapack_diagonalize_ex(PyObject *self, PyObject *args) { // Expert Driver for QR algorithm // Computes *all* eigenvalues and eigenvectors PyArrayObject* a_obj; // Hamiltonian matrix PyArrayObject* b_obj; // overlap matrix PyArrayObject* adesc; // Hamintonian matrix descriptor PyArrayObject* z_obj; // eigenvector matrix PyArrayObject* w_obj; // eigenvalue array //PyArrayObject* H_MM_obj; //PyArrayObject* eps_M_obj; int ibtype = 1; // Solve H*psi = lambda*S*psi int z_mycol = -1; int z_myrow = -1; int z_nprow, z_npcol; int z_type, z_ConTxt, z_m, z_n, z_mb, z_nb, z_rsrc, z_csrc, z_lld; int zdesc[9]; int il, iu; // not used when range = 'A' or 'V' int eigvalm, nz; static int one = 1; double vl, vu; // not used when range = 'A' or 'I' char jobz = 'V'; // eigenvectors also char range = 'A'; // all eigenvalues char uplo; char cmach = 'U'; // most orthogonal eigenvectors // char cmach = 'S'; // most acccurate eigenvalues int isgeneral; // flag for general diagonalize if (!PyArg_ParseTuple(args, "OOcOOO", &a_obj, &adesc, &uplo, &b_obj, //&H_MM_obj, &eps_M_obj &z_obj, &w_obj)) return NULL; // adesc, // bdesc = adesc // This is generally not required, as long as the alignment properties // are satisfied, see pdsygvx.f. In the context of GPAW, don't see why // bdesc would not be equal to adesc so I am just hard-coding it in. int a_type = INTP(adesc)[0]; int a_ConTxt = INTP(adesc)[1]; int a_m = INTP(adesc)[2]; int a_n = INTP(adesc)[3]; int a_mb = INTP(adesc)[4]; int a_nb = INTP(adesc)[5]; int a_rsrc = INTP(adesc)[6]; int a_csrc = INTP(adesc)[7]; int a_lld = INTP(adesc)[8]; // Note that A is symmetric, so n = a_m = a_n; // We do not test for that here. int n = a_n; //printf("C: n=%d", n); // zdesc = adesc // This is generally not required, as long as the alignment properties // are satisfied, see pdsygvx.f. In the context of GPAW, don't see why // zdesc would not be equal to adesc so I am just hard-coding it in. z_type = a_type; z_ConTxt = a_ConTxt; z_m = a_m; z_n = a_n; z_mb = a_mb; z_nb = a_nb; z_rsrc = a_rsrc; z_csrc = a_csrc; z_lld = a_lld; zdesc[0] = z_type; zdesc[1] = z_ConTxt; zdesc[2] = z_m; zdesc[3] = z_n; zdesc[4] = z_mb; zdesc[5] = z_nb; zdesc[6] = z_rsrc; zdesc[7] = z_csrc; zdesc[8] = z_lld; Cblacs_gridinfo_(z_ConTxt, &z_nprow, &z_npcol, &z_myrow, &z_mycol); assert(z_ConTxt != -1); if (z_ConTxt != -1) { if (PyArray_Check(b_obj)) isgeneral = 1; else isgeneral = 0; // Convergence tolerance // most orthogonal eigenvectors double abstol = pdlamch_(&z_ConTxt, &cmach); double orfac = -1.0; // Query part, need to find the optimal size of a number of work arrays int info; int *ifail; ifail = GPAW_MALLOC(int, n); int *iclustr; iclustr = GPAW_MALLOC(int, 2*z_nprow*z_npcol); double *gap; gap = GPAW_MALLOC(double, z_nprow*z_npcol); int querywork = -1; int* iwork; int liwork; int lwork; int lrwork; int i_work; double d_work; double D_work[1]; //double* D_work = &d_work; double_complex c_work; if (a_obj->descr->type_num == PyArray_DOUBLE) { if(!isgeneral){ pdsyevx_(&jobz, &range, &uplo, &n, DOUBLEP(a_obj), &one, &one, INTP(adesc), &vl, &vu, &il, &iu, &abstol, &eigvalm, &nz, DOUBLEP(w_obj), &orfac, DOUBLEP(z_obj), &one, &one, zdesc, &d_work, &querywork, &i_work, &querywork, ifail, iclustr, gap, &info); } else { pdsygvx_(&ibtype, &jobz, &range, &uplo, &n, DOUBLEP(a_obj), &one, &one, INTP(adesc), DOUBLEP(b_obj), &one, &one, INTP(adesc), &vl, &vu, &il, &iu, &abstol, &eigvalm, &nz, DOUBLEP(w_obj), &orfac, DOUBLEP(z_obj), &one, &one, zdesc, D_work, &querywork, &i_work, &querywork, ifail, iclustr, gap, &info); } lwork = (int)(D_work[0]); //lwork = (int)(d_work); printf("abstol after=%f\n", abstol); } else { if(!isgeneral) pzheevx_(&jobz, &range, &uplo, &n, (void*)COMPLEXP(a_obj),&one, &one, INTP(adesc), &vl, &vu, &il, &iu, &abstol, &eigvalm, &nz, DOUBLEP(w_obj), &orfac, (void*)COMPLEXP(z_obj), &one, &one, zdesc, &c_work, &querywork, &d_work, &querywork, &i_work, &querywork, ifail, iclustr, gap, &info); else pzhegvx_(&ibtype, &jobz, &range, &uplo, &n, (void*)COMPLEXP(a_obj), &one, &one, INTP(adesc), (void*)COMPLEXP(b_obj), &one, &one, INTP(adesc), &vl, &vu, &il, &iu, &abstol, &eigvalm, &nz, DOUBLEP(w_obj), &orfac, (void*)COMPLEXP(z_obj), &one, &one, zdesc, &c_work, &querywork, &d_work, &querywork, &i_work, &querywork, ifail, iclustr, gap, &info); lwork = (int)(c_work); lrwork = (int)(d_work); } if (info != 0) { printf("ERROR %d\n", info); PyErr_SetString(PyExc_RuntimeError, "scalapack_diagonalize_ex error in query."); return NULL; } // Computation part lwork = lwork + (n-1)*n; liwork = i_work; iwork = GPAW_MALLOC(int, liwork); if (a_obj->descr->type_num == PyArray_DOUBLE) { double* work = GPAW_MALLOC(double, lwork); if (!isgeneral) pdsyevx_(&jobz, &range, &uplo, &n, DOUBLEP(a_obj), &one, &one, INTP(adesc), &vl, &vu, &il, &iu, &abstol, &eigvalm, &nz, DOUBLEP(w_obj), &orfac, DOUBLEP(z_obj), &one, &one, zdesc, work, &lwork, iwork, &liwork, ifail, iclustr, gap, &info); else pdsygvx_(&ibtype, &jobz, &range, &uplo, &n, DOUBLEP(a_obj), &one, &one, INTP(adesc), DOUBLEP(b_obj), &one, &one, INTP(adesc), &vl, &vu, &il, &iu, &abstol, &eigvalm, &nz, DOUBLEP(w_obj), &orfac, DOUBLEP(z_obj), &one, &one, zdesc, work, &lwork, iwork, &liwork, ifail, iclustr, gap, &info); free(work); } else { double_complex* work = GPAW_MALLOC(double_complex, lwork); double* rwork = GPAW_MALLOC(double, lrwork); if (!isgeneral) pzheevx_(&jobz, &range, &uplo, &n, (void*)COMPLEXP(a_obj), &one, &one, INTP(adesc), &vl, &vu, &il, &iu, &abstol, &eigvalm, &nz, DOUBLEP(w_obj), &orfac, (void*)COMPLEXP(z_obj), &one, &one, zdesc, work, &lwork, rwork, &lrwork, iwork, &liwork, ifail, iclustr, gap, &info); else pzhegvx_(&ibtype, &jobz, &range, &uplo, &n, (void*)COMPLEXP(a_obj), &one, &one, INTP(adesc), (void*)COMPLEXP(b_obj), &one, &one, INTP(adesc), &vl, &vu, &il, &iu, &abstol, &eigvalm, &nz, DOUBLEP(w_obj), &orfac, (void*)COMPLEXP(z_obj), &one, &one, zdesc, work, &lwork, rwork, &lrwork, iwork, &liwork, ifail, iclustr, gap, &info); free(rwork); free(work); } if (info != 0) { PyErr_SetString(PyExc_RuntimeError, "scalapack_diagonalize_ex error in compute."); return NULL; } free(iwork); free(gap); free(iclustr); free(ifail); //PyObject* values = Py_BuildValue("(OO)", w_obj, z_obj); //Py_DECREF(w_obj); //Py_DECREF(z_obj); //return values; Py_RETURN_NONE; } else { Py_RETURN_NONE; //return Py_BuildValue("(OO)", Py_None, Py_None); } }