|
k-dot-p 0.1
|
00001 /* 00002 * Performs a self-consistent potential calculation. 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 <math.h> 00022 #include <glib.h> 00023 #include <libkdotp/wavefunction_cartesian_effective_mass.h++> 00024 #include <libpostproc/density_1d.h> 00025 #include <libpostproc/potential_1d.h> 00026 #include <libpostproc/fftw_wavefunc.h> 00027 #include <libkdotp/hamiltonians.h++> 00028 #include <libmodelxx/cartesian_grid.h++> 00029 #include <libmodelxx/generic_structure.h++> 00030 #include <libkdotp/physical_constants.h++> 00031 00032 #ifndef ___CALCULATION_SELF_CONSISTENT_POTENTIAL___ 00033 #define ___CALCULATION_SELF_CONSISTENT_POTENTIAL___ 00034 00035 #define CALCULATION_SELF_CONSISTENT_GERROR_DOMAIN 8438 00036 00037 00038 namespace kdotp { 00039 namespace libmetacalc { 00040 namespace self_consistent { 00041 00042 /*This is a function pointer that needs passed to get the effective mass*/ 00043 typedef double (*ooms_averager)(double* block, unsigned int eigvec, unsigned int L, double* func); 00044 typedef double (*wavefunction_max_delta_callback)(double* block1, unsigned vec1, double* block2, unsigned vec2, unsigned L); 00045 00046 //typedef void* (*potential_calculator_callback)(void* charge_density, void* privdat); 00047 00048 /**Gets the Fermi energy for a set of eigenvalues (2D DoS) 00049 *\param Neigs number of eigenvalues in the array (extras are OK; just don't have fewer eigs than this 00050 *\param eigs the array of eigenvalues 00051 *\param last_eig pointer to an unsigned int to store the last eig. If this is the last one, we can't be sure that Ef is the correct Ef; there may be a higher-energy subband that would fill! 00052 *\return the Fermi energy 00053 */ 00054 double get_Ef_2D(unsigned int Neigs, double* eigs, double* avg_ooms, int* last_eig, double total_density); 00055 00056 /**callback for mixing the potentials (search for "Mix the potentials" below)*/ 00057 void potential_mixing_callback(int X, unsigned N, double dx, double *restrict to, double from, void* mixing_pct); 00058 00059 /*The point of N_eigs_to_check_for_convergence is to prevent cycles by looking back N eigs.*/ 00060 template<class hamiltonian, unsigned int D, unsigned N_eigs_to_check_for_convergence=2> 00061 class self_consistent_potential { 00062 public: 00063 ~self_consistent_potential() { 00064 /*We do a bunch of these frees. Cluster them. If they're not NULL, free them. 00065 *Note that these are pointers to pointers; we keep going until the array entry is NULL (if it's a real member of this class, it won't be NULL 00066 */ 00067 /*Note that we don't care about the generic structure; we were handed it by someone else*/ 00068 void** things_to_free[] = { 00069 (void**)&dopant_density, 00070 NULL 00071 }; 00072 for(int i=0; things_to_free[i] != NULL; i++) { 00073 if(*things_to_free[i] != NULL) { 00074 free(*things_to_free[i]); 00075 *things_to_free[i] = NULL; 00076 } 00077 } 00078 delete H; 00079 } 00080 self_consistent_potential( 00081 struct ::kdotp::libmodelxx::structure::generic_structure *s, 00082 enum ::kdotp::libkdotp::hamiltonian::boundary_condition bc, 00083 ooms_averager averager_, 00084 wavefunction_max_delta_callback deltar_, double abserr_, double relerr_) 00085 : generic_structure(s), 00086 H(NULL), 00087 averager(averager_), 00088 deltar(deltar_), 00089 dopant_density(NULL), 00090 abserr(abserr_), 00091 relerr(relerr_) { 00092 H = new hamiltonian(s, bc, false); 00093 if(H == NULL) return; 00094 dopant_density = new_density_1d(((::kdotp::libmodelxx::grid::cartesian_grid<double, D>*)(s->doping_grid))->L[0], ((::kdotp::libmodelxx::grid::cartesian_grid<double, D>*)(s->doping_grid))->a[0], 0); 00095 for(unsigned int i=0; i<((::kdotp::libmodelxx::grid::cartesian_grid<double, D>*)(s->doping_grid))->L[0]; i++) { 00096 /*Dopant density is in cm^-3; convert to m^-3*/ 00097 dopant_density->storage[i] = (((::kdotp::libmodelxx::grid::cartesian_grid<double, D>*)(s->doping_grid))->data)[i]*100*100*100; 00098 //fprintf(stderr, "density[%d] = %g\n", i, dopant_density->storage[i]); 00099 } 00100 } 00101 /**Performs the actual calculation. 00102 *\param Neigs number of eigenvalues to use to do the calculation 00103 *\param max_iterations quit after max_iterations has been completed (avoids infinite loops; this can usually be a small value) 00104 *\param convergence the convergence criterion; the max change in probability density must be less than this value to be converged. 00105 *\param max_converged_eigenstate make sure all of the eigenstates up through this one are converged. 00106 *\param eigenvectors pointer to hold the address of the array of eigenvectors 00107 *\param eigenvalues pointer to hold the address of the array of eigenvalues 00108 *\param ooms_parameter parameter to pass to the Hamiltonian to get the static dielectric constant 00109 *\param density_integration_error estimate of the error from integrating the density. 00110 *\param percent_current percent of the previous potential to mix with 1-percent_current of the second-to-last to determine the potential of the current calculation. 00111 *\return a GError containing error information. NULL if successful. 00112 */ 00113 inline GError* perform_calculation(unsigned int Neigs, unsigned int max_iterations, double convergence, unsigned int max_converged_eigenstate, double** eigenvectors, double**eigenvalues, int ooms_parameter, int epsilon_parameter, double* Ef, double *density_integration_error, double *potential_integration_error, double* efield_integration_error, GFile* output_directory, double percent_current=1) { 00114 return perform_calculation(false, 0, 0, Neigs, max_iterations, convergence, max_converged_eigenstate, eigenvectors, eigenvalues, ooms_parameter, epsilon_parameter, Ef, density_integration_error, potential_integration_error, efield_integration_error, output_directory, percent_current); 00115 } 00116 inline GError* perform_calculation(double e_min, double e_max, unsigned int max_iterations, double convergence, unsigned int max_converged_eigenstate, double** eigenvectors, double**eigenvalues, int ooms_parameter, int epsilon_parameter, double* Ef, double *density_integration_error, double *potential_integration_error, double* efield_integration_error, GFile* output_directory, double percent_current=1) { 00117 return perform_calculation(true, e_min, e_max, 0, max_iterations, convergence, max_converged_eigenstate, eigenvectors, eigenvalues, ooms_parameter, epsilon_parameter, Ef, density_integration_error, potential_integration_error, efield_integration_error, output_directory, percent_current); 00118 } 00119 GError* perform_calculation(bool use_energies, double e_min, double e_max, unsigned int Neigs, unsigned int max_iterations, double convergence, unsigned int max_converged_eigenstate, double** eigenvectors, double**eigenvalues, int ooms_parameter, int epsilon_parameter, double* Ef, double *density_integration_error, double *potential_integration_error, double* efield_integration_error, GFile* output_directory, double percent_current=1) { 00120 double* average_ooms; 00121 if(use_energies) { 00122 /*For safety's sake, take many eigenvalues*/ 00123 Neigs = 50; 00124 } 00125 fprintf(stderr, "Neigs=%u\n", Neigs); 00126 average_ooms = new double[Neigs]; 00127 double* mstar = new double[H->L]; 00128 double* epsilon = new double[H->L]; 00129 struct density_1d epsilon_density; 00130 double *evecs; 00131 double *evals; 00132 int Neigs_obtained; 00133 GError *err = NULL; 00134 struct density_1d *subband_density; 00135 struct density_1d *total_density; 00136 struct density_1d *total_potential=NULL; 00137 struct density_1d *previous_potential=NULL; 00138 char fn[4096]; 00139 GFile* gf; 00140 GOutputStream* gos; 00141 GString* gs = g_string_new(""); 00142 gsize wlen; 00143 /*dx in the total doping was in units of nm; we need m here.*/ 00144 double total_doping = density_1d_integrate_density(dopant_density, abserr, relerr, density_integration_error, &err, 0)*1e-9; 00145 //double total_doping = density_1d_sum(dopant_density, CONSTANT)*(dopant_density->dx)*1e-9; 00146 fprintf(stderr, "total doping=%g\n", total_doping); 00147 if(err != NULL) { 00148 GError *e = NULL; 00149 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: Failed to integrate dopant charge density (before iterating)"); 00150 return e; 00151 } 00152 if(output_directory != NULL) { 00153 gf = g_file_get_child(output_directory, "doping.pdata"); 00154 gos = (GOutputStream*)g_file_replace(gf, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &err); 00155 if(err != NULL) { 00156 GError *e = NULL; 00157 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR opening bands file (%s)", g_file_get_uri(gf)); 00158 return e; 00159 } 00160 g_string_printf(gs, "#gridsite\tdensity(*1e18)\n"); 00161 if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &err)) { 00162 GError *e = NULL; 00163 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR writing to bands file (%s)", g_file_get_uri(gf)); 00164 return e; 00165 } 00166 for(unsigned int i=0; i<H->L; i++) { 00167 g_string_printf(gs, "%u\t%g\n", i, dopant_density->storage[i]); 00168 if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &err)) { 00169 GError *e = NULL; 00170 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR writing to bands file (%s)", g_file_get_uri(gf)); 00171 return e; 00172 } 00173 } 00174 g_object_unref(gos); 00175 } 00176 00177 int last_filled_eig; 00178 double* last_evecs[N_eigs_to_check_for_convergence]; 00179 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence; eig++) { 00180 last_evecs[eig]=NULL; 00181 } 00182 bool converged = false; 00183 /*The effective mass across the structure won't change between iterations*/ 00184 H->get_parameter_function(ooms_parameter, mstar); 00185 H->get_parameter_function(epsilon_parameter, epsilon); 00186 epsilon_density.storage = epsilon; 00187 epsilon_density.N = H->L; 00188 /*H has units in m; we need nm*/ 00189 epsilon_density.dx = H->dx; 00190 total_density = new_density_1d(H->L, H->dx, 0); 00191 if(unlikely(total_density == NULL)) { 00192 delete[] average_ooms; 00193 delete[] mstar; 00194 delete[] epsilon; 00195 return g_error_new(CALCULATION_SELF_CONSISTENT_GERROR_DOMAIN, 5, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: failed to allocate storage for the total subband density"); 00196 } 00197 subband_density = new_density_1d(H->L, H->dx, 0); 00198 if(unlikely(subband_density == NULL)) { 00199 free_density_1d(total_density); 00200 delete[] average_ooms; 00201 delete[] mstar; 00202 delete[] epsilon; 00203 return g_error_new(CALCULATION_SELF_CONSISTENT_GERROR_DOMAIN, 5, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: failed to allocate storage for the total subband density"); 00204 } 00205 /*The internal potential is currently 0.*/ 00206 for(unsigned int iter=0; iter<max_iterations; iter++) { 00207 fprintf(stderr, "ITER %u\n\n", iter); 00208 if(use_energies) { 00209 evecs = H->get_eigenvectors_double(e_min, e_max, &evals, &Neigs_obtained, &err); 00210 }else{ 00211 evecs = H->get_eigenvectors_int(1, (int)Neigs, &evals, &Neigs_obtained, &err); 00212 } 00213 if(unlikely(err != NULL)) { 00214 *eigenvectors = evecs; 00215 *eigenvalues = evals; 00216 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence; eig++) { 00217 if(last_evecs[eig] != NULL) free(last_evecs[eig]); 00218 } 00219 free_density_1d(subband_density); 00220 if(total_potential != NULL) free_density_1d(total_potential); 00221 if(previous_potential != NULL) free_density_1d(previous_potential); 00222 free_density_1d(total_density); 00223 GError *e = NULL; 00224 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: Failed to get eigenvalues in iteration %u/%u.", iter, max_iterations); 00225 delete[] average_ooms; 00226 delete[] mstar; 00227 delete[] epsilon; 00228 return e; 00229 } 00230 if(unlikely(Neigs_obtained != (int)Neigs)) { 00231 *eigenvectors = evecs; 00232 *eigenvalues = evals; 00233 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence; eig++) { 00234 if(last_evecs[eig] != NULL) free(last_evecs[eig]); 00235 } 00236 free_density_1d(subband_density); 00237 if(total_potential != NULL) free_density_1d(total_potential); 00238 if(previous_potential != NULL) free_density_1d(previous_potential); 00239 free_density_1d(total_density); 00240 delete[] average_ooms; 00241 delete[] mstar; 00242 delete[] epsilon; 00243 return g_error_new(CALCULATION_SELF_CONSISTENT_GERROR_DOMAIN, 2, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: Got incorrect number of eigenvalues from LAPACK: %u requested, %d obtained @iteration %u", Neigs, Neigs_obtained, iter); 00244 } 00245 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence; eig++) { 00246 if(last_evecs[eig] != NULL) { 00247 for(unsigned int i=0; i<max_converged_eigenstate; i++) { 00248 double delta; 00249 delta = deltar(evecs, i, last_evecs[eig], i, H->L); 00250 if(delta < 0) { 00251 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence; eig++) { 00252 if(last_evecs[eig] != NULL) free(last_evecs[eig]); 00253 } 00254 free_density_1d(subband_density); 00255 if(total_potential != NULL) free_density_1d(total_potential); 00256 if(previous_potential != NULL) free_density_1d(previous_potential); 00257 free_density_1d(total_density); 00258 delete[] average_ooms; 00259 delete[] mstar; 00260 delete[] epsilon; 00261 return g_error_new(CALCULATION_SELF_CONSISTENT_GERROR_DOMAIN, 7, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: Got error in deltar: %g\n", -delta); 00262 } 00263 if(convergence < delta) { 00264 fprintf(stderr, "%u: delta=%g UNCONVERGED (convergence=%g)\n", i, delta, convergence); 00265 converged = false; 00266 break; 00267 }else{ 00268 fprintf(stderr, "%u: delta=%g CONVERGED (convergence=%g)\n", i, delta, convergence); 00269 } 00270 converged = true; 00271 } 00272 /*if just one converges, break.*/ 00273 if(converged) break; 00274 } 00275 } 00276 fprintf(stderr, "Converged? %s\n", converged?"Yes":"No"); 00277 /*Verify our potential*/ 00278 double* potcheck = (double*)malloc(sizeof(double)*(H->L)); 00279 if(potcheck == NULL) { 00280 return g_error_new(CALCULATION_SELF_CONSISTENT_GERROR_DOMAIN, 15, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: Failed to allocate potential check."); 00281 } 00282 H->get_parameter_function(::kdotp::libkdotp::hamiltonian::TOTAL_POTENTIAL, potcheck); 00283 //for(unsigned i=0; i<H->L; i++) fprintf(stderr, "pc@%u: %g\n", i, potcheck[i]); 00284 free(potcheck); 00285 if(converged) { 00286 *eigenvectors = evecs; 00287 *eigenvalues = evals; 00288 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence; eig++) { 00289 if(last_evecs[eig] != NULL) free(last_evecs[eig]); 00290 } 00291 free_density_1d(subband_density); 00292 if(total_potential != NULL) free_density_1d(total_potential); 00293 if(previous_potential != NULL) free_density_1d(previous_potential); 00294 free_density_1d(total_density); 00295 delete[] average_ooms; 00296 delete[] mstar; 00297 delete[] epsilon; 00298 return NULL; 00299 } 00300 for(unsigned int i=0; i<Neigs; i++) 00301 average_ooms[i] = averager(evecs, i, H->L, mstar); 00302 *Ef = get_Ef_2D(Neigs, evals, average_ooms, &last_filled_eig, total_doping); 00303 if(unlikely(last_filled_eig < 0)) { 00304 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence; eig++) { 00305 if(last_evecs[eig] != NULL) free(last_evecs[eig]); 00306 } 00307 free_density_1d(subband_density); 00308 if(total_potential != NULL) free_density_1d(total_potential); 00309 if(previous_potential != NULL) free_density_1d(previous_potential); 00310 free_density_1d(total_density); 00311 delete[] average_ooms; 00312 delete[] mstar; 00313 delete[] epsilon; 00314 return g_error_new(CALCULATION_SELF_CONSISTENT_GERROR_DOMAIN, 3, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: @iter %u: last filled eigenstate (%u) is invalid; no levels are filled!", iter, last_filled_eig); 00315 } 00316 if(unlikely((unsigned)last_filled_eig >= Neigs)) { 00317 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence; eig++) { 00318 if(last_evecs[eig] != NULL) free(last_evecs[eig]); 00319 } 00320 free_density_1d(subband_density); 00321 if(total_potential != NULL) free_density_1d(total_potential); 00322 if(previous_potential != NULL) free_density_1d(previous_potential); 00323 free_density_1d(total_density); 00324 delete[] average_ooms; 00325 delete[] mstar; 00326 delete[] epsilon; 00327 return g_error_new(CALCULATION_SELF_CONSISTENT_GERROR_DOMAIN, 3, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: @iter %u: last filled eigenstate (%u) is the same as the highest calculated eigenstate (%u); we can't be sure there aren't higher filled levels!", iter, Neigs, last_filled_eig); 00328 } 00329 init_density_1d(total_density, 0); 00330 for(unsigned int subband=0; subband <= (unsigned)last_filled_eig; subband++) { 00331 if(unlikely((err = init_density_1d_from_cartesian_effective_mass_block(evecs, subband, H->L, H->dx, subband_density)) != NULL)) { 00332 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence; eig++) { 00333 if(last_evecs[eig] != NULL) free(last_evecs[eig]); 00334 } 00335 free_density_1d(subband_density); 00336 if(total_potential != NULL) free_density_1d(total_potential); 00337 if(previous_potential != NULL) free_density_1d(previous_potential); 00338 free_density_1d(total_density); 00339 delete[] average_ooms; 00340 delete[] mstar; 00341 delete[] epsilon; 00342 GError *e = NULL; 00343 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: @iter %u: failed to set density from wavefunction for subband %u: ", iter, subband); 00344 return e; 00345 } 00346 GError *eerr=NULL; 00347 double dier; 00348 double sum = 0; 00349 for(unsigned i=0; i<subband_density->N; i++) sum += subband_density->storage[i]; 00350 fprintf(stderr, "subband %u: density of this subband is: %g (sum is %g)\n", subband, density_1d_integrate_density(subband_density, abserr, relerr, &dier, &eerr, 1), sum); 00351 /*Multiply the single-electron charge density from the eigenstate by the number of electrons in this state.*/ 00352 density_1d_mul_by_const(subband_density, 2*M_PI*kdp::constants::m0/(kdp::constants::hbar*kdp::constants::hbar*average_ooms[subband])*((*Ef)-evals[subband])); 00353 fprintf(stderr, "Subband %u: after multpliying by total areal charge density (%g), have total areal cahrge density of %g\n", subband, 2*M_PI*kdp::constants::m0/(kdp::constants::hbar*kdp::constants::hbar*average_ooms[subband])*((*Ef)-evals[subband]), density_1d_integrate_density(subband_density, abserr, relerr, &dier, &eerr, 2)); 00354 op_density_1d_to_density_1d(total_density, ADD_EQUALS, subband_density); 00355 } 00356 /*We have |Psi|^2*dx (so the sum is 1) in the total density right now. We need to convert 00357 * it to a charge density. 00358 * |Psi|^2*dx / dx = |Psi|^2 -> 1/m 00359 *Note that we also multiply by a minus sign (negative charge; the magnitude will come in a few lines, when we add in the dopants 00360 */ 00361 density_1d_mul_by_const(total_density, -1.0/(total_density->dx*1e-9)); 00362 double edensity_ierr; 00363 GError *eee=NULL; 00364 double total_electron_density = density_1d_integrate_density(total_density, abserr, relerr, &edensity_ierr, &eee, 3)*1e-9; 00365 /*Renormalize such that we multiply by the percentage we actually want*/ 00366 density_1d_mul_by_const(total_density, fabs(1.0-(fabs(total_electron_density)-fabs(total_doping))/fabs(total_doping))); 00367 double edensity2_ierr; 00368 double total_electron_density_2 = density_1d_integrate_density(total_density, abserr, relerr, &edensity2_ierr, &eee, 6)*1e-9; 00369 //fprintf(stderr, "total_density->dx = %g\n", total_density->dx); 00370 op_density_1d_to_density_1d(total_density, ADD_EQUALS, dopant_density); 00371 double tcdensity_ierr; 00372 double total_calculated_density = density_1d_integrate_density(total_density, abserr, relerr, &edensity_ierr, &eee, 4)*1e-9; 00373 fprintf(stderr, "total dopant density: %.15g total electron density: %.15g sum: %.15g -> %.15g (%g): total calculated density: %.15g \n", total_doping, total_electron_density, total_doping + total_electron_density, total_electron_density_2, total_doping + total_electron_density_2, total_calculated_density); 00374 /*Now multiply by the magnitude of the charge of an electron*/ 00375 /*Multiply the total potential by the grid spacing, since we're taking the second derivative.*/ 00376 density_1d_mul_by_const(total_density, kdp::constants::e); 00377 //total_potential = get_potential_for_density_1d(total_density, &epsilon_density, NULL); 00378 total_potential = potential_1d_get_potential(0.0, 0.0, total_density, &epsilon_density, INTEGRATION_METHOD_NP, potential_integration_error, efield_integration_error, relerr, abserr, &err); 00379 if((total_potential == NULL) || (err != NULL)) { 00380 if(err == NULL) { 00381 err = g_error_new(CALCULATION_SELF_CONSISTENT_GERROR_DOMAIN, 4, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: @iter %u/%u: error getting potential from total electron density distribution (got NULL)", iter, max_iterations); 00382 } 00383 GError *e = NULL; 00384 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: @iter %u/%u: failed to get potential for charge density: ", iter, max_iterations); 00385 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence; eig++) { 00386 if(last_evecs[eig] != NULL) free(last_evecs[eig]); 00387 } 00388 free_density_1d(subband_density); 00389 if(total_potential != NULL) free_density_1d(total_potential); 00390 if(previous_potential != NULL) free_density_1d(previous_potential); 00391 free_density_1d(total_density); 00392 delete[] average_ooms; 00393 delete[] mstar; 00394 delete[] epsilon; 00395 return err; 00396 } 00397 /*Potential was integrated twice with x in the implicit-nm basis; convert to m*/ 00398 density_1d_mul_by_const(total_potential, 1e-9*1e-9); 00399 if(percent_current < 1) { 00400 /*Mix the potentials*/ 00401 if(previous_potential != NULL) { 00402 op_density_1d_to_density_1d_cb(total_potential, previous_potential, potential_mixing_callback, (void*)&percent_current); 00403 free(previous_potential); 00404 } 00405 /*Now that we're done mixing, update.*/ 00406 previous_potential = new_density_1d_copy(total_potential); 00407 } 00408 /**Write out the iteration*/ 00409 if(output_directory != NULL) { 00410 double sum, val; 00411 for(unsigned int j=0; j<Neigs; j++) { 00412 g_string_printf(gs, "i%u_eigvec_%d.pdata", iter, j); 00413 gf = g_file_get_child(output_directory, gs->str); 00414 gos = (GOutputStream*)g_file_replace(gf, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &err); 00415 if(err != NULL) { 00416 GError *e = NULL; 00417 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR opening eigvec file (%s)", g_file_get_uri(gf)); 00418 return e; 00419 } 00420 g_string_printf(gs, "#gridsite\tpsi\n"); 00421 if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &err)) { 00422 GError *e = NULL; 00423 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR writing to bands file (%s)", g_file_get_uri(gf)); 00424 return e; 00425 } 00426 for(unsigned int i=0; i<H->L; i++) { 00427 g_string_printf(gs, "%u\t%g\n", i, evecs[i + j*H->L]); 00428 if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &err)) { 00429 GError *e = NULL; 00430 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR writing to bands file (%s)", g_file_get_uri(gf)); 00431 return e; 00432 } 00433 } 00434 g_object_unref(gos); 00435 } 00436 g_string_printf(gs, "i%u_pot.pdata", iter); 00437 gf = g_file_get_child(output_directory, gs->str); 00438 gos = (GOutputStream*)g_file_replace(gf, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &err); 00439 if(err != NULL) { 00440 GError *e = NULL; 00441 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR opening eigvec file (%s)", g_file_get_uri(gf)); 00442 return e; 00443 } 00444 g_string_printf(gs, "#gridsite\tpot(eV)\n"); 00445 if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &err)) { 00446 GError *e = NULL; 00447 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR writing to bands file (%s)", g_file_get_uri(gf)); 00448 return e; 00449 } 00450 for(unsigned int i=0; i<total_potential->N; i++) { 00451 g_string_printf(gs, "%u\t%g\n", i, total_potential->storage[i]); 00452 if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &err)) { 00453 GError *e = NULL; 00454 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR writing to bands file (%s)", g_file_get_uri(gf)); 00455 return e; 00456 } 00457 } 00458 g_object_unref(gos); 00459 00460 g_string_printf(gs, "i%u_total_density.pdata", iter); 00461 gf = g_file_get_child(output_directory, gs->str); 00462 gos = (GOutputStream*)g_file_replace(gf, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &err); 00463 if(err != NULL) { 00464 GError *e = NULL; 00465 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR opening density file (%s)", g_file_get_uri(gf)); 00466 return e; 00467 } 00468 g_string_printf(gs, "#gridsite\tdensity(m^-3)*a^2\n"); 00469 if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &err)) { 00470 GError *e = NULL; 00471 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR writing to bands file (%s)", g_file_get_uri(gf)); 00472 return e; 00473 } 00474 for(unsigned int i=0; i<total_density->N; i++) { 00475 g_string_printf(gs, "%u\t%g\n", i, total_density->storage[i]); 00476 if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &err)) { 00477 GError *e = NULL; 00478 g_propagate_prefixed_error(&e, err, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: ERROR writing to bands file (%s)", g_file_get_uri(gf)); 00479 return e; 00480 } 00481 } 00482 g_object_unref(gos); 00483 } 00484 /**Final step: copy the new potential through. 00485 *Make sure we copy off the values into a new density so that we don't delete the 00486 * potential array when we exit this function and free the host potential_1d structure 00487 */ 00488 density_1d* tp = new_density_1d_copy(total_potential); 00489 H->replace_internal_potential(tp->storage); 00490 /*Free the struct itself; not the array inside.*/ 00491 free(tp); 00492 free(evals); 00493 if(last_evecs[N_eigs_to_check_for_convergence-1] != NULL) free(last_evecs[N_eigs_to_check_for_convergence-1]); 00494 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence-1; eig++) { 00495 last_evecs[eig+1]=last_evecs[eig]; 00496 } 00497 last_evecs[0] = evecs; 00498 } 00499 /*If we've hit this point, we hit the max number of iterations without success.*/ 00500 for(unsigned eig=0; eig<N_eigs_to_check_for_convergence; eig++) { 00501 if(last_evecs[eig] != NULL) free(last_evecs[eig]); 00502 } 00503 free_density_1d(subband_density); 00504 if(total_potential != NULL) free_density_1d(total_potential); 00505 if(previous_potential != NULL) free_density_1d(previous_potential); 00506 free_density_1d(total_density); 00507 delete[] average_ooms; 00508 delete[] mstar; 00509 delete[] epsilon; 00510 return g_error_new(CALCULATION_SELF_CONSISTENT_GERROR_DOMAIN, 1, "kdotp::libkdotp::calculation_self_consistent_potential::perform_calculation: Maximum number of iterations (%u) reached without convergence.", max_iterations); 00511 } 00512 struct ::kdotp::libmodelxx::structure::generic_structure *generic_structure; 00513 hamiltonian* H; 00514 ooms_averager averager; 00515 wavefunction_max_delta_callback deltar; 00516 struct density_1d *dopant_density; 00517 /** Tolerances for GSL-based integration.*/ 00518 double abserr; 00519 double relerr; 00520 }; 00521 00522 } 00523 } 00524 } 00525 00526 #endif