|
k-dot-p 0.1
|
00001 /* 00002 * 00003 00004 Copyright (C) 2009 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 #include <stdio.h> 00021 #include <string.h> 00022 #include <math.h> 00023 #include <glib.h> 00024 #include <libmodelxx/continuous_structure.h++> 00025 #include <libmodelxx/matdb.h++> 00026 #include <libmodelxx/material.h++> 00027 #include <libmodelxx/generic_structure.h++> 00028 #include <libmodelxx/function_specification.h++> 00029 00030 namespace kdotp { 00031 namespace libmodelxx { 00032 namespace continuous_structure { 00033 #define CONTINUOUS_STRUCTURE_GERROR_DOMAIN 321 00034 00035 static GError* callback_convert_type(double* location, double* values, int t, void* privdat) { 00036 for(int i=0; i<t; i++) { 00037 location[i] = values[i]; 00038 } 00039 if(t == 0) { 00040 location[0] = values[0]; 00041 return g_error_new(CONTINUOUS_STRUCTURE_GERROR_DOMAIN, 1, "::kdotp::libmodelxx::continuous_structure.c++::callback_convert_type:: warning: function data type boolean is invalid!"); 00042 } 00043 if(t < 0) { 00044 return g_error_new(CONTINUOUS_STRUCTURE_GERROR_DOMAIN, 2, "::kdotp::libmodelxx::continuous_structure.c++::callback_convert_type:: warning: function data type is INVALID!"); 00045 } 00046 return NULL; 00047 } 00048 00049 struct callback_get_material_privdat { 00050 char* mat1; 00051 char* mat2; 00052 const struct structure::matdb* mdb; 00053 }; 00054 00055 static GError* callback_get_material(structure::material** location, double* values, int t, void* privdat) { 00056 struct callback_get_material_privdat* p = (struct callback_get_material_privdat*)privdat; 00057 if(t != 1) { 00058 return g_error_new(CONTINUOUS_STRUCTURE_GERROR_DOMAIN, 1, "::kdotp::libmodelxx::continuous_structure.c++::callback_get_material: ERROR: I have no idea how to convert a vector to a material composed of (%s) and (%s)!", p->mat1, p->mat2); 00059 } 00060 fprintf(stderr, "Got material from function: %s(%g)%s\n", p->mat1, values[0], p->mat2); 00061 if((values[0] < 0) || (values[0] > 1)) return g_error_new(CONTINUOUS_STRUCTURE_GERROR_DOMAIN, 2, "::kdotp::libmodelxx::continuous_structure.c++::callback_get_material: ERROR: invalid percentage from function (material would be (%s)(%g)(%s))!", p->mat1, values[0], p->mat2); 00062 location[0] = new structure::material(p->mdb, p->mat1, p->mat2, values[0]); 00063 if(location[0] == NULL) return g_error_new(CONTINUOUS_STRUCTURE_GERROR_DOMAIN, 3, "::kdotp::libmodelxx::continuous_structure.c++::callback_get_material: ERROR: Error getting material from function: (material would be (%s)(%g)(%s))!", p->mat1, values[0], p->mat2); 00064 return NULL; 00065 } 00066 00067 struct structure::generic_structure* postprocess_structure(struct continuous_structure *s, const struct structure::matdb* mdb, GHashTable* global_symbol_table, GError **gerr) { 00068 struct structure::generic_structure* ngs; 00069 if((ngs = structure::generic_structure_new(s->g)) == NULL) { 00070 *gerr = g_error_new(CONTINUOUS_STRUCTURE_DOMAIN, 1, "kdotp::libmodelxx::continouous_structure::postprocess_structure: failed to set up new generic structure (got NULL)"); 00071 return NULL; 00072 } 00073 int err=0; 00074 GList* l; 00075 GError *e = NULL; 00076 struct region* r; 00077 int i=0; 00078 for(l=s->regions; l!=NULL; l=l->next) { 00079 fprintf(stderr, "region %d:", i); 00080 r = (struct region*)(l->data); 00081 if(((r->st)=postprocess_shape_tree(r->st, s->g->dimensions)) == NULL) { 00082 *gerr = g_error_new(CONTINUOUS_STRUCTURE_DOMAIN, 100+err, "kdotp::libmodelxx::continuous_structure::postprocess_structure failed to set up a region shape tree (error in postprocess_shape_tree (error %d))", err); 00083 structure::generic_structure_free(ngs); 00084 return NULL; 00085 } 00086 /*Set up the specified material.*/ 00087 if(r->f == NULL) { 00088 (r->m) = new structure::material(mdb, r->mat1, r->mat2, r->x); 00089 if((r->m) == NULL) { 00090 *gerr = g_error_new(CONTINUOUS_STRUCTURE_DOMAIN, 2, "kdotp::libmodelxx::continuous_structure::postprocess_structure failed to set up constat material (%s(%f)%s)", r->mat1, r->x, r->mat2); 00091 structure::generic_structure_free(ngs); 00092 return NULL; 00093 } 00094 /*Set the material*/ 00095 e = set_value_in_grid(ngs->g->t, ngs->g->dimensions, ngs->material_grid, r->st, r->m, global_symbol_table); 00096 if(e != NULL) { 00097 g_propagate_prefixed_error(gerr, e, "kdotp::libmodelxx::continuous_structure.c++::postprocess_structure: got error setting material in grid (mat1=%s mat2=%s x=%f): ", r->mat1, r->mat2, r->x); 00098 } 00099 }else{ 00100 GString *s = g_string_new(""); 00101 function_print_tree(r->f, &s, 0); 00102 fprintf(stderr, "Got r->f tree:%s\n", s->str); 00103 g_string_free(s, TRUE); 00104 struct callback_get_material_privdat pd; 00105 pd.mat1 = r->mat1; 00106 pd.mat2 = r->mat2; 00107 pd.mdb = mdb; 00108 e = set_value_in_grid(ngs->g->t, ngs->g->dimensions, ngs->material_grid, r->st, r->f, global_symbol_table, callback_get_material, &pd); 00109 if(e != NULL) { 00110 g_propagate_prefixed_error(gerr, e, "kdotp::libmodelxx::continuous_structure.c++::postprocess_structure: got error setting material in grid with function: "); 00111 } 00112 } 00113 fprintf(stderr, " (set material in grid)"); 00114 i++; 00115 fprintf(stderr, "\n"); 00116 } 00117 struct doping *d; 00118 for(l=s->dopings; l!=NULL; l=l->next) { 00119 d=(struct doping*)(l->data); 00120 if(((d->st)=postprocess_shape_tree(d->st, s->g->dimensions)) == NULL) { 00121 *gerr = g_error_new(CONTINUOUS_STRUCTURE_DOMAIN, 100+err, "kdotp::libmodelxx::continuous_structure::postprocess_structure failed to set up a doping shape tree (error in postprocess_shape_tree (error %d))", err); 00122 structure::generic_structure_free(ngs); 00123 return NULL; 00124 } 00125 GString *s = g_string_new(""); 00126 function_print_tree(d->f, &s, 0); 00127 fprintf(stderr, "Got d->f tree:%s\n", s->str); 00128 g_string_free(s, TRUE); 00129 e = set_value_in_grid(ngs->g->t, ngs->g->dimensions, ngs->doping_grid, d->st, d->f, global_symbol_table, callback_convert_type, NULL); 00130 if(e != NULL) { 00131 g_propagate_prefixed_error(gerr, e, "kdotp::libmodelxx::continuous_structure.c++::postprocess_structure: got error setting doping in grid: "); 00132 } 00133 } 00134 struct potential *p; 00135 for(l=s->potential; l != NULL; l=l->next) { 00136 //TODO!! 00137 } 00138 return ngs; 00139 } 00140 00141 void print_structure(const struct continuous_structure *s) { 00142 fprintf(stderr, "================================================================\n"); 00143 fprintf(stderr, "Grid data:\n"); 00144 fprintf(stderr, "Regions:\n"); 00145 } 00146 00147 enum length length_from_str(const char* str) { 00148 if(!strcmp(str, "nm")) return NANOMETER; 00149 else if(!strcmp(str, "A")) return ANGSTROM; 00150 else if(!strcmp(str, "um")) return MICROMETER; 00151 else if(!strcmp(str, "mm")) return MILLIMETER; 00152 else if(!strcmp(str, "cm")) return CENTIMETER; 00153 else if(!strcmp(str, "m")) return METER; 00154 return UNKNOWN_LENGTH; 00155 } 00156 00157 const char* str_from_length(enum length l) { 00158 switch(l) { 00159 case NANOMETER: 00160 return "nm"; 00161 case ANGSTROM: 00162 return "A"; 00163 case MICROMETER: 00164 return "um"; 00165 case MILLIMETER: 00166 return "mm"; 00167 case CENTIMETER: 00168 return "cm"; 00169 case METER: 00170 return "m"; 00171 default: 00172 return "<unknown unit of length>"; 00173 } 00174 } 00175 00176 enum energy energy_from_str(const char* str) { 00177 if(!strcmp(str, "eV")) return EVOLT; 00178 else if(!strcmp(str, "J")) return JOULE; 00179 else if(!strcmp(str, "erg")) return ERG; 00180 else if(!strcmp(str, "Eh")) return HARTREE; 00181 return UNKNOWN_ENERGY; 00182 } 00183 00184 const char* str_from_energy(enum energy e) { 00185 switch(e) { 00186 case EVOLT: 00187 return "eV"; 00188 case JOULE: 00189 return "J"; 00190 case ERG: 00191 return "erg"; 00192 case HARTREE: 00193 return "Eh"; 00194 default: 00195 return "<unknown unit of energy>"; 00196 } 00197 } 00198 00199 double convert_length_to_nm(double len, enum length unit) { 00200 switch(unit) { 00201 case NANOMETER: 00202 return len; 00203 case ANGSTROM: 00204 return len/10.0; 00205 case MICROMETER: 00206 return len*1.0e3; 00207 case MILLIMETER: 00208 return len*1.0e6; 00209 case CENTIMETER: 00210 return len*1.0e7; 00211 case METER: 00212 return len*1.0e9; 00213 default: 00214 fprintf(stderr, "kdotp::libmodelxx::continuous_structure::convert_length_to_nm: ERROR while converting units: unknown unit of length (%s)\n", str_from_length(unit)); 00215 return nan("NaN"); 00216 } 00217 } 00218 00219 /*From NIST*/ 00220 double convert_energy_to_hartree(double en, enum energy unit) { 00221 switch(unit) { 00222 case HARTREE: 00223 return en; 00224 case EVOLT: 00225 return en*3.674932540e-2; 00226 case JOULE: 00227 return en*2.29371269e17; 00228 case ERG: 00229 /*From wikipedia: 1 erg = 1e-7 J */ 00230 return en*2.29371269e10; 00231 default: 00232 fprintf(stderr, "kdotp::libmodelxx::continuous_structure::convert_energy_to_hartree: ERROR while converting units: unknown unit of energy (%s)\n", str_from_energy(unit)); 00233 return nan("NaN"); 00234 } 00235 } 00236 00237 } 00238 } 00239 }