• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

tools/mesh/dxmath.c

00001 
00053 #include "apbscfg.h"
00054 #include "apbs/apbs.h"  
00055 
00056 #define IJK(i,j,k)  (((k)*(nx)*(ny))+((j)*(nx))+(i))
00057 #define ERRRC 13
00058 #define DXM_MAXOP 20
00059 #define DXM_ISGRID 0
00060 #define DXM_ISSCALAR 1
00061 
00062 VEMBED(rcsid="$Id: dxmath.c 1552 2010-02-10 17:46:27Z yhuang01 $")
00063 
00064 typedef enum Dxmath_Opcode {
00065     DXM_ADD,  
00066     DXM_SUB,  
00067     DXM_DIV,  
00068     DXM_MUL,  
00069     DXM_EQU   
00070 } Dxmath_Opcode;
00071 
00072 int main(int argc, char **argv) {
00073 
00074     /* *************** VARIABLES ******************* */
00075     char *input_path;
00076     char *MCwhiteChars = " \t\n";
00077     char *MCcommChars  = "#%";
00078     char tok[VMAX_BUFSIZE];
00079     char gridPath[DXM_MAXOP+1][VMAX_BUFSIZE];
00080     double scalar[DXM_MAXOP+1];
00081     int obType[DXM_MAXOP+1];
00082     int iop, numop;
00083     int i, nx, ny, nz;
00084     Dxmath_Opcode op[DXM_MAXOP];
00085     Vio *sock = VNULL;
00086     Vgrid *grid1 = VNULL;
00087     Vgrid *grid2 = VNULL;
00088 
00089     char *header = "\n\n\
00090     ----------------------------------------------------------------------\n\
00091     ----------------------------------------------------------------------\n\
00092     \n\n";
00093 
00094     char *usage = "\n\n\
00095     ----------------------------------------------------------------------\n\
00096     This driver program (like its UHBD counterpart) does simple arithmetic\n\
00097     with Cartesian grid data.  It is invoked as:\n\n\
00098       dx-math <path>\n\n\
00099     where <path> is the path is the path to a file with operations specified\n\
00100     in a stack-based (RPN) manner.  For example, a command file which adds\n\
00101     grid1 and grid2, multiplies the result by 5.3, adds grid4, subtracts\n\
00102     99.3 from the whole thing, and writes the result on grid5 would have the\n\
00103     form:\n\n\
00104       grid1\n\
00105       grid2 +\n\
00106       5.3 *\n\
00107       grid4 +\n\
00108       99.3 -\n\
00109       grid5 =\n\n\
00110     where the file names, scalar values, and operations must be separated by\n\
00111     tabs, line breaks, or white space.  Comments can be included between the\n\
00112     character # and a new line (in the usual shell script fashion).\n\
00113     ----------------------------------------------------------------------\n\n";
00114 
00115  
00116     /* *************** CHECK INVOCATION ******************* */
00117     Vio_start();
00118     Vnm_print(1, "%s", header);
00119     if (argc != 2) {
00120         Vnm_print(2,"\n*** Syntax error: got %d arguments, expected 2.\n\n",
00121           argc);
00122         Vnm_print(2,"%s\n", usage);
00123         return ERRRC;
00124     } 
00125     input_path = argv[1];
00126 
00127     /* *************** OPEN INPUT FILE ******************* */
00128     sock = Vio_ctor("FILE", "ASC", VNULL, input_path, "r");
00129     if (sock == VNULL) {
00130         Vnm_print(2, "main:  Null socket!\n");
00131         return ERRRC;
00132     }
00133     if (Vio_accept(sock, 0) < 0) {
00134         Vnm_print(2, "main:  Problem reading from socket!\n");
00135         return 0;
00136     }
00137     Vio_setWhiteChars(sock, MCwhiteChars);
00138     Vio_setCommChars(sock, MCcommChars);
00139 
00140     /* *************** PARSE INPUT FILE ******************* */
00141     /* After reading in the first arg, we should alternate between objects and
00142      * operations, starting with the objects.  For each opject, we assign a
00143      * type (0 = grid path, 1 = scalar) */
00144     if (Vio_scanf(sock, "%s", tok) != 1) {
00145         Vnm_print(2, "main:  Ran out of tokens when parsing initial input!\n");
00146         return ERRRC;
00147     }
00148     strncpy(gridPath[0], tok, VMAX_BUFSIZE);
00149     obType[0] = DXM_ISGRID;
00150     numop = 0;
00151     while (Vio_scanf(sock, "%s", tok) == 1) {
00152         if (sscanf(tok, "%lg", &scalar[numop+1]) == 1) {
00153             obType[numop+1] = DXM_ISSCALAR;
00154         } else {
00155             strncpy(gridPath[numop+1], tok, VMAX_BUFSIZE);
00156             obType[numop+1] = DXM_ISGRID;
00157         }
00158         if (Vio_scanf(sock, "%s", tok) != 1) {
00159             Vnm_print(2, "main:  Ran out of tokens when parsing input!\n");
00160             Vnm_print(2, "main:  Last token = %s.\n", tok);
00161             return ERRRC;
00162         }
00163         if (strcmp(tok, "*") == 0) op[numop] = DXM_MUL;
00164         else if (strcmp(tok, "+") == 0) op[numop] = DXM_ADD;
00165         else if (strcmp(tok, "-") == 0) op[numop] = DXM_SUB;
00166         else if (strcmp(tok, "/") == 0) op[numop] = DXM_DIV;
00167         else if (strcmp(tok, "=") == 0) {
00168             op[numop] = DXM_EQU;
00169             numop++;
00170             break;
00171         } else {
00172             Vnm_print(2, "main:  Undefined operation '%s'!\n", tok);
00173             return ERRRC;
00174         }
00175         numop++;
00176         if (numop == DXM_MAXOP) {
00177             Vnm_print(2, "main:  Exceed maximum number of operations (%d)!\n",
00178               DXM_MAXOP);
00179             return ERRRC;
00180         }
00181     } 
00182     Vio_acceptFree(sock);
00183 
00184     /* Spit out what we parsed: */
00185     Vnm_print(1, "main:  Performing following operations:\n");
00186     Vnm_print(1, "main:    %s \n", gridPath[0]);
00187     for (iop=0; iop<numop; iop++) {
00188         if (obType[iop+1] == DXM_ISGRID)
00189           Vnm_print(1, "main:    %s (grid) ", gridPath[iop+1]);
00190         else 
00191           Vnm_print(1, "main:    %g (scalar) ", scalar[iop+1]);
00192         switch (op[iop]) {
00193             case DXM_MUL:
00194                 Vnm_print(1, "*\n");
00195                 break; 
00196             case DXM_ADD:
00197                 Vnm_print(1, "+\n");
00198                 break; 
00199             case DXM_SUB:
00200                 Vnm_print(1, "-\n");
00201                 break; 
00202             case DXM_DIV:
00203                 Vnm_print(1, "/\n");
00204                 break; 
00205             case DXM_EQU:
00206                 Vnm_print(1, "=\n");
00207                 break; 
00208             default:
00209                 Vnm_print(2, "\nmain:  Unknown operation (%d)!", op[iop]);
00210                 return ERRRC;
00211         }
00212     }
00213 
00214     /* *************** PARSE INPUT FILE ******************* */
00215     Vnm_print(1, "main:  Reading grid from %s...\n", gridPath[0]);
00216     grid1 = Vgrid_ctor(0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, VNULL);
00217     if (!Vgrid_readDX(grid1, "FILE", "ASC", VNULL, gridPath[0])) {
00218         Vnm_print(2, "main:  Problem reading OpenDX-format grid from %s\n",
00219           gridPath[0]);
00220         return ERRRC;
00221     }
00222     nx = grid1->nx;
00223     ny = grid1->ny;
00224     nz = grid1->nz;
00225     for (iop=0; iop<numop-1; iop++) {
00226         if (obType[iop+1] == DXM_ISGRID) {
00227             Vnm_print(1, "main:  Reading grid from %s...\n", gridPath[iop+1]);
00228             grid2 = Vgrid_ctor(0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, VNULL);
00229             if (!Vgrid_readDX(grid2, "FILE", "ASC", VNULL, gridPath[iop+1])) {
00230                       Vnm_print(2, "main:  Problem reading OpenDX-format grid from \
00231 %s\n", gridPath[0]);
00232                 return ERRRC;
00233             }
00234             if ((grid2->nx != nx) || (grid2->ny != ny) || (grid2->nz != nz)) {
00235                 Vnm_print(2, "main:  Grid dimension mis-match!\n");
00236                 Vnm_print(2, "main:  Grid 1 is %d x %d x %d\n", nx, ny, nz);
00237                 Vnm_print(2, "main:  Grid 2 is %d x %d x %d\n", 
00238                   grid2->nx, grid2->ny, grid2->nz);
00239                 return ERRRC;
00240             }
00241             switch (op[iop]) {
00242                 case DXM_ADD:
00243                     Vnm_print(1, "main:  Adding...\n");
00244                     for (i=0; i<nx*ny*nz; i++) 
00245                       grid1->data[i] = grid1->data[i] + grid2->data[i];
00246                     break;
00247                 case DXM_MUL:
00248                     Vnm_print(1, "main:  Multiplying...\n");
00249                     for (i=0; i<nx*ny*nz; i++) 
00250                       grid1->data[i] = grid1->data[i] * grid2->data[i];
00251                     break;
00252                 case DXM_SUB:
00253                     Vnm_print(1, "main:  Subtracting...\n");
00254                     for (i=0; i<nx*ny*nz; i++) 
00255                       grid1->data[i] = grid1->data[i] - grid2->data[i];
00256                     break;
00257                 case DXM_DIV:
00258                     Vnm_print(1, "main:  Dividing...\n");
00259                     for (i=0; i<nx*ny*nz; i++) 
00260                       grid1->data[i] = grid1->data[i] / grid2->data[i];
00261                     break;
00262                 default:
00263                     Vnm_print(2, "main:  Unexpected operation (%d)!\n",
00264                       op[iop]);
00265                     break;
00266             }
00267             Vgrid_dtor(&grid2);
00268         } else { /* if (obType[iop+1] == DXM_ISGRID) */
00269             Vnm_print(1, "main:  Loading scalar %g...\n", scalar[iop+1]);
00270             switch (op[iop]) {
00271                 case DXM_ADD:
00272                     Vnm_print(1, "main:  Adding...\n");
00273                     for (i=0; i<nx*ny*nz; i++)
00274                       grid1->data[i] = grid1->data[i] + scalar[iop+1];
00275                     break;
00276                 case DXM_MUL:
00277                     Vnm_print(1, "main:  Multiplying...\n");
00278                     for (i=0; i<nx*ny*nz; i++)
00279                       grid1->data[i] = grid1->data[i] * scalar[iop+1];
00280                     break;
00281                 case DXM_SUB:
00282                     Vnm_print(1, "main:  Subtracting...\n");
00283                     for (i=0; i<nx*ny*nz; i++)
00284                       grid1->data[i] = grid1->data[i] - scalar[iop+1];
00285                     break;
00286                 case DXM_DIV:
00287                     Vnm_print(1, "main:  Dividing...\n");
00288                     for (i=0; i<nx*ny*nz; i++)
00289                       grid1->data[i] = grid1->data[i] / scalar[iop+1];
00290                     break;
00291                 default:
00292                     Vnm_print(2, "main:  Unexpected operation (%d)!\n",
00293                       op[iop]);
00294                     break;
00295             }
00296         } /* if (obType[iop+1] == DXM_ISGRID) */
00297     } /* for (iop=0; iop<numop-1; iop++) */
00298  
00299     /* The last operation is the = sign, implying that we write out the grid */
00300     Vnm_print(1, "main:  Writing results to %s...\n", gridPath[numop]);
00301     Vgrid_writeDX(grid1, "FILE", "ASC", VNULL, gridPath[numop], 
00302       "DXMATH RESULTS", VNULL);
00303 
00304     Vnm_print(1, "main:  All done -- exiting.\n");
00305     return 0;
00306 }

Generated on Wed Oct 20 2010 11:12:19 for APBS by  doxygen 1.7.2