funkalicious 0.1

matdb.c

Go to the documentation of this file.
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-2.0/glib.h>
00027 #include <libdotcode/matdb.h>
00028 
00029 
00030 static void print_property(gpointer key, gpointer value, gpointer user_data) {
00031   fprintf(stderr, "\t\t%s=%g:\n", (char*)key, *(double*)value);
00032 }
00033 static void print_inner_bowing(gpointer key, gpointer value, gpointer user_data) {
00034   struct matdb_bowing *bowing = (struct matdb_bowing*)value;
00035   fprintf(stderr, "\tbowing %s:%s[%s:%s]:\n", bowing->from->str, bowing->to->str, (char*)user_data, (char*)key);
00036   g_hash_table_foreach(bowing->properties, &print_property, NULL);
00037 }
00038 static void print_material(gpointer key, gpointer value, gpointer user_data) {
00039   struct matdb_material *mat = (struct matdb_material*)value;
00040   fprintf(stderr, "\tmaterial %s(%s):\n", mat->name->str, (char*)key);
00041   g_hash_table_foreach(mat->properties, &print_property, NULL);
00042 }
00043 static void print_bowing(gpointer key, gpointer value, gpointer user_data) {
00044   GHashTable *ht = (GHashTable*)value;
00045   g_hash_table_foreach(ht, &print_inner_bowing, key);
00046 }
00047 
00048 void print_matdb(const struct matdb *mdb) {
00049   fprintf(stderr, "matdb:\n");
00050   g_hash_table_foreach(mdb->materials, &print_material, NULL);
00051   g_hash_table_foreach(mdb->bowings, &print_bowing, NULL);
00052 }
00053 
00054 void destroy_material_gpointer(gpointer data) {
00055   destroy_material((struct matdb_material *)data);
00056 }
00057 void destroy_bowing_gpointer(gpointer data) {
00058   destroy_bowing((struct matdb_bowing *)data);
00059 }
00060 void destroy_material(struct matdb_material *mat) {
00061 #ifdef DEBUG
00062   fprintf(stderr, "destroy_material\n");
00063 #endif
00064   g_string_free(mat->name, TRUE);
00065   g_hash_table_unref(mat->properties);
00066   free(mat);
00067 }
00068 void destroy_bowing(struct matdb_bowing *bow) {
00069 #ifdef DEBUG
00070   fprintf(stderr, "destroy_bowing\n");
00071 #endif
00072   g_string_free(bow->from, TRUE);
00073   g_string_free(bow->to, TRUE);
00074   g_hash_table_unref(bow->properties);
00075   free(bow);
00076 }
00077 
00078 double* new_double(double d) {double* D = (double*)malloc(sizeof(double)); *D = d; return D;}
00079 
00080 struct foreach_datum {
00081   GHashTable *new_table;
00082   GHashTable *mat2_ppts;
00083   GHashTable *bowings;
00084   char* mat1;
00085   char* mat2;
00086   double x;
00087 };
00088 
00089 /*Bowing definition from Vurgaftman*/
00090 double interpolate_with_bowing(double mat1, double mat2, double bow, double x) {
00091   return x*mat1 + (1-x)*mat2 - x*(1-x)*bow;
00092 }
00093 
00094 double interpolate_without_bowing(double mat1, double mat2, double x) {
00095   return x*mat1 + (1-x)*mat2;
00096 }
00097 
00098 void clone_each_property(gpointer key, gpointer value, gpointer data) {
00099   char* ppt = (char*)key;
00100   double* val1 = (double*)value;
00101   struct foreach_datum* fd = (struct foreach_datum*)data;
00102   double* val2;
00103   double* bow;
00104   double result;
00105   if(fd->mat2_ppts != NULL) {
00106     val2 = (double*)g_hash_table_lookup(fd->mat2_ppts, ppt);
00107     if(val2 == NULL) {
00108       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);
00109       return;
00110     }else{
00111       if((bow = (double*)g_hash_table_lookup(fd->bowings, ppt)) == NULL) {
00112   result = interpolate_without_bowing(*val1, *val2, fd->x);
00113       }else{
00114   result = interpolate_with_bowing(*val1, *val2, *bow, fd->x);
00115       }
00116     }
00117   } else {
00118     val2=NULL;
00119     result = *val1;
00120   }
00121   g_hash_table_insert(fd->new_table, g_strdup(ppt), new_double(result));
00122 }
00123 
00124 GHashTable* get_material(const struct matdb* matdb, const char* mat1, const char* mat2, double x) {
00125   if((x < 0) || (x>1)) {
00126     fprintf(stderr, "matdb::get_material: material %s(%f)%s doesn't exist: x not in range [0, 1]\n", mat1, x, mat2);
00127     return NULL;
00128   }
00129   if(((!(fabs(x-1.0)) < 1e-8) && (mat2 == NULL))){
00130     fprintf(stderr, "matdb::get_material: material %s(%f)%s doesn't exist: x!=1 and mat2 is NULL\n", mat1, x, mat2);
00131     return NULL;
00132   }
00133   struct foreach_datum fd;
00134   void* rv;
00135   rv = g_hash_table_lookup(matdb->materials, mat1);
00136   GHashTable *ppts1 = NULL;
00137   if(rv == NULL) {
00138     fprintf(stderr, "matdb::get_material: unable to find material %s in materials database!\n", mat1);
00139     return NULL;
00140   } else {
00141     ppts1 = ((struct matdb_material*)rv)->properties;
00142   }
00143   if(mat2 == NULL) {
00144     fd.mat2_ppts = NULL;
00145   } else {
00146     rv = g_hash_table_lookup(matdb->materials, mat2);
00147     if(rv == NULL) {
00148       fprintf(stderr, "matdb::get_material: unable to find material %s in materials database!\n", mat2);
00149       return NULL;
00150     }
00151     fd.mat2_ppts = ((struct matdb_material*)rv)->properties;
00152   }
00153   fd.new_table = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
00154   /*We cast away the const-ness; we need to store these in a struct.*/
00155   fd.mat1 = (char*)mat1;
00156   fd.mat2 = (char*)mat2;
00157   fd.x = x;
00158   rv = NULL;
00159   /*Look up and set bowings, if they exist.*/
00160   if(mat2 != NULL) {
00161     GHashTable *ht = (GHashTable*)g_hash_table_lookup(matdb->bowings, mat1);
00162     if(ht != NULL) {
00163       rv = g_hash_table_lookup(ht, mat2);
00164       if(rv != NULL) {
00165   fd.bowings = ((struct matdb_bowing*)rv)->properties;
00166       }else{
00167   fd.bowings = NULL;
00168       }
00169     }else{
00170       fd.bowings = NULL;
00171     }
00172   }else{
00173     fd.bowings = NULL;
00174   }
00175   g_hash_table_foreach(ppts1, clone_each_property, &fd);
00176   /*Everything else is someone else's pointers, so we don't have to free anything.*/
00177   return fd.new_table;
00178 }
00179 
00180 double get_property1(const struct matdb* matdb, const char* ppt, const char* mat, int* err) {
00181   void* rv;
00182   GHashTable *ppts1;
00183   rv = g_hash_table_lookup(matdb->materials, mat);
00184   if(rv == NULL) {
00185     fprintf(stderr, "matdb::get_material: unable to find material %s in materials database!\n", mat);
00186     *err = 1;
00187     return nan("NaN");
00188   } else {
00189     ppts1 = ((struct matdb_material*)rv)->properties;
00190   }
00191   rv = g_hash_table_lookup(ppts1, ppt);
00192   if(rv == NULL) {
00193     fprintf(stderr, "matdb.c::get_property2: unable to find property %s in material %s\n", ppt, mat);
00194     *err = 4;
00195     return nan("NaN");
00196   }
00197   *err = 0;
00198   return *(double*)rv;
00199 }
00200 double get_property2(const struct matdb* matdb, const char* ppt, const char* mat1, const char* mat2, double x, int* err){
00201   if((x < 0) || (x>0) || ((x != 1.0) && (mat2 == NULL))){
00202     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);
00203     *err = 1;
00204     return nan("NaN");
00205   }
00206   void* rv;
00207   rv = g_hash_table_lookup(matdb->materials, mat1);
00208   GHashTable *ppts1 = NULL;
00209   if(rv == NULL) {
00210     fprintf(stderr, "matdb::get_material: unable to find material %s in materials database!\n", mat1);
00211     *err = 2;
00212     return nan("NaN");
00213   } else {
00214     ppts1 = ((struct matdb_material*)rv)->properties;
00215   }
00216   GHashTable *ppts2;
00217   if(mat2 == NULL) {
00218     ppts2 = NULL;
00219   } else {
00220     rv = g_hash_table_lookup(matdb->materials, mat2);
00221     if(rv == NULL) {
00222       fprintf(stderr, "matdb::get_material: unable to find material %s in materials database!\n", mat2);
00223       *err = 3;
00224       return nan("NaN");
00225     }
00226     ppts2 = ((struct matdb_material*)rv)->properties;
00227   }
00228   rv = NULL;
00229   GHashTable *bowings;
00230   /*Look up and set bowings, if they exist.*/
00231   if(mat2 != NULL) {
00232     GHashTable *ht = (GHashTable*)g_hash_table_lookup(matdb->bowings, mat1);
00233     if(ht != NULL) {
00234       rv = g_hash_table_lookup(ht, mat2);
00235       if(rv != NULL) {
00236   bowings = ((struct matdb_bowing*)rv)->properties;
00237       }else{
00238   bowings = NULL;
00239       }
00240     }else{
00241       bowings = NULL;
00242     }
00243   }else{
00244     bowings=NULL;
00245   }
00246   rv = g_hash_table_lookup(ppts1, ppt);
00247   if(rv == NULL) {
00248     fprintf(stderr, "matdb.c::get_property2: unable to find property %s in material %s\n", ppt, mat1);
00249     *err = 4;
00250     return nan("NaN");
00251   }
00252   double* val1 = (double*)rv;
00253   double* val2;
00254   double* bow;
00255   double result;
00256   if(ppts2 != NULL) {
00257     val2 = (double*)g_hash_table_lookup(ppts2, ppt);
00258     if(val2 == NULL) {
00259       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);
00260       *err = 5;
00261       return nan("NaN");
00262     }else{
00263       if((bow = (double*)g_hash_table_lookup(bowings, ppt)) == NULL) {
00264   result = interpolate_without_bowing(*val1, *val2, x);
00265       }else{
00266   result = interpolate_with_bowing(*val1, *val2, *bow, x);
00267       }
00268     }
00269   } else {
00270     val2=NULL;
00271     result = *val1;
00272   }
00273   /*Everything is someone else's pointers, so we don't have to free anything.*/
00274   *err = 0;
00275   return result;
00276 }
00277 double get_bowing(const struct matdb* matdb, const char* ppt, const char* mat1, const char* mat2, int* err) {
00278   void *rv;
00279   GHashTable *bowings;
00280   /*Look up and set bowings, if they exist.*/
00281   GHashTable *ht = (GHashTable*)g_hash_table_lookup(matdb->bowings, mat1);
00282   if(ht != NULL) {
00283     rv = g_hash_table_lookup(ht, mat2);
00284     if(rv != NULL) {
00285       bowings = ((struct matdb_bowing*)rv)->properties;
00286     }else{
00287       *err = 1;
00288       return nan("NaN");
00289     }
00290   }else{
00291     *err = 2;
00292     return nan("NaN");
00293   }
00294   double* bow;
00295   if((bow = (double*)g_hash_table_lookup(bowings, ppt)) == NULL) {
00296     *err = 3;
00297     return nan("NaN");
00298   }
00299   *err = 0;
00300   return *bow;
00301 }
00302 
00303 
00304 /*TODO: parse the string out*/
00305 double get_property(const struct matdb* matdb, const char* ppt, const char* matstring, int* err) {
00306   return get_property1(matdb, ppt, matstring, err);
00307 }
00308 
00309 
00310 void insert_external_material(struct matdb* matdb, const char* matname) {
00311   struct matdb_material* mat = (struct matdb_material*)malloc(sizeof(struct matdb_material));
00312   /*Create an empty hash table for the fake material.*/
00313   mat->name = g_string_new(matname);
00314   GString* s = g_string_new(matname);
00315   mat->properties = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
00316   g_hash_table_insert(matdb->materials, s->str, mat);
00317   g_string_free(s, FALSE);
00318 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines