#include #include #include #include #include "green.h" #include #define MAXLINE 256 /******************************************************************************* * The class of Green is designed to evaluate the LDOS via the Green's Function * method. The meaning of input/output parameters are as follows: * * ntm (input, value) total number of atoms in system * sdim (input, value) dimension of the system; usually 3 * niter (input, value) maximum iterations during Lanczos diagonalization * min (input, value) minimum value for the angular frequency * max (input, value) maximum value for the angular frequency * ndos (input, value) total number of points in LDOS * eps (input, value) epson that govens the width of delta-function * Hessian (input, pointer of pointer) mass-weighted force constant matrix, of * dimension [natom*sysdim][natm*sysdim]; it is actually * the dynamical matrix at gamma point * itm (input, value) index of the atom to evaluate local phonon DOS, from 0 * lpdos (output, array) double array of size (ndos, sdim) ******************************************************************************* * References: * 1. Z. Tang and N. R. Aluru, Phys. Rev. B 74, 235441 (2006). * 2. C. Hudon, R. Meyer, and L.J. Lewis, Phys. Rev. B 76, 045409 (2007). * 3. L.T. Kong and L.J. Lewis, Phys. Rev. B 77, 165422 (2008). * * NOTE: The real-space Green's function method is not expected to work accurately * for small systems, say, system (unit cell) less than 500 atoms. *******************************************************************************/ /*------------------------------------------------------------------------------ * Constructor is used as the main driver *----------------------------------------------------------------------------*/ Green::Green(const int ntm, const int sdim, const int niter, const double min, const double max, const int ndos, const double eps, double **Hessian, const int itm, double **lpdos) { const double tpi = 8.*atan(1.); natom = ntm; sysdim = sdim; nit = niter; epson = eps; wmin = min*tpi; wmax = max*tpi; nw = ndos + (ndos+1)%2; H = Hessian; iatom = itm; ldos = lpdos; memory = new Memory; if (natom < 1 || iatom < 0 || iatom >= natom){ printf("\nError: Wrong number of total atoms or wrong index of interested atom!\n"); return; } ndim = natom * sysdim; if (nit < 1){printf("\nError: Wrong input of maximum iterations!\n"); return;} if (nit > ndim){printf("\nError: # Lanczos iterations is not expected to exceed the degree of freedom!\n"); return;} if (nw < 1){printf("\nError: Wrong input of points in LDOS!\n"); return;} // initialize variables and allocate local memories dw = (wmax - wmin)/double(nw-1); alpha = memory->create(alpha, sysdim,nit, "Green_Green:alpha"); beta = memory->create(beta, sysdim,nit+1,"Green_Green:beta"); //ldos = memory->create(ldos, nw,sysdim, "Green_Green:ldos"); // use Lanczos algorithm to diagonalize the Hessian Lanczos(); // Get the inverser of the treated hessian by continued fractional method Recursion(); return; } /*------------------------------------------------------------------------------ * Deconstructor is used to free memory *----------------------------------------------------------------------------*/ Green::~Green() { H = NULL; ldos = NULL; memory->destroy(alpha); memory->destroy(beta); delete memory; return; } /*------------------------------------------------------------------------------ * Private method to diagonalize a matrix by the Lanczos algorithm *----------------------------------------------------------------------------*/ void Green::Lanczos() { double *vp, *v, *w, *ptr; vp = new double [ndim]; v = new double [ndim]; w = new double [ndim]; int ipos = iatom*sysdim; // Loop over dimension for (int idim=0; idim Z, z_m_a, r_x, rec_x, rec_x_inv; double sr, si; double w = wmin; for (int i=0; i(w*w, epson); for (int idim=0; idim xmax[idim]) { r_x = sqrt(-2.*two_b + z_m_a); ax = -std::real(r_x) * rtwob; bx = -std::imag(r_x) * rtwob; } else { r_x = sqrt(2.*two_b - z_m_a); ax = std::imag(r_x) * rtwob; bx = -std::real(r_x) * rtwob; } sr = (a - alpha_inf[idim])*rtwob + ax; si = epson * rtwob + bx; rec_x = std::complex (sr, si); for (int j=0; j Z, rec_x, rec_x_inv; std::complex cunit = std::complex(0.,1.); double w = wmin; for (int i=0; i(w*w, epson); for (int idim=0; idim(0.,0.); for (int j=0; j