|
k-dot-p 0.1
|
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 }