k-dot-p 0.1

oneoff_optimize_1d.c++

Go to the documentation of this file.
00001 /*
00002  *A quick program to perform a 1D k-dot-p calc
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 /*The following line will be removed in the auto-generated MPI variant.*/
00022 #undef HAVE_MPI
00023 
00024 #include <string>
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <sys/stat.h>
00028 #include <sys/types.h>
00029 #include <glib.h>
00030 #include <gio/gio.h>
00031 #include <gsl/gsl_errno.h>
00032 #include <libmodelxx/matdb.h++>
00033 #include <libmodelxx/matdb-dotcode.h++>
00034 #include <libmodelxx/continuous_structure.h++>
00035 #include <libmodelxx/generic_structure.h++>
00036 #include <libmodelxx/cartesian_grid.h++>
00037 #include <libkdotp/hamiltonians.h++>
00038 #include <libmodelxx/grid.h++>
00039 #include <libmodelxx/material.h++>
00040 #include <libmodelxx/utilities.h++>
00041 #include <libmetacalc/calculation_self_consistent_potential.h++>
00042 #include <libkdotp/wavefunction_cartesian_effective_mass.h++>
00043 #include <libpostproccalx/alpha_calc.h>
00044 #include <libmodelxx/function_specification.h++>
00045 #include <libmetacalc/digital_alloy_optimizer_1d.h++>
00046 #include <libmetacalc/continuous_alloy_optimizer_1d.h++>
00047 #ifdef HAVE_MPI
00048 #include <mpi.h>
00049 #include <libmetacalc/digital_alloy_optimizer_1d_mpi.h++>
00050 #endif
00051 #include "oneoff_optimize_1d_argprocess.h++"
00052 
00053 using namespace kdotp::libmodelxx::continuous_structure;
00054 using namespace kdotp::libmodelxx::structure;
00055 using namespace kdotp::libmodelxx::grid;
00056 using namespace kdotp::libkdotp::hamiltonian;
00057 using namespace kdotp::libmodelxx::utilities;
00058 using namespace kdotp::libmetacalc::self_consistent;
00059 using namespace kdotp::libkdotp::wavefunction;
00060 using namespace kdotp::libmodelxx::postprocessing;
00061 using namespace std;
00062 using namespace kdotp::libmetacalc::optimizer;
00063 
00064 static void free_value(void* value, void* pridat) {free(value);}
00065 static void delete_double(void* value, void* pridat) {delete (double*)value;}
00066 void set_point_callback(unsigned X, const material* mat, void* privdat);
00067 double alpha_efield_change_calculation_callback(void* privdat, unsigned assignment, long unsigned iteration);
00068 double calculate_alpha_for_structure(void* privdat, unsigned assignment, long unsigned iteration);
00069 void write_raw_bands_file(GFile* file, struct generic_structure* genstruct);
00070 
00071 void yyparse();
00072 int yylex();
00073 extern int yydebug;
00074 
00075 extern struct continuous_structure* the_structure;
00076 extern GInputStream* instream;
00077 
00078 typedef kdotp::libmodelxx::grid::cartesian_grid<kdotp::libmodelxx::structure::material*,1,1> matgrid;
00079 typedef kdotp::libmodelxx::grid::cartesian_grid<double,1,1> potgrid;
00080 
00081 struct set_point_callback_privdat {
00082   struct generic_structure *genstruct;
00083   self_consistent_potential< ::kdotp::libkdotp::hamiltonian::cartesian_effective_mass, 1>* scpot_calc;
00084   GFile* base_job_directory;
00085   GOutputStream* alpha_by_iteration_gos;
00086   GFile* alpha_by_iteration_file;
00087   /*This stores the different alpha values from the current computation.*/
00088   double alpha_iface;
00089   double alpha_efield;
00090   double alpha_method2;
00091   double alpha_iface_0field;
00092   double alpha_efield_0field;
00093   double alpha_method2_0field;
00094   double Ep;
00095   gboolean do_nofield_comparison;
00096   #ifdef HAVE_MPI
00097   int N_nodes;
00098   int node;
00099   #endif
00100 };
00101 
00102 
00103 static void gsl_error_handler (const char * reason, const char * file, int line, int gsl_errno) {
00104   //fprintf(stderr, "GSL error occured in file %s, line %d (%d: %s).  This should be caught by the calling function, or report a bug.\n", file, line, gsl_errno, reason);
00105 }
00106 
00107 int main(int argc, char **argv) {
00108   g_type_init();
00109   #ifdef HAVE_MPI
00110   MPI_Init(&argc, &argv);
00111   #endif
00112   gsl_set_error_handler(&gsl_error_handler);
00113   //yydebug = 1;
00114   struct args args;
00115   int err;
00116   err = process_args(argc, argv, &args);
00117   if(err != 0) exit(1);
00118   fprintf(stderr, "Got minx=%g maxx=%g stepsize=%g multiplier=%g min_stepsize=%g\n", args.minx, args.maxx, args.stepsize, args.multiplier, args.min_stepsize);
00119   GString *mdb_file = g_string_new(args.matdb);
00120   struct matdb* mdb = read_matdb_dotcode(mdb_file, &err);
00121   if(mdb == NULL) {
00122     fprintf(stderr, "ERROR reading in the materials database %s: %d\n", args.matdb, err); 
00123     #ifdef HAVE_MPI
00124     MPI_Finalize();
00125     #endif
00126     return 1;
00127   }
00128 
00129   /*Insert the fake material into the mdb.*/
00130   ::kdotp::libmodelxx::structure::insert_external_material(mdb, args.optimizer_material);
00131 
00132   GList* l;
00133   GError* gerr = NULL;
00134   GString *gs = g_string_new("");
00135   gsize wlen;
00136   GHashTable *gst = new_symbol_table();
00137   GString *alpha_filename = g_string_new("");
00138   GFile* alpha_file;
00139   #ifdef HAVE_MPI
00140   int node;
00141   int N_nodes;
00142   MPI_Comm_rank(MPI_COMM_WORLD, &node);
00143   MPI_Comm_size(MPI_COMM_WORLD, &N_nodes);
00144   #endif
00145   for(l=(args.filestreams); l != NULL; l=l->next) {
00146     parameter_list_init(args.template_parameters);
00147     alpha_filename = g_string_assign(alpha_filename, ((struct file_info*)(l->data))->filename->str);
00148     alpha_filename = g_string_append(alpha_filename, "_alpha.pdata");
00149     alpha_file = g_file_new_for_path(alpha_filename->str);
00150     g_string_free(alpha_filename, TRUE);
00151     GOutputStream* alpha_gos = (GOutputStream*)g_file_replace(alpha_file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &gerr);
00152     if(gerr != NULL) {
00153       fprintf(stderr, "ERROR opening alpha file (%s): %s\n", g_file_get_uri(alpha_file), gerr->message);
00154       exit(32);
00155     }
00156     g_string_printf(gs, "#");
00157     char* paramstring;
00158     g_string_append(gs, paramstring = get_header_for_template_state(args.template_parameters));
00159     g_free(paramstring);
00160     g_string_append_printf(gs, "\tstartstruct\tEp\talpha_iface (eVm)\talpha_efield\talpha method 1(eVm)\talpha method2(eVm)\n");
00161     if(!g_output_stream_write_all(alpha_gos, gs->str, gs->len, &wlen, NULL, &gerr)) {
00162       fprintf(stderr, "ERROR writing to alpha file (%s): %s\n", g_file_get_uri(alpha_file), gerr->message);
00163       exit(32);
00164     }
00165     gerr = NULL;
00166     GString *gfn=g_string_new(((struct file_info*)(l->data))->filename->str);
00167     gfn = g_string_append(gfn, "_output/");
00168     do {
00169       add_template_parameters_to_symbol_table(gst, args.template_parameters);
00170       GFile* file_directory = get_gfile_directory_for_template_state(gfn->str, args.template_parameters);
00171       g_file_make_directory_with_parents(file_directory, NULL, &gerr);
00172       if(gerr != NULL) {
00173   if(gerr->code != G_IO_ERROR_EXISTS) {
00174     char* fn = g_file_get_uri(file_directory);
00175     fprintf(stderr, "ERROR creating the target directory for templated job (%s): %s\n", fn, gerr->message);
00176     g_free(fn);
00177     exit(5);
00178   }else{
00179     /*If the directory already exists, that's OK.*/
00180     g_error_free(gerr);
00181     gerr = NULL;
00182   }
00183       }
00184       for(unsigned sstruct=0; sstruct<args.N_starting_points; sstruct++) {
00185   /*For now, we read in the file over and over.  It's inefficient, but not *that* inefficient.*/
00186   instream = (GInputStream*)((struct file_info*)(l->data))->instream;
00187   yyparse();
00188   if(the_structure == NULL) {
00189     fprintf(stderr, "the_structure was NULL!\n");
00190     exit(1);
00191   }
00192   struct generic_structure *s = postprocess_structure(the_structure, mdb, gst, &gerr);
00193   if(gerr != NULL) {
00194     fprintf(stderr, "ERROR while postprocessing structure: %s\n", gerr->message);
00195           #ifdef HAVE_MPI
00196     MPI_Finalize();
00197           #endif
00198     return 5;
00199   }
00200   fprintf(stderr, "got structure!\n");
00201 
00202   material* markermat = new material(mdb, args.optimizer_material, NULL, 1);
00203   material* mat1=NULL;
00204   material* mat0=NULL;
00205   if(!(args.continuous)) {
00206     mat1 = new material(mdb, args.mat1.mat1, args.mat1.mat2, args.mat1.x);
00207     mat0 = new material(mdb, args.mat0.mat1, args.mat0.mat2, args.mat0.x);
00208   }
00209 
00210   GError *e = NULL;
00211   /**We have the structure set up.  Now we need to set up the optimizer.
00212    *\note that this is used for both set_point and calculate_alpha_for_structure.
00213    */
00214   GString *iter_dirname = g_string_new("");
00215   g_string_append_printf(iter_dirname, "%s_optimizer_start_%u", (args.continuous)?"continuous":"digital", sstruct);
00216   GFile* job_directory = g_file_get_child(file_directory, iter_dirname->str);
00217   g_string_free(iter_dirname, TRUE);
00218   g_file_make_directory_with_parents(job_directory, NULL, &gerr);
00219   if(gerr != NULL) {
00220     if(gerr->code != G_IO_ERROR_EXISTS) {
00221       char* fn = g_file_get_uri(job_directory);
00222       fprintf(stderr, "ERROR creating the target directory for templated job (%s): %s\n", fn, gerr->message);
00223       g_free(fn);
00224       exit(5);
00225     }else{
00226       /*If the directory already exists, that's OK.*/
00227       g_error_free(gerr);
00228       gerr = NULL;
00229     }
00230   }
00231   GString *alpha_by_iter_filename = g_string_new("alpha_sstruct");
00232   #ifdef HAVE_MPI
00233   g_string_append_printf(alpha_by_iter_filename, "_node%d", node);
00234   #endif
00235   g_string_append_printf(alpha_by_iter_filename, "=%u.pdata", sstruct);
00236   GFile* alpha_by_iter_file = g_file_get_child(job_directory, alpha_by_iter_filename->str);
00237   g_string_free(alpha_by_iter_filename, TRUE);
00238   GOutputStream* alpha_by_iter_gos = (GOutputStream*)g_file_replace(alpha_by_iter_file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &gerr);
00239   if(gerr != NULL) {
00240     fprintf(stderr, "ERROR opening alpha_by_iter file (%s): %s\n", g_file_get_uri(alpha_by_iter_file), gerr->message);
00241     exit(32);
00242   }
00243   g_string_printf(gs, "#");
00244   g_string_append(gs, paramstring = get_header_for_template_state(args.template_parameters));
00245   g_free(paramstring);
00246   g_string_append_printf(gs, "iteration\ttotal\tiface\tefield");
00247   if(args.do_nofield_comparison) {
00248     g_string_append_printf(gs, "total 0field\tiface 0field\tefield 0field\ttotal difference\tiface difference\tefield difference\n");
00249   }else{
00250     gs = g_string_append(gs, "\n");
00251   }
00252   if(!g_output_stream_write_all(alpha_by_iter_gos, gs->str, gs->len, &wlen, NULL, &gerr)) {
00253     fprintf(stderr, "ERROR writing to alpha_by_iteration file (%s): %s\n", g_file_get_uri(alpha_by_iter_file), gerr->message);
00254     exit(32);
00255   }
00256 
00257   GFile* dump_file = g_file_get_child(job_directory, "structure.griddump");
00258   gerr = generic_structure_dump(s, dump_file);
00259   if(gerr != NULL) {
00260     fprintf(stderr, "ERROR while dumping structure: %s\n", gerr->message);
00261           #ifdef HAVE_MPI
00262     MPI_Finalize();
00263           #endif
00264     return 5;
00265   }
00266   fprintf(stderr, "got structure!\n");
00267   struct set_point_callback_privdat spcp = {
00268     s,
00269     NULL,
00270     job_directory,
00271     alpha_by_iter_gos,
00272     alpha_by_iter_file,
00273     0,
00274     0,
00275     0,
00276     0,
00277     0,
00278     0,
00279     0,
00280     args.do_nofield_comparison
00281     #ifdef HAVE_MPI
00282     N_nodes,
00283     node,
00284     #endif
00285   };
00286         #ifdef HAVE_MPI
00287   digital_alloy_optimizer_1d_mpi* digital_optimizer_mpi=NULL;
00288         #endif
00289   digital_alloy_optimizer_1d* optimizer=NULL;
00290   continuous_alloy_optimizer_1d* continuous_optimizer=NULL;
00291   if(args.continuous) {
00292     continuous_optimizer = new continuous_alloy_optimizer_1d(markermat, args.mat1.mat1, args.mat0.mat1, s, &set_point_callback, args.blocksize, continuous_alloy_optimizer_1d::MAXIMIZE_ABS, &e, (void*)&spcp, mdb, args.minx, args.maxx, args.seed_value, args.stepsize, args.N_blocks, args.assignments, args.assignment_expr);
00293   }else{
00294           #ifdef HAVE_MPI
00295     if(args.mpi) {
00296       digital_optimizer_mpi = new digital_alloy_optimizer_1d_mpi(markermat, mat1, mat0, s, &set_point_callback, args.blocksize, digital_alloy_optimizer_1d_mpi::MAXIMIZE_ABS, &e, (void*)&spcp, N_nodes, node, args.N_blocks, args.seed_value, args.assignments, args.assignment_expr, args.temperature);
00297     }else{
00298             #endif
00299       optimizer = new digital_alloy_optimizer_1d(markermat, mat1, mat0, s, &set_point_callback, args.blocksize, digital_alloy_optimizer_1d::MAXIMIZE_ABS, &e, (void*)&spcp, args.N_blocks, args.seed_value, args.assignments, args.assignment_expr);
00300       #ifdef HAVE_MPI
00301     }
00302             #endif
00303   }
00304   if(e != NULL) {
00305     fprintf(stderr, "ERROR setting up optimizer: %s", e->message);
00306           #ifdef HAVE_MPI
00307     MPI_Finalize();
00308           #endif
00309     return 102;
00310   }
00311   if(args.continuous) {
00312     e = continuous_optimizer->do_optimization(args.do_nofield_comparison?&alpha_efield_change_calculation_callback:&calculate_alpha_for_structure, (void*)&spcp, (void*)&spcp, args.multiplier, args.min_stepsize);
00313   }else{
00314     #ifdef HAVE_MPI
00315     if(args.mpi) {
00316       e = digital_optimizer_mpi->do_optimization(args.do_nofield_comparison?&alpha_efield_change_calculation_callback:&calculate_alpha_for_structure, (void*)&spcp, (void*)&spcp, args.anneal_start, args.anneal_end, args.num_anneal_steps, args.anneal_cycles, args.calculation_steps_per_annealing_step);
00317     }else{
00318       #endif
00319       e = optimizer->do_optimization(args.do_nofield_comparison?&alpha_efield_change_calculation_callback:&calculate_alpha_for_structure, (void*)&spcp, (void*)&spcp);
00320       #ifdef HAVE_MPI
00321     }
00322             #endif
00323   }
00324   if(e != NULL) {
00325     fprintf(stderr, "ERROR running optimizer: %s", e->message);
00326           #ifdef HAVE_MPI
00327     MPI_Finalize();
00328           #endif
00329     return 103;
00330   }
00331   gs = g_string_assign(gs, paramstring=get_string_for_template_state(args.template_parameters));
00332   g_free(paramstring);
00333   g_string_append_printf(gs, "\t%u\t%g\t%g\t%g\t%g\t%g", sstruct, spcp.Ep, spcp.alpha_iface, spcp.alpha_efield, spcp.alpha_iface + spcp.alpha_efield, spcp.alpha_method2);
00334   if(args.do_nofield_comparison) {
00335     g_string_append_printf(gs, "\t%g\t%g\t%g\t%g\t%g\t%g\t%g\n", spcp.alpha_iface_0field, spcp.alpha_efield_0field, spcp.alpha_iface_0field + spcp.alpha_efield_0field, spcp.alpha_method2, spcp.alpha_iface - spcp.alpha_iface_0field, spcp.alpha_efield - spcp.alpha_efield_0field, (spcp.alpha_iface - spcp.alpha_iface_0field) + (spcp.alpha_efield - spcp.alpha_efield_0field));
00336   }else{
00337     gs = g_string_append(gs, "\n");
00338   }
00339   if(!g_output_stream_write_all(alpha_gos, gs->str, gs->len, &wlen, NULL, &gerr)) {
00340     fprintf(stderr, "ERROR writing to alpha file (%s): %s\n", g_file_get_uri(alpha_file), gerr->message);
00341     exit(32);
00342   }
00343   dump_file = g_file_get_child(job_directory, "final-structure.griddump");
00344   gerr = generic_structure_dump(s, dump_file);
00345   if(gerr != NULL) {
00346     fprintf(stderr, "ERROR while dumping structure: %s\n", gerr->message);
00347           #ifdef HAVE_MPI
00348     MPI_Finalize();
00349           #endif
00350     return 5;
00351   }
00352   GFile* file = g_file_get_child(job_directory, "final-bands.pdata");
00353   write_raw_bands_file(file, spcp.genstruct);
00354   if(args.continuous) {
00355     delete continuous_optimizer;
00356   }else{
00357     delete optimizer;
00358   }
00359   g_object_unref(alpha_by_iter_gos);
00360   g_object_unref(alpha_by_iter_file);
00361   generic_structure_free(s);
00362       }
00363       g_object_unref(file_directory);
00364     }while(!update_parameters_plus_check_if_done(args.template_parameters));
00365     g_string_free(gfn, TRUE);
00366     g_object_unref(alpha_gos);
00367     g_object_unref(alpha_file);
00368   }
00369   #ifdef HAVE_MPI
00370   MPI_Finalize();
00371   #endif
00372   return 0;
00373 }
00374 
00375 void set_point_callback(unsigned X, const material* mat, void* privdat) {
00376   struct set_point_callback_privdat* spcp = (struct set_point_callback_privdat*)privdat;
00377   /*We don't need to do anything if we've not yet set up the calculation (and therefore also not the hamiltonian).*/
00378   if(spcp->scpot_calc == NULL) return;
00379   /**\note that it'll likely be faster to introduce a special routine to just change the nearest neighbors of this point.*/
00380 }
00381 
00382 double alpha_efield_change_calculation_callback(void* privdat, unsigned assignment, long unsigned iteration) {
00383   struct set_point_callback_privdat* spcp = (struct set_point_callback_privdat*)privdat;
00384   /*We set the job directory to "with_field/" and "without_field/" for each respective run
00385     Additionally, we save off the alpha values that are being overwritten.
00386     Technically, Ep should change (it's an average), but not a lot.
00387    */
00388   GFile* original_base_job_dir = spcp->base_job_directory;
00389 
00390   GError* e = NULL;
00391   void* original_applied_potential = spcp->genstruct->potential_grid;
00392   if(e != NULL) {
00393     fprintf(stderr, "ERROR making 0-potential grid: %s\n", e->message);
00394     g_error_free(e);
00395     exit(64);
00396   }
00397   spcp->genstruct->potential_grid = set_up_grid<double>(spcp->genstruct->g, 0, &e);
00398   spcp->base_job_directory = g_file_get_child(original_base_job_dir, "without_field");
00399   calculate_alpha_for_structure(privdat, assignment, iteration);
00400 
00401   generic_structure_free_potential(spcp->genstruct);
00402   spcp->genstruct->potential_grid = original_applied_potential;
00403   spcp->alpha_iface_0field = spcp->alpha_iface;
00404   spcp->alpha_efield_0field = spcp->alpha_efield;
00405   spcp->alpha_method2_0field = spcp->alpha_method2;
00406   g_object_unref(spcp->base_job_directory);
00407   spcp->base_job_directory = g_file_get_child(original_base_job_dir, "with_field");
00408   calculate_alpha_for_structure(privdat, assignment, iteration);
00409 
00410   g_object_unref(spcp->base_job_directory);
00411   spcp->base_job_directory = original_base_job_dir;
00412   /*Now write out the values we got*/
00413   GString* gs = g_string_new("");
00414   g_string_append_printf(gs, "%lu\t%g\t%g\t%g", iteration, spcp->alpha_iface + spcp->alpha_efield, spcp->alpha_iface, spcp->alpha_efield);
00415   g_string_append_printf(gs, "%g\t%g\t%g", spcp->alpha_iface_0field + spcp->alpha_efield_0field, spcp->alpha_iface_0field, spcp->alpha_efield_0field);
00416   g_string_append_printf(gs, "%g\t%g\t%g", (spcp->alpha_iface - spcp->alpha_iface_0field) + (spcp->alpha_efield - spcp->alpha_efield_0field), spcp->alpha_iface - spcp->alpha_iface_0field, spcp->alpha_efield - spcp->alpha_efield_0field);
00417   gsize wlen;
00418   GError *gerr = NULL;
00419   if(!g_output_stream_write_all(spcp->alpha_by_iteration_gos, gs->str, gs->len, &wlen, NULL, &gerr)) {
00420     fprintf(stderr, "ERROR writing to alpha_by_iteration file (%s): %s\n", g_file_get_uri(spcp->alpha_by_iteration_file), gerr->message);
00421     exit(32);
00422   }
00423   /*Stopping memory leaks*/
00424   g_string_free(gs, TRUE);
00425   /*And return the *difference**/
00426   return (spcp->alpha_iface - spcp->alpha_iface_0field) + (spcp->alpha_efield - spcp->alpha_efield_0field);
00427 }
00428 
00429 double calculate_alpha_for_structure(void* privdat, unsigned assignment, long unsigned iteration) {
00430   struct set_point_callback_privdat* spcp = (struct set_point_callback_privdat*)privdat;
00431   GError *gerr = NULL;
00432   matgrid *mg = (matgrid*)(spcp->genstruct->material_grid);
00433   potgrid *pg = (potgrid*)(spcp->genstruct->potential_grid);
00434   int L = mg->L[0];
00435   GString *gs=g_string_new("");
00436   GString *iter_dirname = g_string_new("optimizer_iteration_");
00437   g_string_append_printf(iter_dirname, "%lu", iteration);
00438   #ifdef HAVE_MPI
00439   g_string_append_printf(iter_dirname, "_node_%d_assignment_%u", spcp->node, assignment);
00440   #endif
00441   GFile* job_directory = g_file_get_child(spcp->base_job_directory, iter_dirname->str);
00442   g_string_free(iter_dirname, TRUE);
00443   /*make the directory and cd into it*/
00444   g_file_make_directory_with_parents(job_directory, NULL, &gerr);
00445   if(gerr != NULL) {
00446     if(gerr->code != G_IO_ERROR_EXISTS) {
00447       char* fn = g_file_get_uri(job_directory);
00448       fprintf(stderr, "ERROR creating the target directory for templated job (%s): %s\n", fn, gerr->message);
00449       g_free(fn);
00450       exit(5);
00451     }else{
00452       /*If the directory already exists, that's OK.*/
00453       g_error_free(gerr);
00454       gerr = NULL;
00455     }
00456   }
00457   /*Set the dump to go into this directory.*/
00458   GFile* dump_file = g_file_get_child(job_directory, "structure.griddump");
00459   GFile* file = g_file_get_child(job_directory, "bands.pdata");
00460   write_raw_bands_file(file, spcp->genstruct);
00461   g_object_unref(file);
00462   file = NULL;
00463   gsize wlen;
00464 
00465   double dopant_ierr, potential_ierr, efield_ierr;
00466 
00467   if(spcp->scpot_calc == NULL) {
00468     /*The goal is to make this not get regenerated on each loop.  The main time-eater, though, is in the potential calculation, so it's not a huge issue*/
00469     spcp->scpot_calc = new self_consistent_potential< ::kdotp::libkdotp::hamiltonian::cartesian_effective_mass, 1>(spcp->genstruct, ::kdotp::libkdotp::hamiltonian::HARDWALL, get_average_with_cartesian_effective_mass_block, get_cartesian_effective_mass_block_max_delta, 1e6, 1e-14);
00470   }
00471 
00472   double* eigvals=NULL;
00473   double* eigvecs=NULL;
00474   int neigs=0;
00475   double Ef=0;
00476   gerr = (spcp->scpot_calc)->perform_calculation(3, 1001, 1e-8, 1, &eigvecs, &eigvals, ::kdotp::libkdotp::hamiltonian::OOMSTAR, ::kdotp::libkdotp::hamiltonian::EPSILON, &Ef, &dopant_ierr, &potential_ierr, &efield_ierr, job_directory, 0.75);
00477   printf("dopant integration error: %g\npotential integration error: %g\nefield integration error: %g\n", dopant_ierr, potential_ierr, efield_ierr);
00478 
00479   if(gerr != NULL) {
00480     fprintf(stderr, "ERROR getting eigenvectors of Hamiltonian: %s\n", gerr->message);
00481   }else{
00482     printf("Got %d eigenvalues: %g, %g, %g\n", neigs, eigvals[0], eigvals[1], eigvals[2]);
00483     char fn[1024];
00484     double sum, val;
00485     printf("Checking normalization and writing wavefunctions:\n");
00486     double x;
00487     for(int j=0; j<3; j++) {
00488       //sprintf(fn, "eigvec_%g.pdata", eigvals[j]);
00489       printf("\t%g: ", eigvals[j]);
00490       g_string_printf(gs, "eigvec_%d.pdata", j);
00491       file = g_file_get_child(job_directory, gs->str);
00492       GOutputStream* gos = (GOutputStream*)g_file_replace(file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &gerr);
00493       if(gerr != NULL) {
00494   fprintf(stderr, "ERROR opening eigenvec %d file (%s): %s\n", j, g_file_get_uri(file), gerr->message);
00495   exit(32);
00496       }
00497       g_string_printf(gs, "#pos(nm)\tpsi\n");
00498       if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &gerr)) {
00499   fprintf(stderr, "ERROR writing to eigvec %d file (%s): %s\n", j, g_file_get_uri(file), gerr->message);
00500   exit(32);
00501       }
00502       sum = 0;
00503       for(int i=0; i<L; i++) {
00504   val=eigvecs[i + j*L];
00505   unsigned X=i;
00506   (spcp->scpot_calc)->H->matgrid->point_index_to_realspace(&X, &x);
00507   g_string_printf(gs, "%g\t%g\n", x, val);
00508   if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &gerr)) {
00509     fprintf(stderr, "ERROR writing to eigvec %d file (%s): %s\n", j, g_file_get_uri(file), gerr->message);
00510     exit(32);
00511   }
00512   sum += val*val;
00513       }
00514       g_object_unref(file);
00515       if(fabs(1.0-sum) < 1e-8) {
00516   printf("Normalized (%g)\n", sum);
00517       }else{
00518   printf("NON-NORMALIZED (%g)\n", sum);
00519       }
00520       g_object_unref(gos);
00521     }
00522     printf("################################################################\n");
00523     printf("################################################################\n");
00524     printf("## Final output\n");
00525     printf("################################################################\n");
00526     printf("################################################################\n");
00527     printf("Ef=%g\n", Ef);
00528     struct ::potential pot;
00529     pot.N = (spcp->scpot_calc)->H->L;
00530     pot.spacing=(spcp->scpot_calc)->H->dx;
00531 
00532     fprintf(stderr, "pot.x=%p pot.potential=%p H->internal_potential=%p\n", (void*)pot.x, (void*)pot.potential, (void*)(spcp->scpot_calc)->H->internal_potential);
00533     pot.x = (double*)malloc(sizeof(double)*pot.N);
00534     pot.potential = (double*)malloc(sizeof(double)*pot.N);
00535     if((pot.x == NULL) || (pot.potential == NULL)) {
00536       fprintf(stderr, "ERROR: unable to allocate memory for pot x or bandedge data!\n");
00537       exit(5);
00538     }
00539     fprintf(stderr, "N=%d dx=%g\n", pot.N, pot.spacing);
00540     for(unsigned int i=0; i<(unsigned int)pot.N; i++) {
00541       (spcp->scpot_calc)->H->matgrid->point_index_to_realspace(&i, &(pot.x[i]));
00542       fprintf(stderr, "%u/%d: x=%g (&X=%p, &pot.x[%d]=%p(%p/%p))\n", X, i, pot.x[i], (void*)&i, i, (void*)&(pot.x[i]), (void*)pot.x, (void*)(spcp->scpot_calc)->H->internal_potential);
00543     }
00544     (spcp->scpot_calc)->H->get_parameter_function(TOTAL_POTENTIAL, pot.potential);
00545     struct mstar_wavefunction_1d *wf = mstar_wavefunction_1d_new((spcp->scpot_calc)->H->L);
00546     if(wf == NULL) {
00547       fprintf(stderr, "ERROR: unable to allocate memory for wavefunction data!\n");
00548       exit(5);
00549     }
00550     for(int i=0; i<wf->N; i++) {
00551       unsigned int X=i;
00552       (spcp->scpot_calc)->H->matgrid->point_index_to_realspace(&X, &(wf->points[i].x));
00553       (spcp->scpot_calc)->H->matgrid->point_index_to_realspace(&X, &(wf->points[i].x));
00554       wf->points[i].im=0;
00555       /*We want the first wavefunction*/
00556       wf->points[i].re=eigvecs[i];
00557     }
00558     /**Bands: 0->CB, 1->HH, 2->SO*/
00559     struct band bands[3];
00560     int errnum;
00561     for(int i=0; i<3; i++) {
00562       bands[i].N = (spcp->scpot_calc)->H->L;
00563       bands[i].spacing=(spcp->scpot_calc)->H->dx;
00564       bands[i].x = (double*)malloc(sizeof(double)*bands[i].N);
00565       bands[i].bandedge = (double*)malloc(sizeof(double)*bands[i].N);
00566       if((bands[i].x == NULL) || (bands[i].bandedge == NULL)) {
00567   fprintf(stderr, "ERROR: unable to allocate memory for pot x or bandedge data!\n");
00568   exit(5);
00569       }
00570       for(unsigned int j=0; j<(unsigned int)bands[i].N; j++) {
00571   (spcp->scpot_calc)->H->matgrid->point_index_to_realspace(&j, &(bands[i].x[j]));
00572       }
00573     }
00574     /*For alpha_calch.h compat, and implying nextnano compat, we add in the potential*/
00575     /*\note these band edge energies are relative to Ef, for compatibility with alpha_calc (and therefore with nextnano*/
00576     (spcp->scpot_calc)->H->get_parameter_function(EC, bands[0].bandedge);
00577     for(unsigned j=0; j<(spcp->scpot_calc)->H->L; j++) {
00578       /*Add the potential to the CB*/
00579       bands[0].bandedge[j] += -(pot.potential[j] + Ef);
00580       /*Set the HH/LH band edge*/
00581       bands[1].bandedge[j] = (spcp->scpot_calc)->H->matgrid->data[j]->get_property("E_v", &errnum) - pot.potential[j] - Ef;
00582       if(errnum != 0) fprintf(stderr, "ERROR getting property Ev at gridsite %u: %d\n", j, errnum);
00583       /*Subtract the Delta from the HH/LH band edge (note: HH/LH includes potential and Ef already)*/
00584       bands[2].bandedge[j] = bands[1].bandedge[j] - (spcp->scpot_calc)->H->matgrid->data[j]->get_property("Delta", &errnum);
00585       if(errnum != 0) fprintf(stderr, "ERROR getting property Delta at gridsite %u: %d\n", j, errnum);
00586       /**\note that the bandedge of the HH/LH band includes the potential (previous loop)*/
00587     }
00588     /*Use method 1*/
00589     /*First, find the ifaces.*/
00590     GList* ifaces=NULL;
00591     /*We start at 1, since we compare against the *previous* point*/
00592     /*While we're going through it, get Ep for the material.*/
00593     double* Ep_in_structure = new double[(spcp->scpot_calc)->H->L];
00594     for(unsigned i=1; i<(spcp->scpot_calc)->H->L; i++) {
00595       if((spcp->scpot_calc)->H->matgrid->data[i-1] != (spcp->scpot_calc)->H->matgrid->data[i]) {
00596   double *midpoint = new double;
00597   double x_prev, x_cur;
00598   unsigned prev=i-1;
00599   (spcp->scpot_calc)->H->matgrid->point_index_to_realspace(&prev, &x_prev);
00600   (spcp->scpot_calc)->H->matgrid->point_index_to_realspace(&i, &x_cur);
00601   /*cur and prev are fixed; the interface is halfway between.*/
00602   *midpoint = x_prev + (x_cur - x_prev)*0.5;
00603   ifaces = g_list_append(ifaces, midpoint);
00604   printf("Got interface: %g\n", *midpoint);
00605       }
00606       Ep_in_structure[i] = (spcp->scpot_calc)->H->matgrid->data[i]->get_property("E_p", &errnum);
00607       if(errnum != 0) fprintf(stderr, "ERROR getting property E_p at gridsite %u: %d\n", i, errnum);
00608     }
00609     delete[] Ep_in_structure;
00610     struct alpha_integrand_verificator vf1;
00611     struct alpha_integrand_verificator_2 vf2;
00612     double Ep = get_average_with_cartesian_effective_mass_block(eigvecs, 0, (spcp->scpot_calc)->H->L, Ep_in_structure);
00613     printf("Ep_avg=%g\n", Ep);
00614     double ierr_alpha, ierr_alpha_m2;
00615     double alpha_iface = alpha_interface_term_mstar_nostrain(wf, &bands[1], &bands[1], &bands[2], &bands[0], &pot, ifaces, Ep);
00616     g_list_foreach(ifaces, delete_double, NULL);
00617     g_list_free(ifaces);
00618     double alpha_efield = alpha_electric_term_mstar_nostrain(wf, &bands[1], &bands[1], &bands[2], &bands[0], &pot, &vf1, &ierr_alpha, 1e-7, 1e-7, FALSE, Ep);
00619     double alpha_method2 = alpha_from_del_psi2_nostrain(wf, &bands[1], &bands[1], &bands[2], &bands[0], &pot, &vf2, &ierr_alpha_m2, 1e-7, 1e-7, FALSE, Ep);
00620     /*Write out the band ifnormation as it'll be passed into alpah_calc.*/
00621     file = g_file_get_child(job_directory, "bands2.pdata");
00622     GOutputStream* gos = (GOutputStream*)g_file_replace(file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &gerr);
00623     if(gerr != NULL) {
00624       fprintf(stderr, "ERROR opening bands2 file (%s): %s\n", g_file_get_uri(file), gerr->message);
00625       exit(32);
00626     }
00627     g_string_printf(gs, "#x(nm)\tcb(eV)\tHH/LH(eV)\tSO(eV)\tpot(eV)\tpsi^2(nm^-1)\n");
00628     if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &gerr)) {
00629       fprintf(stderr, "ERROR writing to bands2 file (%s): %s\n", g_file_get_uri(file), gerr->message);
00630       exit(32);
00631     }
00632     for(int i=0; i<bands[0].N; i++) {
00633       g_string_printf(gs, "%g\t", bands[0].x[i]);
00634       for(int j=0; j<3; j++) {
00635   g_string_append_printf(gs, "%g\t", bands[j].bandedge[i]);
00636       }
00637       g_string_append_printf(gs, "%g\n", pot.potential[i]);
00638       g_string_append_printf(gs, "%g\n", wf->points[i].re*wf->points[i].re);
00639       g_string_append_printf(gs, "#x(nm)\tcb(eV)\tHH/LH(eV)\tSO(eV)\tpot(eV)\tpsi^2(nm^-1)\n");
00640       if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &gerr)) {
00641   fprintf(stderr, "ERROR writing to bands2 file (%s): %s\n", g_file_get_uri(file), gerr->message);
00642   exit(32);
00643       }
00644     }
00645     g_object_unref(file);
00646     g_object_unref(gos);
00647     spcp->Ep = Ep;
00648     spcp->alpha_iface = alpha_iface;
00649     spcp->alpha_efield = alpha_efield;
00650     spcp->alpha_method2 = alpha_method2;
00651 
00652     GFile* vf1_file = g_file_get_child(job_directory, "alpha_method_1_efield_instrumentation.pdata");
00653     GFile* vf2_file = g_file_get_child(job_directory, "alpha_method_2_instrumentation.pdata");
00654     alpha_write_verificator_data(vf1_file, &vf1);
00655     alpha_write_verificator2_data(vf2_file, &vf2);
00656     alpha_free_verificator_data(&vf1);
00657     alpha_free_verificator2_data(&vf2);
00658     g_object_unref(vf1_file);
00659     g_object_unref(vf2_file);
00660     for(int i=0; i<3; i++) {
00661       free(bands[i].x);
00662       free(bands[i].bandedge);
00663     }
00664     free(pot.potential);
00665     free(pot.x);
00666     mstar_wavefunction_1d_free(wf);
00667     free(eigvecs);
00668     free(eigvals);
00669   }
00670   /*This should go away after I've vetted the spcot class for this use.*/
00671   delete spcp->scpot_calc;
00672   spcp->scpot_calc = NULL;
00673   g_object_unref(dump_file);
00674   /*If do_nofield_comparison is true, we're being called from another callback, which is writing the values out to the file.*/
00675   if(!spcp->do_nofield_comparison) {
00676     gs = g_string_assign(gs, "");
00677     g_string_append_printf(gs, "%lu\t%g\t%g\t%g\n", iteration, spcp->alpha_iface + spcp->alpha_efield, spcp->alpha_iface, spcp->alpha_efield);
00678     if(!g_output_stream_write_all(spcp->alpha_by_iteration_gos, gs->str, gs->len, &wlen, NULL, &gerr)) {
00679       fprintf(stderr, "ERROR writing to alpha_by_iteration file (%s): %s\n", g_file_get_uri(spcp->alpha_by_iteration_file), gerr->message);
00680       exit(32);
00681     }
00682     /*Stopping memory leaks*/
00683     g_string_free(gs, TRUE);
00684   }
00685   return spcp->alpha_iface + spcp->alpha_efield;
00686 }
00687 
00688 void write_raw_bands_file(GFile* file, struct generic_structure* genstruct) {
00689   matgrid *mg = (matgrid*)(genstruct->material_grid);
00690   potgrid *pg = (potgrid*)(genstruct->potential_grid);
00691   GString *gs = g_string_new("");
00692   gsize wlen;
00693   int L = mg->L[0];
00694   GError *gerr = NULL;
00695   GOutputStream* gos = (GOutputStream*)g_file_replace(file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &gerr);
00696   if(gerr != NULL) {
00697     fprintf(stderr, "ERROR opening bands file (%s): %s\n", g_file_get_uri(file), gerr->message);
00698     exit(32);
00699   }
00700   g_string_printf(gs, "#pos(nm)\tCB\tHH/LH\tSO\tPotential\n");
00701   if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &gerr)) {
00702     fprintf(stderr, "ERROR writing to bands file (%s): %s\n", g_file_get_uri(file), gerr->message);
00703     exit(32);
00704   }
00705   double x;
00706   int e;
00707   for(int i=0; i<L; i++) {
00708     e=0;
00709     double Eg = mg->data[i]->get_property("E_g_Gamma", &e);
00710     if(e != 0) fprintf(stderr, "ERROR: got error %d for property E_g_Gamma\n", e);
00711     e=0;
00712     double Ev = mg->data[i]->get_property("E_v", &e);
00713     if(e != 0) fprintf(stderr, "ERROR: got error %d for property E_v\n", e);
00714     e=0;
00715     double Delta = mg->data[i]->get_property("Delta", &e);
00716     if(e != 0) fprintf(stderr, "ERROR: got error %d for property Delta\n", e);
00717     unsigned X=i;
00718     mg->point_index_to_realspace(&X, &x);
00719     g_string_printf(gs, "%g\t%g\t%g\t%g\t%g\n", x, Eg+Ev, Ev, Ev-Delta, pg->data[i]);
00720     if(!g_output_stream_write_all(gos, gs->str, gs->len, &wlen, NULL, &gerr)) {
00721       fprintf(stderr, "ERROR writing to bands file (%s): %s\n", g_file_get_uri(file), gerr->message);
00722       exit(32);
00723     }
00724   }
00725   g_object_unref(gos);
00726 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines