k-dot-p 0.1

hamiltonian_cartesian_8band.c++

Go to the documentation of this file.
00001 /*
00002  *An 8-band Hamiltonian on a Cartesian grid.
00003 
00004     Copyright (C) 2010 Joseph Pingenot
00005 
00006     This program is free software: you can redistribute it and/or modify
00007     it under the terms of the GNU Affero General Public License as published by
00008     the Free Software Foundation, either version 3 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU Affero General Public License for more details.
00015 
00016     You should have received a copy of the GNU Affero General Public License
00017     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 
00019 */
00020 
00021 #include <string.h>
00022 #include <liblapackwrap/lapackwrap_real_double.h>
00023 #include <liblapackwrap/lapackwrap_complex_double.h>
00024 #include <liblapackwrap/blaswrap_complex_double.h>
00025 #include <liblapackwrap/blaswrap_real_double.h>
00026 #include <libkdotp/hamiltonian_cartesian_8band.h++>
00027 #include <libmodelxx/grid.h++>
00028 #include <libkdotp/physical_constants.h++>
00029 #include <libmodelxx/cartesian_grid.h++>
00030 #include <libkdotp/physical_constants.h++>
00031 #include <libmodelxx/material.h++>
00032 
00033 using namespace kdp::constants;
00034 
00035 #define N_BANDS 8
00036 
00037 namespace kdotp {
00038   namespace libkdotp {
00039     namespace hamiltonian {
00040 
00041       typedef libmodelxx::grid::cartesian_grid<libmodelxx::structure::material*,1,1> matgrid;
00042       typedef libmodelxx::grid::cartesian_grid<double,1,1> potgrid;
00043 
00044       /**\note This matrix contains all of the *constants* of the 8-band
00045        *k-dot-p matrix. Any non-constants across the nanostructure (e.g.
00046        *the coupling constants P, gamma_i, m', etc.) are dependent upon
00047        *position and, therefore, not included (they're not constant across
00048        *the entire structure (nor can they be determined at compile time)
00049        */
00050       const static struct llw_complex_double consts_8band[] = {
00051   {-hbar*hbar/2.0, 0},
00052   {0, 0},
00053   {-1/__builtin_sqrt(2), 0},
00054   {__builtin_sqrt(2/3), 0},
00055   {1/__builtin_sqrt(6), 0},
00056   {0, 0},
00057   {-1/__builtin_sqrt(3), 0},
00058   {-1/__builtin_sqrt(3), 0},
00059   
00060   {0, 0},
00061   {-hbar*hbar/2.0, 0},
00062   {0, 0,},
00063   {-1/__builtin_sqrt(2), 0},
00064   {__builtin_sqrt(2/3), 0},
00065   {1/__builtin_sqrt(2), 0},
00066   {-1/__builtin_sqrt(3), 0},
00067   {1/__builtin_sqrt(3), 0},
00068 
00069   {-1/__builtin_sqrt(2), 0},
00070   {0, 0},
00071   /**\notehbar^2/2 for both k_|| and k_z*/
00072   {-hbar*hbar/(2*m0), 0},
00073   {2*__builtin_sqrt(3)*hbar*hbar/(2*m0), 0},
00074   {__builtin_sqrt(3)*hbar*hbar/(2*m0), 2*__builtin_sqrt(3)*hbar*hbar/(2*m0)},
00075   {0, 0},
00076   {-__builtin_sqrt(6)*hbar*hbar/(2*m0), 0},
00077   {-__builtin_sqrt(6)*hbar*hbar/(2*m0), 2*__builtin_sqrt(6)*hbar*hbar/(2*m0)},
00078   
00079   {__builtin_sqrt(2/3), 0},
00080   {-__builtin_sqrt(6), 0},
00081   {2*__builtin_sqrt(3)*hbar*hbar/(2*m0), 0},
00082   {-hbar*hbar/(2*m0), 0},
00083   {0, 0},
00084   {__builtin_sqrt(3)*hbar*hbar/(2*m0), 2*__builtin_sqrt(3)*hbar*hbar/(2*m0)},
00085   {-__builtin_sqrt(2)*hbar*hbar/(2*m0), 0},
00086   {-3*__builtin_sqrt(2)*hbar*hbar/(2*m0), 0},
00087   
00088   {1/__builtin_sqrt(6), 0},
00089   {__builtin_sqrt(2/3), 0},
00090   {__builtin_sqrt(3)*hbar*hbar/(2*m0), -2*__builtin_sqrt(3)*hbar*hbar/(2*m0)},
00091   {0, 0},
00092   {-hbar*hbar/(2*m0), 0},
00093   {-2*__builtin_sqrt(3)*hbar*hbar/(2*m0), 0},
00094   {3*__builtin_sqrt(2)*hbar*hbar/(2*m0), 0},
00095   {__builtin_sqrt(2)*hbar*hbar/(2*m0), 0},
00096 
00097   {0, 0},
00098   {1/__builtin_sqrt(2), 0},
00099   {0, 0},
00100   {__builtin_sqrt(3)*hbar*hbar/(2*m0), 2*__builtin_sqrt(3)*hbar*hbar/(2*m0)},
00101   {-2*__builtin_sqrt(3)*hbar*hbar/(2*m0), 0},
00102   {__builtin_sqrt(6)*hbar*hbar/(2*m0), -2*__builtin_sqrt(6)*hbar*hbar/(2*m0)},
00103   {-__builtin_sqrt(6)*hbar*hbar/(2*m0), 0},
00104   
00105   {-1/__builtin_sqrt(3), 0},
00106   {-1/__builtin_sqrt(3), 0},
00107   {-__builtin_sqrt(6)*hbar*hbar/(2*m0), 0},
00108   {-__builtin_sqrt(2)*hbar*hbar/(2*m0), 0},
00109   {3*__builtin_sqrt(2)*hbar*hbar/(2*m0), 0},
00110   {__builtin_sqrt(6)*hbar*hbar/(2*m0), 2*__builtin_sqrt(6)*hbar*hbar/(2*m0)},
00111   {-hbar*hbar/(2*m0), 0},
00112   {0, 0},
00113   
00114   {-1/__builtin_sqrt(3), 0},
00115   {1/__builtin_sqrt(3), 0},
00116   {-__builtin_sqrt(6)*hbar*hbar/(2*m0), 2*__builtin_sqrt(6)*hbar*hbar/(2*m0)},
00117   {3*__builtin_sqrt(2)*hbar*hbar/(2*m0), 0},
00118   {__builtin_sqrt(2)*hbar*hbar/(2*m0), 0},
00119   {-__builtin_sqrt(6)*hbar*hbar/(2*m0), 0},
00120   {0, 0},
00121   {-hbar*hbar/(2*m0), 0}
00122       };
00123 
00124       /**Simple helper function to get the appropriate constant out of consts_8band[]
00125        *\note entries are stored in column-major order.
00126        *\note rows, cols are in the order of page 215 in Winkler's spin-orbit book
00127        */
00128       static inline short get_consts_index(short unsigned row, short unsigned col) {
00129   return row*8 + col;
00130       }
00131 
00132       /**does a quick check to make sure the constants matrix is truly Hermitean
00133        *\param eye pointer to a short unsigned int to store the row index of the invalid constant.
00134        *\return -j if a real portion was not identical across a transpose
00135        *        +j if a complex portion was not negated across a transpose
00136        *        0 if identical
00137        *\note this is a debugging/safety aid, but costs basically no time.
00138        */
00139       static int check_constants_hermiticity(unsigned short *eye) {
00140   for(unsigned short i=0; i<8; i++) {
00141     for(unsigned short j=0; j<8; j++) {
00142       /*
00143        *This is buggy and this file currently unused, so it's been commented out so that things will build.
00144       if(consts_8band[get_consts_index(i, j)].re 
00145          != consts_8band[get_consts_index(i, j)].re) {
00146         *eye = i;
00147         return -j;
00148       }
00149       if(consts_8band[get_consts_index(i, j)].im 
00150          != -consts_8band[get_consts_index(i, j)].im) {
00151         *eye = i;
00152         return j;
00153       }
00154       */
00155     }
00156   }
00157   return 0;
00158       }
00159 
00160       static GError* store_reduced_material_parameters(struct parameters_8band_nostrain *params, matgrid *mg, potgrid *pg) {
00161   int e;
00162   char *s;
00163   const char* paramstring[] = {"E_g_Gamma", "E_v", "Delta", "m_e_Gamma", "gamma1", "gamma2", "gamma3", "Ep"};
00164   double temp_params[8];
00165   for(long unsigned i=0; i<mg->L[0]; i++) {
00166     for(short unsigned p=0; p<8; p++) {
00167       temp_params[i] = mg->data[i]->get_property(paramstring[p], &e);
00168       if(e != 0) {
00169         return g_error_new(HAMILTONIAN_CARTESIAN_8BAND_GERROR_DOMAIN, 10+e, "Got error %d getting property (%s) at site %lu (material %s).\n", e, paramstring[p], i, s=mg->data[i]->get_name());
00170       }
00171     }
00172     params[i].Ec = temp_params[0]+temp_params[1];
00173     params[i].Ev = temp_params[1];
00174     params[i].Eso = temp_params[1]-temp_params[2];
00175     params[i].P = sqrt(hbar*hbar/(2*m0)*temp_params[7]);
00176     /*For the reduced param terms, see Winkler's Spin-orbit book page 216*/
00177     params[i].oo_mstar = 1.0/temp_params[4] - temp_params[7]/(3*m0)*(2/(temp_params[0]+temp_params[1]) + 1/(temp_params[0]+temp_params[1]+temp_params[2]));
00178     params[i].gamma1 = temp_params[4] - temp_params[7]/(3*(temp_params[0] + temp_params[1]));
00179     params[i].gamma2 = temp_params[5] - temp_params[7]/(6*(temp_params[0] + temp_params[1]));
00180     params[i].gamma3 = temp_params[6] - temp_params[7]/(6*(temp_params[0] + temp_params[1]));
00181   }
00182   return NULL;
00183       }
00184 
00185 
00186       cartesian_8band::cartesian_8band(struct libmodelxx::structure::generic_structure *gs, boundary_condition bc_, bool second_neighbor_) : upper_diagonal(NULL), diagonal(NULL), matrix(NULL), Q(NULL), bc(bc_), second_neighbor(second_neighbor_), params(NULL) {
00187   n_neighbors=second_neighbor_?2:1;
00188   /*Check to make sure our consts matrix is Hermitean*/
00189   {
00190     int col;
00191     short unsigned row;
00192     if((col=check_constants_hermiticity(&row)) != 0) {
00193       fprintf(stderr, "Hermiticty check of 8-band constants FAILED at row=%hu col=%d.\n", row, col);
00194     }else{
00195       fprintf(stderr, "Hermiticty check of 8-band constants PASSED.\n");
00196     }
00197   }
00198   matgrid *mg = (matgrid*)(gs->material_grid);
00199   potgrid *pg = (potgrid*)(gs->potential_grid);
00200   L = mg->L[0];
00201   /*Load the reduced material parameters into the array.*/
00202   params = (struct parameters_8band_nostrain*)malloc(L*sizeof(struct parameters_8band_nostrain));
00203   if(params == NULL) return;
00204   GError *e = NULL;
00205   if((e = store_reduced_material_parameters(params, mg, pg)) != NULL) {
00206     fprintf(stderr, "hamiltonian_cartesian_8band: ERROR calculating reduced band parameters: %s\n", e->message);
00207     g_error_free(e);
00208     free(params);
00209     params =NULL;
00210     return;
00211   }
00212         if(bc == HARDWALL) {
00213     matrix = new llw_complex_double[(n_neighbors+1)*L*N_BANDS];
00214       for(long unsigned i = 0; i<(n_neighbors+1)*L*N_BANDS; i++) {
00215         matrix[i].re = 0;
00216         matrix[i].im = 0;
00217       }
00218   }else{
00219     matrix = new llw_complex_double[L*L*N_BANDS*N_BANDS];
00220     for(long unsigned int i=0; i<(L*L*N_BANDS*N_BANDS); i++) {
00221       matrix[i].re = 0;
00222       matrix[i].im = 0;
00223     }
00224   }
00225   int e2=0;
00226         //double dconsts = -1/(nm_to_bohr(mg->a[0])*nm_to_bohr(mg->a[0]));
00227   /*Set up the constants for the diagonal, superdiagonal, and second superdiagonal for first nearest neighbor*/
00228   
00229   double ooms=0, ooms_prev=0, ooms_next=0, Eg=0, Ev=0, ooms_prev2=0, ooms_next2=0;
00230   /*Initialize the current ooms.*/
00231   ooms = 1.0/mg->data[0]->get_property("m_e_Gamma", &e2);
00232   if(e2 != 0) {
00233     fprintf(stderr, "hamiltonians::cartesian_8band: ERROR getting m_e_Gamma (err=%d).\n", e2);
00234     e2=0;
00235   }
00236   ooms_next = 1.0/mg->data[1]->get_property("m_e_Gamma", &e2);
00237   if(e2 != 0) {
00238     fprintf(stderr, "hamiltonians::cartesian_8band: ERROR getting m_e_Gamma (err=%d).\n", e2);
00239     e2=0;
00240   }
00241   for(unsigned int i=0; i<L; i++, ooms_prev2 = ooms_prev, ooms_prev=ooms, ooms=ooms_next, ooms_next = ooms_next2) {
00242     //Eg = ev_to_hartree(mg->data[i]->get_property("E_g_Gamma", &e2));
00243     Eg = mg->data[i]->get_property("E_g_Gamma", &e2);
00244     if(e2 != 0) {
00245       fprintf(stderr, "hamiltonians::cartesian_8band: ERROR getting E_g_Gamma (err=%d).\n", e2);
00246       e2=0;
00247     }
00248     //Ev = ev_to_hartree(mg->data[i]->get_property("E_v", &e2));
00249     Ev = mg->data[i]->get_property("E_v", &e2);
00250     if(e2 != 0) {
00251       fprintf(stderr, "hamiltonians::cartesian_8band: ERROR getting E_v (err=%d).\n", e2);
00252       e2=0;
00253     }
00254     if(i < L-2) {
00255       ooms_next2 = 1.0/mg->data[i+2]->get_property("m_e_Gamma", &e2);
00256       if(e2 != 0) {
00257         fprintf(stderr, "hamiltonians::cartesian_8band: ERROR getting m_e_Gamma (err=%d).\n", e2);
00258         e2=0;
00259       }
00260     }
00261     char *s;
00262     fprintf(stderr, "%05u(%s): ooms_prev2=%g ooms_prev=%g ooms=%g ooms_next=%g ooms_next2=%g Ev+Eg=%g\n", i, s=mg->data[i]->get_name(), ooms_prev2, ooms_prev, ooms, ooms_next, ooms_next2, Ev+Eg);
00263     g_free(s);
00264     ////////////////////////////////////////////////////////////////
00265     // NOTHING BELOW THIS LINE HAS BEEN FULLY IMPLEMENTED FOR 8BAND;
00266     // THIS IS ALL PLACEHOLDER/FORM CODE WHICH HAS BEEN MADE TO
00267     // COMPILE.
00268     ////////////////////////////////////////////////////////////////
00269     if(bc == HARDWALL) {
00270     }else{
00271     }
00272   }
00273       }
00274       
00275       cartesian_8band::~cartesian_8band(){
00276   if(matrix != NULL) delete[] matrix;
00277   if(diagonal != NULL) delete[] diagonal;
00278   if(upper_diagonal != NULL) delete[] upper_diagonal;
00279   if(Q != NULL) delete[] Q;
00280   if(matrix != NULL) delete[] matrix;
00281       }
00282 
00283       double* cartesian_8band::get_eigenvectors(char VoI, double eVmin, double eVmax, int imin, int imax, double **evals, int *n_eigs, GError **err)  {
00284   int info;
00285   if ((bc == PERIODIC) && (diagonal == NULL) && (upper_diagonal == NULL) && (Q == NULL)) {
00286     /*If we're not hardwall, we first have to reduce to tridiagonal.*/
00287     /*We're a symmetric matrix, but not tridiag.
00288      *Call DSYTRD to get the tri-diag matrix*/
00289     /*Call DORGTR to get the matrix Q to convert the eigenfunctions back to the position basis.*/
00290   } else if (second_neighbor && (diagonal == NULL) && (upper_diagonal == NULL) && (Q == NULL)) {
00291     /*We're a banded matrix.*/
00292     /*Call DSBTRD to get the tri-diagonal matrix and Q*/
00293     info = llw_complex_double_sbtrd_a('V', 'U', L, n_neighbors, matrix, n_neighbors+1, &diagonal, &upper_diagonal, &Q);
00294     if(info != 0) {
00295       *err = g_error_new(HAMILTONIAN_CARTESIAN_8BAND_GERROR_DOMAIN, 1, "Got error from llw_complex_double_sbtrd_a: %d\n", info);
00296       if(diagonal != NULL) {
00297         free(diagonal);
00298         diagonal = NULL;
00299       }
00300       if(upper_diagonal != NULL) {
00301         free(upper_diagonal);
00302         upper_diagonal = NULL;
00303       }
00304       if(Q != NULL) {
00305         free(Q);
00306         Q = NULL;
00307       }
00308       return NULL;
00309     }
00310   }
00311   double *eigvecs = NULL;
00312   int n_eigvecs = -1;
00313   int* isuppz = NULL;
00314   //info = llw_complex_double_stegr_a('V', VoI, L, diagonal, upper_diagonal, eVmin, eVmax, imin, imax, n_eigs, evals, &eigvecs, &n_eigvecs, &isuppz);
00315   if((n_eigvecs <= *n_eigs) || (info != 0)) {
00316     if(n_eigvecs <= *n_eigs) {
00317       *err = g_error_new(HAMILTONIAN_CARTESIAN_8BAND_GERROR_DOMAIN, 6, "in return from llw_complex_double_stegr_a: failed to get same number or more eigenvec storage than there were eigenvals (%d and %d, respectively)", n_eigvecs, *n_eigs);
00318     }else{
00319       if(info < 0) {
00320         *err = g_error_new(HAMILTONIAN_CARTESIAN_8BAND_GERROR_DOMAIN, 1, "Bad argument to LAPACK call DSTEGR: %d\n", -info);
00321       }else if(info < 10) {
00322         *err = g_error_new(HAMILTONIAN_CARTESIAN_8BAND_GERROR_DOMAIN, 2, "Error in BLAS call DLARRE called by LAPACK call DSGEGR: %d\n", info);
00323       }else if(info < 20) {
00324         *err = g_error_new(HAMILTONIAN_CARTESIAN_8BAND_GERROR_DOMAIN, 3, "Error in BLAS call DLARRV called by LAPACK call DSGEGR: %d\n", info/2);
00325       }else if(info == 100) {
00326         *err = g_error_new(HAMILTONIAN_CARTESIAN_8BAND_GERROR_DOMAIN, 5, "Error in liblapackwrap llw_complex_double_stegr_a: malloc failed (%d)\n", info/100);
00327       }else{
00328         *err = g_error_new(HAMILTONIAN_CARTESIAN_8BAND_GERROR_DOMAIN, 4, "Got error (info=%d) from DSTEGR, but don't know what it means.\n", info);
00329       }
00330     }
00331     free(*evals);
00332     free(eigvecs);
00333     *evals=NULL;
00334     eigvecs=NULL;
00335   }else{
00336     free(isuppz);
00337     if(Q != NULL) {
00338       double* final_eigvecs = NULL;
00339       double one = 1.0;
00340       //info = llw_complex_double_gemm_a('N', 'N', L, n_eigvecs, L, &one, Q, L, eigvecs, L, &final_eigvecs);
00341       if(info != 0) {
00342         *err = g_error_new(HAMILTONIAN_CARTESIAN_8BAND_GERROR_DOMAIN, 4, "Got error (info=%d) from llw_complex_double_gemmm_a\n", info);
00343         if(final_eigvecs != NULL) free(final_eigvecs);
00344         return eigvecs;
00345       }
00346       free(eigvecs);
00347       return final_eigvecs;
00348     }
00349   }
00350   return eigvecs;
00351       }
00352 
00353 
00354     }
00355   }
00356 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines