funkalicious 0.1

getChainPotential_args.c

Go to the documentation of this file.
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 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines