k-dot-p 0.1

calculation_self_consistent_potential.h++

Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines