|
k-dot-p 0.1
|
00001 /* 00002 * matdb: generic materials database information. 00003 00004 00005 00006 Copyright (C) 2009 Joseph Pingenot 00007 00008 This program is free software: you can redistribute it and/or modify 00009 it under the terms of the GNU Affero General Public License as published by 00010 the Free Software Foundation, either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU Affero General Public License for more details. 00017 00018 You should have received a copy of the GNU Affero General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. 00020 00021 */ 00022 00023 #include <stdio.h> 00024 #include <stdlib.h> 00025 #include <math.h> 00026 #include <glib.h> 00027 #include <libmodelxx/matdb.h++> 00028 00029 00030 namespace kdotp { 00031 namespace libmodelxx { 00032 namespace structure { 00033 00034 static void print_property(gpointer key, gpointer value, gpointer user_data) { 00035 fprintf(stderr, "\t\t%s=%g:\n", (char*)key, *(double*)value); 00036 } 00037 static void print_inner_bowing(gpointer key, gpointer value, gpointer user_data) { 00038 struct matdb_bowing *bowing = (struct matdb_bowing*)value; 00039 fprintf(stderr, "\tbowing %s:%s[%s:%s]:\n", bowing->from->str, bowing->to->str, (char*)user_data, (char*)key); 00040 g_hash_table_foreach(bowing->properties, &print_property, NULL); 00041 } 00042 static void print_material(gpointer key, gpointer value, gpointer user_data) { 00043 struct matdb_material *mat = (struct matdb_material*)value; 00044 fprintf(stderr, "\tmaterial %s(%s):\n", mat->name->str, (char*)key); 00045 g_hash_table_foreach(mat->properties, &print_property, NULL); 00046 } 00047 static void print_bowing(gpointer key, gpointer value, gpointer user_data) { 00048 GHashTable *ht = (GHashTable*)value; 00049 g_hash_table_foreach(ht, &print_inner_bowing, key); 00050 } 00051 00052 void print_matdb(const struct matdb *mdb) { 00053 fprintf(stderr, "matdb:\n"); 00054 g_hash_table_foreach(mdb->materials, &print_material, NULL); 00055 g_hash_table_foreach(mdb->bowings, &print_bowing, NULL); 00056 } 00057 00058 void destroy_material_gpointer(gpointer data) { 00059 destroy_material((struct matdb_material *)data); 00060 } 00061 void destroy_bowing_gpointer(gpointer data) { 00062 destroy_bowing((struct matdb_bowing *)data); 00063 } 00064 void destroy_material(struct matdb_material *mat) { 00065 #ifdef DEBUG 00066 fprintf(stderr, "destroy_material\n"); 00067 #endif 00068 g_string_free(mat->name, TRUE); 00069 g_hash_table_unref(mat->properties); 00070 free(mat); 00071 } 00072 void destroy_bowing(struct matdb_bowing *bow) { 00073 #ifdef DEBUG 00074 fprintf(stderr, "destroy_bowing\n"); 00075 #endif 00076 g_string_free(bow->from, TRUE); 00077 g_string_free(bow->to, TRUE); 00078 g_hash_table_unref(bow->properties); 00079 free(bow); 00080 } 00081 00082 double* new_double(double d) {double* D = (double*)malloc(sizeof(double)); *D = d; return D;} 00083 00084 struct foreach_datum { 00085 GHashTable *new_table; 00086 GHashTable *mat2_ppts; 00087 GHashTable *bowings; 00088 char* mat1; 00089 char* mat2; 00090 double x; 00091 }; 00092 00093 /*Bowing definition from Vurgaftman*/ 00094 double interpolate_with_bowing(double mat1, double mat2, double bow, double x) { 00095 return x*mat1 + (1-x)*mat2 - x*(1-x)*bow; 00096 } 00097 00098 double interpolate_without_bowing(double mat1, double mat2, double x) { 00099 return x*mat1 + (1-x)*mat2; 00100 } 00101 00102 void clone_each_property(gpointer key, gpointer value, gpointer data) { 00103 char* ppt = (char*)key; 00104 double* val1 = (double*)value; 00105 struct foreach_datum* fd = (struct foreach_datum*)data; 00106 double* val2; 00107 double* bow; 00108 double result; 00109 if(fd->mat2_ppts != NULL) { 00110 if(fd->mat2_ppts == NULL) { 00111 fprintf(stderr, "matdb.c++::clone_each_property: fd->mat2_ppts is NULL\n"); 00112 } 00113 val2 = (double*)g_hash_table_lookup(fd->mat2_ppts, ppt); 00114 if(val2 == NULL) { 00115 fprintf(stderr, "matdb.c::clone_each_property: WARNING material %s in material %s is not set in %s; skipping for their alloy.\n", ppt, fd->mat1, fd->mat2); 00116 return; 00117 }else{ 00118 00119 if((fd->bowings == NULL) || ((bow = (double*)g_hash_table_lookup(fd->bowings, ppt)) == NULL)) { 00120 result = interpolate_without_bowing(*val1, *val2, fd->x); 00121 }else{ 00122 result = interpolate_with_bowing(*val1, *val2, *bow, fd->x); 00123 } 00124 } 00125 } else { 00126 val2=NULL; 00127 result = *val1; 00128 } 00129 g_hash_table_insert(fd->new_table, g_strdup(ppt), new_double(result)); 00130 } 00131 00132 GHashTable* get_material(const struct matdb* matdb, const char* mat1, const char* mat2, double x) { 00133 if((x < 0) || (x>1)) { 00134 fprintf(stderr, "matdb::get_material: material %s(%f)%s doesn't exist: x not in range [0, 1]\n", mat1, x, mat2); 00135 return NULL; 00136 } 00137 if(((!(fabs(x-1.0)) < 1e-8) && (mat2 == NULL))){ 00138 fprintf(stderr, "matdb::get_material: material %s(%f)%s doesn't exist: x!=1 and mat2 is NULL\n", mat1, x, mat2); 00139 return NULL; 00140 } 00141 struct foreach_datum fd; 00142 void* rv; 00143 if(matdb->materials == NULL) { 00144 fprintf(stderr, "matdb.c++::get_material: matdb->materials is NULL\n"); 00145 } 00146 rv = g_hash_table_lookup(matdb->materials, mat1); 00147 GHashTable *ppts1 = NULL; 00148 if(rv == NULL) { 00149 fprintf(stderr, "matdb::get_material: unable to find material %s in materials database!\n", mat1); 00150 return NULL; 00151 } else { 00152 ppts1 = ((struct matdb_material*)rv)->properties; 00153 } 00154 if(mat2 == NULL) { 00155 fd.mat2_ppts = NULL; 00156 } else { 00157 rv = g_hash_table_lookup(matdb->materials, mat2); 00158 if(rv == NULL) { 00159 fprintf(stderr, "matdb::get_material: unable to find material %s in materials database!\n", mat2); 00160 return NULL; 00161 } 00162 fd.mat2_ppts = ((struct matdb_material*)rv)->properties; 00163 } 00164 fd.new_table = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); 00165 /*We cast away the const-ness; we need to store these in a struct.*/ 00166 fd.mat1 = (char*)mat1; 00167 fd.mat2 = (char*)mat2; 00168 fd.x = x; 00169 rv = NULL; 00170 /*Look up and set bowings, if they exist.*/ 00171 if(mat2 != NULL) { 00172 if(matdb->bowings == NULL) { 00173 fprintf(stderr, "matdb.c++::get_material: matdb->bowings is NULL\n"); 00174 } 00175 GHashTable *ht = (GHashTable*)g_hash_table_lookup(matdb->bowings, mat1); 00176 if(ht != NULL) { 00177 rv = g_hash_table_lookup(ht, mat2); 00178 if(rv != NULL) { 00179 fd.bowings = ((struct matdb_bowing*)rv)->properties; 00180 }else{ 00181 fd.bowings = NULL; 00182 } 00183 }else{ 00184 fd.bowings = NULL; 00185 } 00186 }else{ 00187 fd.bowings = NULL; 00188 } 00189 g_hash_table_foreach(ppts1, clone_each_property, &fd); 00190 /*Everything else is someone else's pointers, so we don't have to free anything.*/ 00191 return fd.new_table; 00192 } 00193 00194 double get_property1(const struct matdb* matdb, const char* ppt, const char* mat, int* err) { 00195 void* rv; 00196 GHashTable *ppts1; 00197 if(matdb->materials == NULL) { 00198 fprintf(stderr, "matdb.c++::get_property1: matdb->materials is NULL\n"); 00199 } 00200 rv = g_hash_table_lookup(matdb->materials, mat); 00201 if(rv == NULL) { 00202 fprintf(stderr, "matdb::get_material: unable to find material %s in materials database!\n", mat); 00203 *err = 1; 00204 return nan("NaN"); 00205 } else { 00206 ppts1 = ((struct matdb_material*)rv)->properties; 00207 } 00208 if(ppts1 == NULL) { 00209 fprintf(stderr, "matdb.c++::get_property1: ppts1 is NULL\n"); 00210 } 00211 rv = g_hash_table_lookup(ppts1, ppt); 00212 if(rv == NULL) { 00213 fprintf(stderr, "matdb.c::get_property2: unable to find property %s in material %s\n", ppt, mat); 00214 *err = 4; 00215 return nan("NaN"); 00216 } 00217 *err = 0; 00218 return *(double*)rv; 00219 } 00220 double get_property2(const struct matdb* matdb, const char* ppt, const char* mat1, const char* mat2, double x, int* err){ 00221 if((x < 0) || (x>0) || ((x != 1.0) && (mat2 == NULL))){ 00222 fprintf(stderr, "matdb::get_material: material %s(%e)%s doesn't exist: x not in range [0, 1], or x==1 and mat2 is NULL\n", mat1, x, mat2); 00223 *err = 1; 00224 return nan("NaN"); 00225 } 00226 void* rv; 00227 if(matdb->materials == NULL) { 00228 fprintf(stderr, "matdb.c++::get_property2: matdb->materials is NULL\n"); 00229 } 00230 rv = g_hash_table_lookup(matdb->materials, mat1); 00231 GHashTable *ppts1 = NULL; 00232 if(rv == NULL) { 00233 fprintf(stderr, "matdb::get_property2: unable to find material %s in materials database!\n", mat1); 00234 *err = 2; 00235 return nan("NaN"); 00236 } else { 00237 ppts1 = ((struct matdb_material*)rv)->properties; 00238 } 00239 GHashTable *ppts2; 00240 if(mat2 == NULL) { 00241 ppts2 = NULL; 00242 } else { 00243 if(matdb->materials == NULL) { 00244 fprintf(stderr, "matdb.c++::get_property2: matdb->materials is NULL\n"); 00245 } 00246 rv = g_hash_table_lookup(matdb->materials, mat2); 00247 if(rv == NULL) { 00248 fprintf(stderr, "matdb::get_property2: unable to find material %s in materials database!\n", mat2); 00249 *err = 3; 00250 return nan("NaN"); 00251 } 00252 ppts2 = ((struct matdb_material*)rv)->properties; 00253 } 00254 rv = NULL; 00255 GHashTable *bowings; 00256 /*Look up and set bowings, if they exist.*/ 00257 if(mat2 != NULL) { 00258 if(matdb->bowings == NULL) { 00259 fprintf(stderr, "matdb.c++::get_property2: matdb->bowings is NULL\n"); 00260 } 00261 GHashTable *ht = (GHashTable*)g_hash_table_lookup(matdb->bowings, mat1); 00262 if(ht != NULL) { 00263 rv = g_hash_table_lookup(ht, mat2); 00264 if(rv != NULL) { 00265 bowings = ((struct matdb_bowing*)rv)->properties; 00266 }else{ 00267 bowings = NULL; 00268 } 00269 }else{ 00270 bowings = NULL; 00271 } 00272 }else{ 00273 bowings=NULL; 00274 } 00275 if(ppts1 == NULL) { 00276 fprintf(stderr, "matdb.c++::get_property2: ppts1 is NULL\n"); 00277 } 00278 rv = g_hash_table_lookup(ppts1, ppt); 00279 if(rv == NULL) { 00280 fprintf(stderr, "matdb.c::get_property2: unable to find property %s in material %s\n", ppt, mat1); 00281 *err = 4; 00282 return nan("NaN"); 00283 } 00284 double* val1 = (double*)rv; 00285 double* val2; 00286 double* bow; 00287 double result; 00288 if(ppts2 != NULL) { 00289 val2 = (double*)g_hash_table_lookup(ppts2, ppt); 00290 if(val2 == NULL) { 00291 fprintf(stderr, "matdb.c::clone_each_property: WARNING material %s in material %s is not set in %s; skipping for their alloy.\n", ppt, mat1, mat2); 00292 *err = 5; 00293 return nan("NaN"); 00294 }else{ 00295 if(bowings == NULL) { 00296 fprintf(stderr, "matdb.c++::get_property2: bowings is NULL\n"); 00297 } 00298 if((bow = (double*)g_hash_table_lookup(bowings, ppt)) == NULL) { 00299 result = interpolate_without_bowing(*val1, *val2, x); 00300 }else{ 00301 result = interpolate_with_bowing(*val1, *val2, *bow, x); 00302 } 00303 } 00304 } else { 00305 val2=NULL; 00306 result = *val1; 00307 } 00308 /*Everything is someone else's pointers, so we don't have to free anything.*/ 00309 *err = 0; 00310 return result; 00311 } 00312 double get_bowing(const struct matdb* matdb, const char* ppt, const char* mat1, const char* mat2, int* err) { 00313 void *rv; 00314 GHashTable *bowings; 00315 /*Look up and set bowings, if they exist.*/ 00316 if(matdb->bowings == NULL) { 00317 fprintf(stderr, "matdb.c++::get_bowing: bowings is NULL\n"); 00318 } 00319 GHashTable *ht = (GHashTable*)g_hash_table_lookup(matdb->bowings, mat1); 00320 if(ht != NULL) { 00321 rv = g_hash_table_lookup(ht, mat2); 00322 if(rv != NULL) { 00323 bowings = ((struct matdb_bowing*)rv)->properties; 00324 }else{ 00325 *err = 1; 00326 return nan("NaN"); 00327 } 00328 }else{ 00329 *err = 2; 00330 return nan("NaN"); 00331 } 00332 double* bow; 00333 if(bowings == NULL) { 00334 fprintf(stderr, "matdb.c++::get_bowing: bowings is NULL\n"); 00335 } 00336 if((bow = (double*)g_hash_table_lookup(bowings, ppt)) == NULL) { 00337 *err = 3; 00338 return nan("NaN"); 00339 } 00340 *err = 0; 00341 return *bow; 00342 } 00343 00344 void insert_external_material(struct matdb* matdb, const char* matname) { 00345 struct matdb_material* mat = (struct matdb_material*)malloc(sizeof(struct matdb_material)); 00346 /*Create an empty hash table for the fake material.*/ 00347 mat->name = g_string_new(matname); 00348 GString* s = g_string_new(matname); 00349 mat->properties = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); 00350 g_hash_table_insert(matdb->materials, s->str, mat); 00351 g_string_free(s, FALSE); 00352 } 00353 00354 00355 } 00356 } 00357 }