|
funkalicious 0.1
|
00001 /* 00002 ** getChainPotential_args.c 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 ** Made by (Johnny Q. Hacker) 00020 ** Login <solarion@nathan> 00021 ** 00022 ** Started on Sat Nov 14 19:00:09 2009 Johnny Q. Hacker 00023 ** Last update Sun May 12 01:17:25 2002 Speed Blue 00024 */ 00025 00026 #include <errno.h> 00027 #include <stdlib.h> 00028 #include <stdio.h> 00029 #include <string.h> 00030 #include <gio/gio.h> 00031 #include <glib-2.0/glib.h> 00032 #include "config.h" 00033 #include "getChainPotential_args.h" 00034 00035 #define GET_CHAIN_POTENTIAL_ARGS_DOMAIN 1024 00036 00037 #define DEFAULT_OUTPUT_FILENAME "potential.grid" 00038 00039 extern void program_print_version(FILE* f); 00040 extern void libdotcode_print_version(FILE* f); 00041 extern void libpostproc_print_version(FILE* f); 00042 00043 void print_version_info() { 00044 program_print_version(stdout); 00045 libdotcode_print_version(stdout); 00046 libpostproc_print_version(stdout); 00047 printf("autotools info:\n\tProject: %s\n\tVersion: %s\n", PACKAGE_NAME, VERSION); 00048 printf("Platform information:\n\tSize of int=%d double=%d\n\tEndianness: %s\n", SIZEOF_INT, SIZEOF_DOUBLE, 00049 #ifdef WORDS_BIGENDIAN 00050 "big" 00051 #else 00052 "little" 00053 #endif 00054 ); 00055 } 00056 00057 struct args args = { 00058 .wf_list = NULL, 00059 .center_wf_list = NULL, 00060 /*0->x 1->y 2->z*/ 00061 .N_neighbors = {0, 0, 0}, 00062 .xslices = NULL, 00063 .yslices = NULL, 00064 .zslices = NULL, 00065 .sweep_x = FALSE, 00066 .sweep_y = FALSE, 00067 .sweep_z = FALSE, 00068 .pixel_strategy = 0, 00069 .outfile = NULL, 00070 .invert_odd = 0, 00071 .expand_density_boxes = NULL, 00072 .save_ascii_values = FALSE, 00073 .sepchar = '\t', 00074 .povray= FALSE, 00075 .use_inhomogeneous_dielectric = FALSE, 00076 .extra_neighbor = {0, 0, 0}, 00077 .neighbor_offset = {0, 0, 0}, 00078 .save_inhomog_iterations = FALSE 00079 }; 00080 00081 void yyparse(); 00082 int yylex(); 00083 00084 extern const char* version_info; 00085 00086 double* new_double_from_string(const char* s, GError **err) { 00087 double* d = (double*)malloc(sizeof(double)); 00088 if(d == NULL) { 00089 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 1, "getChainPotential_args.c::new_double_from_string: Error occurred converting string (%s) to double: out of memory/malloc failed", s); 00090 return NULL; 00091 } 00092 char *end; 00093 errno = 0; 00094 *d = strtod(s, &end); 00095 if(((end == s) && (*d == 0)) || (errno != 0)) { 00096 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 2, "getChainPotential_args.c::new_double_from_string: Error occurred converting string (%s) to double: %s", s, strerror(errno)); 00097 free(d); 00098 return NULL; 00099 } 00100 return d; 00101 } 00102 00103 int* new_int_from_string(const char* s, GError **err) { 00104 int* d = (int*)malloc(sizeof(int)); 00105 if(d == NULL) { 00106 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 1, "getChainPotential_args.c::new_int_from_string: Error occurred converting string (%s) to int: out of memory/malloc failed", s); 00107 return NULL; 00108 } 00109 char *end; 00110 errno = 0; 00111 *d = strtod(s, &end); 00112 if(((end == s) && (*d == 0)) || (errno != 0)) { 00113 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 2, "getChainPotential_args.c::new_int_from_string: Error occurred converting string (%s) to int: %s", s, strerror(errno)); 00114 free(d); 00115 return NULL; 00116 } 00117 return d; 00118 } 00119 00120 struct args* process_args(int argc, char **argv, GError **err) { 00121 fprintf(stderr, "Will I segfault too? %d %s\n", argc, argv[0]); 00122 gchar **file_names = NULL; 00123 gboolean print_version = FALSE; 00124 gchar** xslices = NULL; 00125 gchar** yslices = NULL; 00126 gchar** zslices = NULL; 00127 gboolean sweeps_exp_percent = FALSE; 00128 gboolean sweeps_log_percent = FALSE; 00129 char* invert_odd_coords = NULL; 00130 char* outfile = NULL; 00131 gboolean save_ascii_comma = FALSE; 00132 /*Static so that it doesn't disappear when we leave scope! This is the 00133 *array that will be used in the arg struct if expand_box[0] is non-zero. 00134 *The two negative numbers are flags for future code to let us know that 00135 *the other two numbers haven't been modified. 00136 */ 00137 static int expand_box[3] = {-1, -1, -1}; 00138 gchar* offsets=NULL; 00139 gchar* s_expand_box = NULL; 00140 GOptionEntry options[] = { 00141 { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &file_names,}, 00142 { "version", 'v', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &print_version, "Print version information about this program", NULL }, 00143 { "ascii-dump", 'a', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &(args.save_ascii_values), "Dump the entire array to a tab-separated file", NULL }, 00144 { "povray", 'p', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &(args.povray), "Dump the entire array to a povray-rendered scene", NULL }, 00145 { "ascii-dump-comma", 'c', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &(save_ascii_comma), "When dumping the entire array to a file, use commas instead of tabs to separate values.", NULL }, 00146 { "expand-box", 'E', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_FILENAME, &(s_expand_box), "Before calculating the potential, extend the box out in all directionsby this many grid sites.", NULL }, 00147 { "invert-odd", 'i', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_FILENAME, &invert_odd_coords, "3 characters representing the coordinates to invert on every odd site (one of each coordinate, in any order, no separators; used to make a chain of up-down-up-down-up potentials).", NULL }, 00148 { "outfile", 'o', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_FILENAME, &outfile, "File into which to put the resulting potential.", NULL}, 00149 { "xneighbors", 'x', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &(args.N_neighbors[0]), "Number of nearest neighbors along x", NULL}, 00150 { "yneighbors", 'y', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &(args.N_neighbors[1]), "Number of nearest neighbors along y", NULL}, 00151 { "zneighbors", 'z', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &(args.N_neighbors[2]), "Number of nearest neighbors along z", NULL}, 00152 { "offset-distance", 'd', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING, &offsets, "Offset between neighbors in each direction, in gridsites. Is specified as x,y,z, e.g. 5,10,15 will have each each item in the chain setparted by x distance of 5, y of 10, and z of 15 gridsites.", NULL}, 00153 { "xslice", 'X', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING_ARRAY, &(xslices), "x coordinate (in grid sites) along which to output a 2D slice of the total density and the resulting potential", NULL}, 00154 { "yslice", 'Y', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING_ARRAY, &(yslices), "y coordinate (in grid sites) along which to output a 2D slice of the total density and the resulting potential", NULL}, 00155 { "zslice", 'Z', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING_ARRAY, &(zslices), "z coordinate (in grid sites) along which to output a 2D slice of the total density and the resulting potential", NULL}, 00156 { "sweepx", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &args.sweep_x, "Output a sequence of PBMs to the sweep_x subdirectory showing a sweep along the x axis across the entire structure", NULL }, 00157 { "sweepy", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &args.sweep_y, "Output a sequence of PBMs to the sweep_y subdirectory showing a sweep along the y axis across the entire structure", NULL }, 00158 { "sweepz", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &args.sweep_z, "Output a sequence of PBMs to the sweep_z subdirectory showing a sweep along the z axis across the entire structure", NULL }, 00159 { "sweep_exp", 'e', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &sweeps_exp_percent, "Set pixel values in the sweep images to the \"normalized exp\" of the percentage of the maximum value, instead of just the percentage =pixel_max_value*(1.0-exp(percent))/(1.0-e).", NULL}, 00160 { "sweep_log", 'l', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &sweeps_log_percent, "Set pixel values in the sweep images to the \"normalized log\" of the percentage of the maximum value, instead of just the percentage =pixel_max_value*log(percent+1)/log(2).", NULL}, 00161 { "inhomogeneous", 'H', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &args.use_inhomogeneous_dielectric, "Dielectric is inhomogeneous; use recursive multigrid calculation to find the potential (otherwise, will only divide rho by epsilon at each point)", NULL }, 00162 { "save_inhomog_iterations", 's', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &args.save_inhomog_iterations, "Save a sweep along z of the potential and del_phi term at each iteration of the inhomogeneous solver and a dump.", NULL}, 00163 {NULL} 00164 }; 00165 GOptionContext *ctx; 00166 ctx = g_option_context_new("- create a dotcode potential for the specified grid of nearest neighbors"); 00167 g_option_context_add_main_entries(ctx, options, "Options"); 00168 00169 g_option_context_parse(ctx, &argc, &argv, NULL); 00170 00171 if(save_ascii_comma) args.sepchar = ','; 00172 00173 /*Add an extra neighbor to each non-zero direction.*/ 00174 for(int i=0; i<3; i++) if(args.N_neighbors[i]) args.extra_neighbor[i]=1; 00175 00176 if(offsets != NULL) { 00177 gchar** specs=g_strsplit(offsets, ",", 3); 00178 for(int i=0; i<3; i++) { 00179 if(specs[i] == NULL) { 00180 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 75, "getChainPotential_args.c: too few numbers in the neighbor offset list (got %d; should be exactly 3)\n", i); 00181 return NULL; 00182 } 00183 GError *e = NULL; 00184 int* val = new_int_from_string(specs[i], &e); 00185 if((val == NULL) || (e != NULL)) { 00186 if(e != NULL) { 00187 g_propagate_prefixed_error(err, e, "getChainPotential_args.c: Unable to convert specified offset (%s) (whole list was (%s)) or unable to allcoate an int!\n", specs[i], offsets); 00188 }else{ 00189 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 76, "getChainPotential_args.c: Unable to convert specified offset (%s) (whole list was (%s)) or unable to allcoate an int!\n", specs[i], offsets); 00190 } 00191 return NULL; 00192 } 00193 args.neighbor_offset[i] = *val; 00194 free(val); 00195 } 00196 g_strfreev(specs); 00197 } 00198 00199 if(invert_odd_coords != NULL) { 00200 for(int i=0; i<3; i++) { 00201 if(invert_odd_coords[i] == '\0') break; 00202 switch(invert_odd_coords[i]){ 00203 case 'X': 00204 case 'x': 00205 args.invert_odd |= 1; 00206 break; 00207 case 'Y': 00208 case 'y': 00209 args.invert_odd |= 2; 00210 break; 00211 case 'Z': 00212 case 'z': 00213 args.invert_odd |= 4; 00214 break; 00215 default: 00216 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 15, "getChainPotential_args.c: character %c in invert-odd coordinate string (%s) is not x, y, or z!", invert_odd_coords[i], invert_odd_coords); 00217 return NULL; 00218 } 00219 } 00220 } 00221 00222 args.xslices = NULL; 00223 int *d; 00224 GError *e = NULL; 00225 if(xslices != NULL) { 00226 for(int i=0; xslices[i] != NULL; i++) { 00227 if((d=new_int_from_string(xslices[i], &e)) != NULL) { 00228 args.xslices = g_list_append(args.xslices, d); 00229 }else{ 00230 *err = e; 00231 return NULL; 00232 } 00233 } 00234 } 00235 args.yslices = NULL; 00236 e = NULL; 00237 if(yslices != NULL) { 00238 for(int i=0; yslices[i] != NULL; i++) { 00239 if((d=new_int_from_string(yslices[i], &e)) != NULL) { 00240 args.yslices = g_list_append(args.yslices, d); 00241 }else{ 00242 *err = e; 00243 return NULL; 00244 } 00245 } 00246 } 00247 args.zslices = NULL; 00248 e = NULL; 00249 if(zslices != NULL) { 00250 for(int i=0; zslices[i] != NULL; i++) { 00251 if((d=new_int_from_string(zslices[i], &e)) != NULL) { 00252 args.zslices = g_list_append(args.zslices, d); 00253 }else{ 00254 *err = e; 00255 return NULL; 00256 } 00257 } 00258 } 00259 if(sweeps_log_percent) { 00260 if(sweeps_exp_percent) { 00261 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 24, "getChainPotential_args.c: you may give EITHER the normalized log OR exp strategy, not both!\n"); 00262 return NULL; 00263 }else{ 00264 args.pixel_strategy=1; 00265 } 00266 }else if(sweeps_exp_percent) { 00267 args.pixel_strategy=2; 00268 } 00269 00270 if(s_expand_box != NULL) { 00271 fprintf(stderr, "Got s_expand_box=%s\n", s_expand_box); 00272 gchar** sb = g_strsplit(s_expand_box, ",", 0); 00273 int i; 00274 for(i=0; sb[i] != NULL; i++) { 00275 if(i>2) break; 00276 expand_box[i] = atoi(sb[i]); 00277 fprintf(stderr, "sb[%d]=%s->%d\n", i, sb[i], expand_box[i]); 00278 } 00279 g_strfreev(sb); 00280 if(i>3) { 00281 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 24, "getChainPotential_args.c: ERROR: got more than 3 values for the expansion box (%s)\n", s_expand_box); 00282 return NULL; 00283 } 00284 /*Once the input has been processed, we check the values*/ 00285 if((expand_box[0] == 0) && (expand_box[1] == 0) && (expand_box[2] == 0)) { 00286 /*Scenario three: all set to zero. Do nothing.*/ 00287 } else if((expand_box[0] == 0) && (expand_box[1] == -1) && (expand_box[2] == -1)) { 00288 /*Scenario four: all set to zero by setting only the first. Do nothing.*/ 00289 } else if((expand_box[0] >= 0) && (expand_box[1] == -1) && (expand_box[2] == -1)) { 00290 /*scenario one: just one coordinate set; expand in all directions.*/ 00291 expand_box[1] = expand_box[0]; 00292 expand_box[2] = expand_box[0]; 00293 args.expand_density_boxes = expand_box; 00294 } else if((expand_box[0] >= 0) && (expand_box[1] >= 0) && (expand_box[2] >= 0)) { 00295 /*scenario two: User set all 3 values, so we need to save it to the struct*/ 00296 args.expand_density_boxes = expand_box; 00297 } else { 00298 /*One or more invalid numbers.*/ 00299 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 14, "getChainPotential_args.c: ERROR: a specified calculation box expansion size was negative! (%d,%d,%d)", expand_box[0], expand_box[1], expand_box[2]); 00300 return NULL; 00301 } 00302 fprintf(stderr, "expand_box=%d,%d,%d expand_density_boxes=%p\n", expand_box[0], expand_box[1], expand_box[2], (void*)args.expand_density_boxes); 00303 } 00304 00305 //gchar* htext = g_option_context_get_help(ctx, FALSE, NULL); 00306 g_option_context_free(ctx); 00307 00308 args.wf_list = NULL; 00309 struct wavefunction *wf =NULL; 00310 gboolean center; 00311 if(file_names != NULL) { 00312 for(int i = 0; file_names[i] != NULL; i++) { 00313 if((wf = (struct wavefunction*)malloc(sizeof(struct wavefunction))) == NULL) { 00314 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 3, "getChainPotential_args.c::new_double_from_string: Failed to allocate a struct wavefunction! Get more memory perhaps? (malloc returned NULL)"); 00315 return NULL; 00316 } 00317 if(file_names[i][0] == '-') { 00318 wf->charge = -1.0; 00319 }else if(file_names[i][0] == '+') { 00320 wf->charge = 1.0; 00321 }else{ 00322 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 3, "getChainPotential_args.c::new_double_from_string: first character of the wavefunction argument was not a plus (+) or minus (-); we got \"%c\"; specification of \"%s\"! What is the sign of the charge here?", file_names[i][0], file_names[i]); 00323 free(wf); 00324 return NULL; 00325 } 00326 if(file_names[i][1] == '/') { 00327 center = FALSE; 00328 }else if(file_names[i][1] == '@') { 00329 center = TRUE; 00330 }else{ 00331 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 3, "getChainPotential_args.c::new_double_from_string: second character of the wavefunction argument was not a slash (/); we got \"%c\"; specification of \"%s\"! What is the sign of the charge here?", file_names[i][1], file_names[i]); 00332 free(wf); 00333 return NULL; 00334 } 00335 wf->storage =NULL; 00336 wf->file = g_file_new_for_commandline_arg(&file_names[i][2]); 00337 if(center) { 00338 fprintf(stderr, "center: %s\n", file_names[i]); 00339 args.center_wf_list = g_list_append(args.center_wf_list, wf); 00340 }else{ 00341 fprintf(stderr, "not center: %s\n", file_names[i]); 00342 args.wf_list = g_list_append(args.wf_list, wf); 00343 } 00344 } 00345 } 00346 00347 if(print_version){ 00348 print_version_info(); 00349 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 7, "\n"); 00350 return NULL; 00351 } 00352 00353 if((args.wf_list == NULL) && (args.center_wf_list == NULL)) { 00354 *err = g_error_new(GET_CHAIN_POTENTIAL_ARGS_DOMAIN, 3, "getChainPotential_args.c::you MUST give at least one wave function to process!\n"); 00355 return NULL; 00356 } 00357 00358 if(outfile == NULL) { 00359 args.outfile = g_file_new_for_path(DEFAULT_OUTPUT_FILENAME); 00360 }else{ 00361 args.outfile = g_file_new_for_commandline_arg(outfile); 00362 } 00363 00364 return &args; 00365 }