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

src/generic/nosh.c

Go to the documentation of this file.
00001 
00050 #include "apbscfg.h"
00051 #include "apbs/nosh.h"
00052 #include "apbs/vstring.h"
00053 #include "apbs/mgparm.h"
00054 #include "apbs/femparm.h"
00055 
00056 VEMBED(rcsid="$Id: nosh.c 1585 2010-05-13 16:21:17Z sdg0919 $")
00057 
00058 
00059 VPRIVATE int NOsh_parseREAD(
00060        NOsh *thee, 
00061        Vio *sock);
00062 
00063 VPRIVATE int NOsh_parsePRINT(
00064         NOsh *thee, 
00065         Vio *sock);
00066 
00067 VPRIVATE int NOsh_parseELEC(
00068        NOsh *thee, 
00069        Vio *sock
00070        );
00071 
00072 VPRIVATE int NOsh_parseAPOLAR(
00073        NOsh *thee, 
00074        Vio *sock
00075        );
00076 
00077 VEXTERNC int NOsh_parseFEM(
00078          NOsh *thee, 
00079          Vio *sock, 
00080          NOsh_calc *elec
00081          );
00082 
00083 VEXTERNC int NOsh_parseMG(
00084         NOsh *thee, 
00085         Vio *sock, 
00086         NOsh_calc *elec
00087         );
00088 
00089 VEXTERNC int NOsh_parseAPOL(
00090          NOsh *thee, 
00091          Vio *sock, 
00092          NOsh_calc *elec
00093          );
00094 
00095 VPRIVATE int NOsh_setupCalcMG(
00096          NOsh *thee,
00097          NOsh_calc *elec
00098          ); 
00099 
00100 VPRIVATE int NOsh_setupCalcMGAUTO(
00101           NOsh *thee,
00102           NOsh_calc *elec
00103           ); 
00104 
00105 VPRIVATE int NOsh_setupCalcMGMANUAL(
00106          NOsh *thee,
00107          NOsh_calc *elec
00108          ); 
00109 
00110 VPRIVATE int NOsh_setupCalcMGPARA(
00111           NOsh *thee,
00112           NOsh_calc *elec
00113           ); 
00114 
00115 VPRIVATE int NOsh_setupCalcFEM(
00116           NOsh *thee,
00117           NOsh_calc *elec
00118           );
00119 
00120 VPRIVATE int NOsh_setupCalcFEMANUAL(
00121           NOsh *thee,
00122           NOsh_calc *elec
00123           );
00124 
00125 VPRIVATE int NOsh_setupCalcAPOL(
00126         NOsh *thee, 
00127         NOsh_calc *elec
00128         );
00129 
00130 #if !defined(VINLINE_NOSH)
00131 
00132 VPUBLIC char* NOsh_getMolpath(NOsh *thee, int imol) {
00133  VASSERT(thee != VNULL);
00134  VASSERT(imol < thee->nmol);
00135  return thee->molpath[imol];
00136 }
00137 VPUBLIC char* NOsh_getDielXpath(NOsh *thee, int imol) {
00138  VASSERT(thee != VNULL);
00139  VASSERT(imol < thee->nmol);
00140  return thee->dielXpath[imol];
00141 }
00142 VPUBLIC char* NOsh_getDielYpath(NOsh *thee, int imol) {
00143  VASSERT(thee != VNULL);
00144  VASSERT(imol < thee->nmol);
00145  return thee->dielYpath[imol];
00146 }
00147 VPUBLIC char* NOsh_getDielZpath(NOsh *thee, int imol) {
00148  VASSERT(thee != VNULL);
00149  VASSERT(imol < thee->nmol);
00150  return thee->dielZpath[imol];
00151 }
00152 VPUBLIC char* NOsh_getKappapath(NOsh *thee, int imol) {
00153  VASSERT(thee != VNULL);
00154  VASSERT(imol < thee->nmol);
00155  return thee->kappapath[imol];
00156 }
00157 VPUBLIC char* NOsh_getPotpath(NOsh *thee, int imol) {
00158  VASSERT(thee != VNULL);
00159  VASSERT(imol < thee->nmol);
00160  return thee->potpath[imol];
00161 }
00162 VPUBLIC char* NOsh_getChargepath(NOsh *thee, int imol) {
00163  VASSERT(thee != VNULL);
00164  VASSERT(imol < thee->nmol);
00165  return thee->chargepath[imol];
00166 }
00167 VPUBLIC NOsh_calc* NOsh_getCalc(NOsh *thee, int icalc) {
00168  VASSERT(thee != VNULL);
00169  VASSERT(icalc < thee->ncalc);
00170  return thee->calc[icalc];
00171 }
00172 VPUBLIC int NOsh_getDielfmt(NOsh *thee, int i) {
00173  VASSERT(thee != VNULL);
00174  VASSERT(i < thee->ndiel);
00175  return (thee->dielfmt[i]);
00176 }
00177 VPUBLIC int NOsh_getKappafmt(NOsh *thee, int i) {
00178  VASSERT(thee != VNULL);
00179  VASSERT(i < thee->nkappa);
00180  return (thee->kappafmt[i]);
00181 }
00182 VPUBLIC int NOsh_getPotfmt(NOsh *thee, int i) {
00183  VASSERT(thee != VNULL);
00184  VASSERT(i < thee->npot);
00185  return (thee->potfmt[i]);
00186 }
00187 VPUBLIC int NOsh_getChargefmt(NOsh *thee, int i) {
00188  VASSERT(thee != VNULL);
00189  VASSERT(i < thee->ncharge);
00190  return (thee->chargefmt[i]);    
00191 }
00192 
00193 
00194 #endif /* if !defined(VINLINE_NOSH) */
00195 
00196 VPUBLIC NOsh_PrintType NOsh_printWhat(NOsh *thee, int iprint) {
00197  VASSERT(thee != VNULL);
00198  VASSERT(iprint < thee->nprint);
00199  return thee->printwhat[iprint];
00200 }
00201 
00202 VPUBLIC int NOsh_printNarg(NOsh *thee, int iprint) {
00203  VASSERT(thee != VNULL);
00204  VASSERT(iprint < thee->nprint);
00205  return thee->printnarg[iprint];
00206 }
00207 
00208 VPUBLIC int NOsh_elec2calc(NOsh *thee, int icalc) {
00209  VASSERT(thee != VNULL);
00210  VASSERT(icalc < thee->ncalc);
00211  return thee->elec2calc[icalc];
00212 }
00213 
00214 VPUBLIC int NOsh_apol2calc(NOsh *thee, int icalc) {
00215  VASSERT(thee != VNULL);
00216  VASSERT(icalc < thee->ncalc);
00217  return thee->apol2calc[icalc];
00218 }
00219 
00220 VPUBLIC char* NOsh_elecname(NOsh *thee, int ielec) {
00221  VASSERT(thee != VNULL);
00222  VASSERT(ielec < thee->nelec + 1);
00223  return thee->elecname[ielec];
00224 } 
00225 
00226 VPUBLIC int NOsh_printOp(NOsh *thee, int iprint, int iarg) {
00227  VASSERT(thee != VNULL);
00228  VASSERT(iprint < thee->nprint);
00229  VASSERT(iarg < thee->printnarg[iprint]);
00230  return thee->printop[iprint][iarg];
00231 }
00232 
00233 VPUBLIC int NOsh_printCalc(NOsh *thee, int iprint, int iarg) {
00234  VASSERT(thee != VNULL);
00235  VASSERT(iprint < thee->nprint);
00236  VASSERT(iarg < thee->printnarg[iprint]);
00237  return thee->printcalc[iprint][iarg];
00238 }
00239 
00240 VPUBLIC NOsh* NOsh_ctor(int rank, int size) {
00241  
00242  /* Set up the structure */
00243  NOsh *thee = VNULL;
00244  thee = Vmem_malloc(VNULL, 1, sizeof(NOsh) );
00245  VASSERT( thee != VNULL);
00246  VASSERT( NOsh_ctor2(thee, rank, size) );
00247  
00248  return thee;
00249 }
00250 
00251 VPUBLIC int NOsh_ctor2(NOsh *thee, int rank, int size) {
00252  
00253  int i;
00254  
00255  if (thee == VNULL) return 0;
00256  
00257  thee->proc_rank = rank;
00258  thee->proc_size = size;
00259  
00260  thee->ispara = 0;
00261     thee->parsed = 0;
00262  
00263     thee->nmol = 0;
00264     thee->gotparm = 0;
00265     thee->ncharge = 0;
00266     thee->ndiel = 0;
00267     thee->nkappa = 0;
00268  thee->npot = 0;
00269     thee->nprint = 0;
00270  
00271     for (i=0; i<NOSH_MAXCALC; i++) {
00272   thee->calc[i] = VNULL;
00273   thee->elec[i] = VNULL;
00274   thee->apol[i] = VNULL;
00275  }
00276  for (i=0; i<NOSH_MAXMOL; i++) {
00277   thee->alist[i] = VNULL;
00278  }
00279  thee->ncalc = 0;
00280  thee->nelec = 0;
00281  thee->napol = 0;
00282  
00283     return 1; 
00284 }
00285 
00286 VPUBLIC void NOsh_dtor(NOsh **thee) {
00287     if ((*thee) != VNULL) {
00288         NOsh_dtor2(*thee);
00289         Vmem_free(VNULL, 1, sizeof(NOsh), (void **)thee);
00290         (*thee) = VNULL;
00291     }
00292 }
00293 
00294 VPUBLIC void NOsh_dtor2(NOsh *thee) { 
00295  
00296  int i;
00297  
00298  if (thee != VNULL) {
00299   for (i=0; i<(thee->ncalc); i++) NOsh_calc_dtor(&(thee->calc[i]));
00300   for (i=0; i<(thee->nelec); i++) NOsh_calc_dtor(&(thee->elec[i]));
00301   for (i=0; i<(thee->napol); i++) NOsh_calc_dtor(&(thee->apol[i]));
00302     }
00303  
00304 }
00305 
00306 VPUBLIC NOsh_calc* NOsh_calc_ctor(
00307           NOsh_CalcType calctype
00308           ) {
00309  NOsh_calc *thee;
00310  thee = (NOsh_calc *)Vmem_malloc(VNULL, 1, sizeof(NOsh_calc));
00311  thee->calctype = calctype;
00312  switch (calctype) {
00313   case NCT_MG:
00314    thee->mgparm = MGparm_ctor(MCT_NONE);
00315    thee->femparm = VNULL;
00316    thee->apolparm = VNULL;
00317    break;
00318   case NCT_FEM:
00319    thee->mgparm = VNULL;
00320    thee->femparm = FEMparm_ctor(FCT_NONE);
00321    thee->apolparm = VNULL;
00322    break;
00323   case NCT_APOL:
00324    thee->mgparm = VNULL;
00325    thee->femparm = VNULL;
00326    thee->apolparm = APOLparm_ctor();
00327    break;
00328   default:
00329    Vnm_print(2, "NOsh_calc_ctor:  unknown calculation type (%d)!\n",
00330        calctype);
00331    VASSERT(0);
00332  }
00333  thee->pbeparm = PBEparm_ctor();
00334  
00335  return thee;
00336 }
00337 
00338 VPUBLIC void NOsh_calc_dtor(
00339        NOsh_calc **thee 
00340        ) {
00341  
00342  NOsh_calc *calc = VNULL;
00343  calc = *thee;
00344  if (calc == VNULL) return;
00345  
00346  switch (calc->calctype) {
00347   case NCT_MG:
00348    MGparm_dtor(&(calc->mgparm));
00349    break;
00350   case NCT_FEM:
00351    FEMparm_dtor(&(calc->femparm));
00352    break;
00353   case NCT_APOL:
00354    APOLparm_dtor(&(calc->apolparm));
00355    break;
00356   default:
00357    Vnm_print(2, "NOsh_calc_ctor:  unknown calculation type (%d)!\n",
00358        calc->calctype);
00359    VASSERT(0);
00360  }
00361  PBEparm_dtor(&(calc->pbeparm));
00362  
00363  Vmem_free(VNULL, 1, sizeof(NOsh_calc), (void **)thee);
00364  calc = VNULL;
00365  
00366 }
00367 
00368 VPUBLIC int NOsh_calc_copy(
00369          NOsh_calc *thee,
00370          NOsh_calc *source
00371          ) {
00372  
00373  VASSERT(thee != VNULL);
00374  VASSERT(source != VNULL);
00375  VASSERT(thee->calctype == source->calctype);
00376  if (source->mgparm != VNULL)
00377   MGparm_copy(thee->mgparm, source->mgparm);
00378  if (source->femparm != VNULL)
00379   FEMparm_copy(thee->femparm, source->femparm);
00380  if (source->pbeparm != VNULL)
00381   PBEparm_copy(thee->pbeparm, source->pbeparm);
00382  if (source->apolparm != VNULL)
00383   APOLparm_copy(thee->apolparm, source->apolparm);
00384  
00385  return 1;
00386  
00387 }
00388 
00389 VPUBLIC int NOsh_parseInputFile(
00390         NOsh *thee, 
00391         char *filename
00392         ) {
00393  
00394  Vio *sock;
00395  int rc;
00396  
00397  sock = Vio_ctor("FILE", "ASC", VNULL, filename, "r");
00398  rc = NOsh_parseInput(thee, sock);
00399  Vio_dtor(&sock);
00400  
00401  return rc;
00402 }
00403 
00404 VPUBLIC int NOsh_parseInput(
00405        NOsh *thee, 
00406        Vio *sock
00407        ) {
00408  
00409  char *MCwhiteChars = " =,;\t\r\n";
00410  char *MCcommChars  = "#%";
00411  char tok[VMAX_BUFSIZE];
00412  
00413  if (thee == VNULL) {
00414   Vnm_print(2, "NOsh_parseInput:  Got NULL thee!\n");
00415   return 0;
00416  }
00417  
00418  if (sock == VNULL) {
00419   Vnm_print(2, "NOsh_parseInput:  Got pointer to NULL socket!\n");
00420   Vnm_print(2, "NOsh_parseInput:  The specified input file was not found!\n");
00421   return 0;
00422  } 
00423  
00424  if (thee->parsed) {
00425   Vnm_print(2, "NOsh_parseInput:  Already parsed an input file!\n");
00426   return 0;
00427  }
00428  
00429  if (Vio_accept(sock, 0) < 0) {
00430   Vnm_print(2, "NOsh_parseInput:  Problem reading from socket!\n");
00431   return 0;
00432  }
00433  
00434  /* Set up the whitespace and comment character definitions */
00435  Vio_setWhiteChars(sock, MCwhiteChars);
00436  Vio_setCommChars(sock, MCcommChars);
00437  
00438  /* We parse the file until we run out of tokens */
00439  Vnm_print(0, "NOsh_parseInput:  Starting file parsing...\n");
00440  while (Vio_scanf(sock, "%s", tok) == 1) {
00441   /* At the highest level, we look for keywords that indicate functions like:
00442   
00443   read => Read in a molecule file
00444   elec => Do an electrostatics calculation
00445   print => Print some results
00446   apolar => do a non-polar calculation
00447   quit => Quit
00448   
00449   These cause the code to go to a lower-level parser routine which
00450   handles keywords specific to the particular function.  Each
00451   lower-level parser routine then returns when it hits the "end"
00452   keyword.  Due to this simple layout, no nesting of these "function"
00453   sections is allowed.
00454   */
00455   if (Vstring_strcasecmp(tok, "read") == 0) {
00456    Vnm_print(0, "NOsh: Parsing READ section\n");
00457    if (!NOsh_parseREAD(thee, sock)) return 0;
00458    Vnm_print(0, "NOsh: Done parsing READ section \
00459 (nmol=%d, ndiel=%d, nkappa=%d, ncharge=%d, npot=%d)\n", thee->nmol, thee->ndiel, 
00460        thee->nkappa, thee->ncharge,thee->npot);
00461   } else if (Vstring_strcasecmp(tok, "print") == 0) {
00462    Vnm_print(0, "NOsh: Parsing PRINT section\n");
00463    if (!NOsh_parsePRINT(thee, sock)) return 0;
00464    Vnm_print(0, "NOsh: Done parsing PRINT section\n");
00465   } else if (Vstring_strcasecmp(tok, "elec") == 0) {
00466    Vnm_print(0, "NOsh: Parsing ELEC section\n");
00467    if (!NOsh_parseELEC(thee, sock)) return 0;
00468    Vnm_print(0, "NOsh: Done parsing ELEC section (nelec = %d)\n",
00469        thee->nelec);
00470   } else if (Vstring_strcasecmp(tok, "apolar") == 0) {
00471    Vnm_print(0, "NOsh: Parsing APOLAR section\n");
00472    if (!NOsh_parseAPOLAR(thee, sock)) return 0;
00473    Vnm_print(0, "NOsh: Done parsing APOLAR section (nelec = %d)\n",
00474        thee->nelec);
00475   } else if (Vstring_strcasecmp(tok, "quit") == 0) {
00476    Vnm_print(0, "NOsh: Done parsing file (got QUIT)\n");
00477    break;
00478   } else {
00479    Vnm_print(2, "NOsh_parseInput: Ignoring undefined keyword %s!\n", tok);
00480   }
00481  }
00482  
00483  thee->parsed = 1;
00484  return 1;
00485  
00486 }
00487 
00488 VPRIVATE int NOsh_parseREAD_MOL(NOsh *thee, Vio *sock) {
00489  
00490     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
00491     NOsh_MolFormat molfmt;
00492  
00493     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00494     if (Vstring_strcasecmp(tok, "pqr") == 0) {
00495         molfmt = NMF_PQR;
00496         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00497         if (tok[0]=='"') {
00498             strcpy(strnew, "");
00499             while (tok[strlen(tok)-1] != '"') {
00500                 strcat(str, tok);
00501                 strcat(str, " ");
00502                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00503    }
00504             strcat(str, tok);
00505             strncpy(strnew, str+1, strlen(str)-2);
00506             strcpy(tok, strnew);
00507         }
00508         Vnm_print(0, "NOsh: Storing molecule %d path %s\n", 
00509       thee->nmol, tok);
00510         thee->molfmt[thee->nmol] = molfmt;
00511         strncpy(thee->molpath[thee->nmol], tok, VMAX_ARGLEN);
00512         (thee->nmol)++;
00513     } else if (Vstring_strcasecmp(tok, "pdb") == 0) {
00514         molfmt = NMF_PDB;
00515         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00516         if (tok[0]=='"') {
00517             strcpy(strnew, "");
00518             while (tok[strlen(tok)-1] != '"') {
00519                 strcat(str, tok);
00520                 strcat(str, " ");
00521                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00522    }
00523             strcat(str, tok);
00524             strncpy(strnew, str+1, strlen(str)-2);
00525             strcpy(tok, strnew);
00526         }
00527         Vnm_print(0, "NOsh: Storing molecule %d path %s\n", 
00528       thee->nmol, tok);
00529         thee->molfmt[thee->nmol] = molfmt;
00530         strncpy(thee->molpath[thee->nmol], tok, VMAX_ARGLEN);
00531         (thee->nmol)++;
00532     } else if (Vstring_strcasecmp(tok, "xml") == 0) {
00533         molfmt = NMF_XML;
00534         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00535         if (tok[0]=='"') {
00536             strcpy(strnew, "");
00537             while (tok[strlen(tok)-1] != '"') {
00538                 strcat(str, tok);
00539                 strcat(str, " ");
00540                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00541    }
00542             strcat(str, tok);
00543             strncpy(strnew, str+1, strlen(str)-2);
00544             strcpy(tok, strnew);
00545         }
00546         Vnm_print(0, "NOsh: Storing molecule %d path %s\n", 
00547       thee->nmol, tok);
00548         thee->molfmt[thee->nmol] = molfmt;
00549         strncpy(thee->molpath[thee->nmol], tok, VMAX_ARGLEN);
00550         (thee->nmol)++;
00551     } else {
00552         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined mol format \
00553 %s!\n", tok);
00554     } 
00555  
00556     return 1;
00557  
00558  
00559 VERROR1:
00560         Vnm_print(2, "NOsh_parseREAD_MOL:  Ran out of tokens while parsing READ section!\n");
00561  return 0;
00562  
00563 }
00564 
00565 VPRIVATE int NOsh_parseREAD_PARM(NOsh *thee, Vio *sock) {
00566  
00567     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
00568     NOsh_ParmFormat parmfmt;
00569  
00570     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00571     if (Vstring_strcasecmp(tok, "flat") == 0) {
00572         parmfmt = NPF_FLAT;
00573         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00574         if (tok[0]=='"') {
00575             strcpy(strnew, "");
00576             while (tok[strlen(tok)-1] != '"') {
00577                 strcat(str, tok);
00578                 strcat(str, " ");
00579                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00580    }
00581             strcat(str, tok);
00582             strncpy(strnew, str+1, strlen(str)-2);
00583             strcpy(tok, strnew);
00584         }
00585         if (thee->gotparm) {
00586             Vnm_print(2, "NOsh:  Hey!  You already specified a parameterfile (%s)!\n", thee->parmpath);
00587             Vnm_print(2, "NOsh:  I'm going to ignore this one (%s)!\n", tok);
00588         } else {
00589             thee->parmfmt = parmfmt;
00590             thee->gotparm = 1;
00591             strncpy(thee->parmpath, tok, VMAX_ARGLEN);
00592         }
00593     } else if(Vstring_strcasecmp(tok, "xml") == 0) {
00594         parmfmt = NPF_XML;
00595         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00596         if (tok[0]=='"') {
00597             strcpy(strnew, "");
00598             while (tok[strlen(tok)-1] != '"') {
00599                 strcat(str, tok);
00600                 strcat(str, " ");
00601                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00602    }
00603             strcat(str, tok);
00604             strncpy(strnew, str+1, strlen(str)-2);
00605             strcpy(tok, strnew);
00606         }
00607         if (thee->gotparm) {
00608             Vnm_print(2, "NOsh:  Hey!  You already specified a parameterfile (%s)!\n", thee->parmpath);
00609             Vnm_print(2, "NOsh:  I'm going to ignore this one (%s)!\n", tok);
00610         } else {
00611             thee->parmfmt = parmfmt;
00612             thee->gotparm = 1;
00613             strncpy(thee->parmpath, tok, VMAX_ARGLEN);
00614         }
00615   
00616     } else {
00617         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined parm format \
00618 %s!\n", tok);
00619     } 
00620  
00621     return 1;
00622  
00623 VERROR1:
00624         Vnm_print(2, "NOsh_parseREAD_PARM:  Ran out of tokens while parsing READ section!\n");
00625  return 0;
00626  
00627 }
00628 
00629 VPRIVATE int NOsh_parseREAD_DIEL(NOsh *thee, Vio *sock) {
00630  
00631     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
00632     Vdata_Format dielfmt;
00633  
00634     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00635     if (Vstring_strcasecmp(tok, "dx") == 0) {
00636         dielfmt = VDF_DX;
00637  } else if (Vstring_strcasecmp(tok, "gz") == 0) {
00638         dielfmt = VDF_GZ;
00639  } else {
00640         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined format \
00641       %s!\n", tok);
00642   return VRC_FAILURE;
00643  }
00644  
00645  VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00646  if (tok[0]=='"') {
00647   strcpy(strnew, "");
00648   while (tok[strlen(tok)-1] != '"') {
00649    strcat(str, tok);
00650    strcat(str, " ");
00651    VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00652   }
00653   strcat(str, tok);
00654   strncpy(strnew, str+1, strlen(str)-2);
00655   strcpy(tok, strnew);
00656  }
00657  Vnm_print(0, "NOsh: Storing x-shifted dielectric map %d path \
00658      %s\n", thee->ndiel, tok);
00659  strncpy(thee->dielXpath[thee->ndiel], tok, VMAX_ARGLEN);
00660  VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00661  Vnm_print(0, "NOsh: Storing y-shifted dielectric map %d path \
00662      %s\n", thee->ndiel, tok);
00663  strncpy(thee->dielYpath[thee->ndiel], tok, VMAX_ARGLEN);
00664  VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00665  Vnm_print(0, "NOsh: Storing z-shifted dielectric map %d path \
00666      %s\n", thee->ndiel, tok);
00667  strncpy(thee->dielZpath[thee->ndiel], tok, VMAX_ARGLEN);
00668  thee->dielfmt[thee->ndiel] = dielfmt;
00669  (thee->ndiel)++;
00670 
00671  return 1;
00672  
00673 VERROR1:
00674         Vnm_print(2, "NOsh_parseREAD_DIEL:  Ran out of tokens while parsing READ \
00675 section!\n");
00676  return 0;
00677  
00678 }
00679 
00680 VPRIVATE int NOsh_parseREAD_KAPPA(NOsh *thee, Vio *sock) {
00681  
00682     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
00683     Vdata_Format kappafmt;
00684  
00685     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00686     if (Vstring_strcasecmp(tok, "dx") == 0) {
00687         kappafmt = VDF_DX;
00688  } else if (Vstring_strcasecmp(tok, "gz") == 0) {
00689         kappafmt = VDF_GZ;
00690  } else {
00691         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined format \
00692       %s!\n", tok);
00693   return VRC_FAILURE;
00694  }
00695  
00696  VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00697  if (tok[0]=='"') {
00698   strcpy(strnew, "");
00699   while (tok[strlen(tok)-1] != '"') {
00700    strcat(str, tok);
00701    strcat(str, " ");
00702    VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00703   }
00704   strcat(str, tok);
00705   strncpy(strnew, str+1, strlen(str)-2);
00706   strcpy(tok, strnew);
00707  }
00708  Vnm_print(0, "NOsh: Storing kappa map %d path %s\n",
00709      thee->nkappa, tok);
00710  thee->kappafmt[thee->nkappa] = kappafmt;
00711  strncpy(thee->kappapath[thee->nkappa], tok, VMAX_ARGLEN);
00712  (thee->nkappa)++;
00713     
00714     return 1;
00715  
00716 VERROR1:
00717         Vnm_print(2, "NOsh_parseREAD:  Ran out of tokens while parsing READ \
00718 section!\n");
00719  return 0;
00720  
00721 }
00722 
00723 VPRIVATE int NOsh_parseREAD_POTENTIAL(NOsh *thee, Vio *sock) {
00724  
00725     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
00726     Vdata_Format potfmt;
00727  
00728     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00729     if (Vstring_strcasecmp(tok, "dx") == 0) {
00730         potfmt = VDF_DX;
00731  } else if (Vstring_strcasecmp(tok, "gz") == 0) {
00732         potfmt = VDF_GZ;
00733  } else {
00734         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined format \
00735       %s!\n", tok);
00736   return VRC_FAILURE;
00737    }
00738  
00739  VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00740  if (tok[0]=='"') {
00741   strcpy(strnew, "");
00742   while (tok[strlen(tok)-1] != '"') {
00743    strcat(str, tok);
00744    strcat(str, " ");
00745    VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00746   }
00747   strcat(str, tok);
00748   strncpy(strnew, str+1, strlen(str)-2);
00749   strcpy(tok, strnew);
00750  }
00751  Vnm_print(0, "NOsh: Storing potential map %d path %s\n",
00752      thee->npot, tok);
00753  thee->potfmt[thee->npot] = potfmt;
00754  strncpy(thee->potpath[thee->npot], tok, VMAX_ARGLEN);
00755  (thee->npot)++;
00756     
00757  return 1;
00758  
00759 VERROR1:
00760  Vnm_print(2, "NOsh_parseREAD:  Ran out of tokens while parsing READ \
00761      section!\n");
00762  return 0;
00763  
00764 }
00765 
00766 VPRIVATE int NOsh_parseREAD_CHARGE(NOsh *thee, Vio *sock) {
00767  
00768     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
00769     Vdata_Format chargefmt;
00770  
00771     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00772     if (Vstring_strcasecmp(tok, "dx") == 0) {
00773         chargefmt = VDF_DX;
00774  } else if (Vstring_strcasecmp(tok, "gz") == 0) {
00775         chargefmt = VDF_GZ;
00776  } else {
00777         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined format \
00778       %s!\n", tok);
00779   return VRC_FAILURE;
00780  }
00781  
00782  VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00783  if (tok[0]=='"') {
00784   strcpy(strnew, "");
00785   while (tok[strlen(tok)-1] != '"') {
00786    strcat(str, tok);
00787    strcat(str, " ");
00788    VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00789   }
00790   strcat(str, tok);
00791   strncpy(strnew, str+1, strlen(str)-2);
00792   strcpy(tok, strnew);
00793  }
00794  Vnm_print(0, "NOsh: Storing charge map %d path %s\n",
00795      thee->ncharge, tok);
00796  thee->chargefmt[thee->ncharge] = chargefmt;
00797  strncpy(thee->chargepath[thee->ncharge], tok, VMAX_ARGLEN);
00798  (thee->ncharge)++;
00799  
00800     return 1;
00801  
00802 VERROR1:
00803         Vnm_print(2, "NOsh_parseREAD:  Ran out of tokens while parsing READ \
00804 section!\n");
00805  return 0;
00806  
00807 }
00808 
00809 VPRIVATE int NOsh_parseREAD_MESH(NOsh *thee, Vio *sock) {
00810  
00811     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
00812     Vdata_Format meshfmt;
00813  
00814     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00815     if (Vstring_strcasecmp(tok, "mcsf") == 0) {
00816         meshfmt = VDF_MCSF;
00817         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00818         if (tok[0]=='"') {
00819             strcpy(strnew, "");
00820             while (tok[strlen(tok)-1] != '"') {
00821                 strcat(str, tok);
00822                 strcat(str, " ");
00823                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00824    }
00825             strcat(str, tok);
00826             strncpy(strnew, str+1, strlen(str)-2);
00827             strcpy(tok, strnew);
00828         }
00829         Vnm_print(0, "NOsh: Storing mesh %d path %s\n",
00830       thee->nmesh, tok);
00831         thee->meshfmt[thee->nmesh] = meshfmt;
00832         strncpy(thee->meshpath[thee->nmesh], tok, VMAX_ARGLEN);
00833         (thee->nmesh)++;
00834     } else {
00835         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined mesh format \
00836       %s!\n", tok);
00837     }
00838  
00839     return 1;
00840  
00841 VERROR1:
00842  Vnm_print(2, "NOsh_parseREAD:  Ran out of tokens while parsing READ \
00843      section!\n");
00844  return 0;
00845  
00846 }
00847 
00848 
00849 VPRIVATE int NOsh_parseREAD(NOsh *thee, Vio *sock) {
00850  
00851     char tok[VMAX_BUFSIZE];
00852  
00853     if (thee == VNULL) {
00854         Vnm_print(2, "NOsh_parseREAD:  Got NULL thee!\n");
00855         return 0;
00856     }
00857  
00858     if (sock == VNULL) {
00859         Vnm_print(2, "NOsh_parseREAD:  Got pointer to NULL socket!\n");
00860         return 0;
00861     } 
00862  
00863     if (thee->parsed) {
00864         Vnm_print(2, "NOsh_parseREAD:  Already parsed an input file!\n");
00865         return 0;
00866     }
00867  
00868     /* Read until we run out of tokens (bad) or hit the "END" keyword (good) */
00869     while (Vio_scanf(sock, "%s", tok) == 1) {
00870         if (Vstring_strcasecmp(tok, "end") == 0) {
00871             Vnm_print(0, "NOsh: Done parsing READ section\n");
00872             return 1;
00873         } else if (Vstring_strcasecmp(tok, "mol") == 0) {
00874             NOsh_parseREAD_MOL(thee, sock);
00875         } else if (Vstring_strcasecmp(tok, "parm") == 0) {
00876             NOsh_parseREAD_PARM(thee,sock);
00877         } else if (Vstring_strcasecmp(tok, "diel") == 0) {
00878             NOsh_parseREAD_DIEL(thee,sock);
00879         } else if (Vstring_strcasecmp(tok, "kappa") == 0) {
00880             NOsh_parseREAD_KAPPA(thee,sock);
00881   } else if (Vstring_strcasecmp(tok, "pot") == 0) {
00882             NOsh_parseREAD_POTENTIAL(thee,sock);
00883         } else if (Vstring_strcasecmp(tok, "charge") == 0) {
00884             NOsh_parseREAD_CHARGE(thee,sock);
00885   } else if (Vstring_strcasecmp(tok, "mesh") == 0) {
00886    NOsh_parseREAD_MESH(thee,sock);
00887         } else {
00888             Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined keyword %s!\n", 
00889        tok);
00890         }
00891     }
00892  
00893     /* We ran out of tokens! */
00894     Vnm_print(2, "NOsh_parseREAD:  Ran out of tokens while parsing READ \
00895 section!\n");
00896     return 0;
00897  
00898 }
00899 
00900 VPRIVATE int NOsh_parsePRINT(NOsh *thee, Vio *sock) {
00901  
00902     char tok[VMAX_BUFSIZE];
00903  char name[VMAX_BUFSIZE];
00904     int ti, idx, expect, ielec, iapol;
00905  
00906     if (thee == VNULL) {
00907         Vnm_print(2, "NOsh_parsePRINT:  Got NULL thee!\n");
00908         return 0;
00909     }
00910  
00911     if (sock == VNULL) {
00912         Vnm_print(2, "NOsh_parsePRINT:  Got pointer to NULL socket!\n");
00913         return 0;
00914     } 
00915  
00916     if (thee->parsed) {
00917         Vnm_print(2, "NOsh_parsePRINT:  Already parsed an input file!\n");
00918         return 0;
00919     }
00920  
00921     idx = thee->nprint;
00922     if (thee->nprint >= NOSH_MAXPRINT) {
00923         Vnm_print(2, "NOsh_parsePRINT:  Exceeded max number (%d) of PRINT \
00924 sections\n", 
00925       NOSH_MAXPRINT);
00926         return 0;
00927     }
00928  
00929  
00930     /* The first thing we read is the thing we want to print */ 
00931     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
00932     if (Vstring_strcasecmp(tok, "energy") == 0) {
00933         thee->printwhat[idx] = NPT_ENERGY;
00934         thee->printnarg[idx] = 0;
00935     } else if (Vstring_strcasecmp(tok, "force") == 0) {
00936         thee->printwhat[idx] = NPT_FORCE;
00937         thee->printnarg[idx] = 0;
00938  } else if (Vstring_strcasecmp(tok, "elecEnergy") == 0) {
00939         thee->printwhat[idx] = NPT_ELECENERGY;
00940         thee->printnarg[idx] = 0;
00941  } else if (Vstring_strcasecmp(tok, "elecForce") == 0) {
00942         thee->printwhat[idx] = NPT_ELECFORCE;
00943         thee->printnarg[idx] = 0;
00944     } else if (Vstring_strcasecmp(tok, "apolEnergy") == 0) {
00945         thee->printwhat[idx] = NPT_APOLENERGY;
00946         thee->printnarg[idx] = 0;
00947  } else if (Vstring_strcasecmp(tok, "apolForce") == 0) {
00948         thee->printwhat[idx] = NPT_APOLFORCE;
00949         thee->printnarg[idx] = 0;
00950     } else {
00951         Vnm_print(2, "NOsh_parsePRINT:  Undefined keyword %s while parsing \
00952 PRINT section!\n", tok);
00953         return 0;
00954     }
00955  
00956     expect = 0;   /* We first expect a calculation ID (0) then an op (1) */
00957  
00958     /* Read until we run out of tokens (bad) or hit the "END" keyword (good) */
00959     while (Vio_scanf(sock, "%s", tok) == 1) {
00960   
00961         /* The next thing we read is either END or an ARG OP ARG statement */
00962         if (Vstring_strcasecmp(tok, "end") == 0) {
00963             if (expect != 0) {
00964                 (thee->nprint)++;
00965                 (thee->printnarg[idx])++;
00966                 Vnm_print(0, "NOsh: Done parsing PRINT section\n");
00967                 return 1;
00968             } else {
00969                 Vnm_print(2, "NOsh_parsePRINT:  Got premature END to PRINT!\n");
00970                 return 0;
00971             }
00972         } else {
00973    
00974             /* Grab a calculation ID */
00975             if ((sscanf(tok, "%d", &ti) == 1) && 
00976     (Vstring_isdigit(tok) == 1)) {
00977                 if (expect == 0) {
00978                     thee->printcalc[idx][thee->printnarg[idx]] = ti-1;
00979                     expect = 1;
00980                 } else {
00981                     Vnm_print(2, "NOsh_parsePRINT:  Syntax error in PRINT \
00982 section while reading %s!\n", tok);
00983                     return 0;
00984                 }
00985     /* Grab addition operation */
00986             } else if (Vstring_strcasecmp(tok, "+") == 0) {
00987                 if (expect == 1) {
00988                     thee->printop[idx][thee->printnarg[idx]] = 0;
00989                     (thee->printnarg[idx])++;
00990                     expect = 0;
00991                     if (thee->printnarg[idx] >= NOSH_MAXPOP) {
00992                         Vnm_print(2, "NOsh_parsePRINT:  Exceeded max number \
00993 (%d) of arguments for PRINT section!\n", 
00994           NOSH_MAXPOP);
00995                         return 0;
00996                     }
00997                 } else {
00998                     Vnm_print(2, "NOsh_parsePRINT:  Syntax error in PRINT \
00999 section while reading %s!\n", tok);
01000                     return 0;
01001                 }
01002     /* Grab subtraction operation */
01003             } else if (Vstring_strcasecmp(tok, "-") == 0) {
01004                 if (expect == 1) {
01005                     thee->printop[idx][thee->printnarg[idx]] = 1;
01006                     (thee->printnarg[idx])++;
01007                     expect = 0;
01008                     if (thee->printnarg[idx] >= NOSH_MAXPOP) {
01009                         Vnm_print(2, "NOsh_parseREAD:  Exceeded max number \
01010 (%d) of arguments for PRINT section!\n", 
01011           NOSH_MAXPOP);
01012                         return 0;
01013                     }
01014                 } else {
01015                     Vnm_print(2, "NOsh_parsePRINT:  Syntax error in PRINT \
01016 section while reading %s!\n", tok);
01017                     return 0;
01018                 }
01019     /* Grab a calculation name from elec ID */
01020    } else if (sscanf(tok, "%s", name) == 1) {
01021        if (expect == 0) {
01022      for (ielec=0; ielec<thee->nelec; ielec++) {
01023          if (Vstring_strcasecmp(thee->elecname[ielec], name) == 0) {
01024        thee->printcalc[idx][thee->printnarg[idx]] = ielec;
01025        expect = 1;
01026        break;
01027          }
01028         }
01029      for (iapol=0; iapol<thee->napol; iapol++) {
01030          if (Vstring_strcasecmp(thee->apolname[iapol], name) == 0) {
01031        thee->printcalc[idx][thee->printnarg[idx]] = iapol;
01032        expect = 1;
01033        break;
01034          }
01035         }
01036      if (expect == 0) {
01037       Vnm_print(2, "No ELEC or APOL statement has been named %s!\n", 
01038           name);
01039       return 0;
01040      }
01041                 } else {
01042                     Vnm_print(2, "NOsh_parsePRINT:  Syntax error in PRINT \
01043 section while reading %s!\n", tok);
01044                     return 0;
01045                 }
01046     /* Got bad operation */
01047             } else {
01048                 Vnm_print(2, "NOsh_parsePRINT:  Undefined keyword %s while \
01049 parsing PRINT section!\n", tok);
01050                 return 0;
01051             } 
01052         } /* end parse token */
01053 
01054     } /* end while */
01055 
01056     VJMPERR1(0);
01057 
01058     /* We ran out of tokens! */
01059 VERROR1:
01060        Vnm_print(2, "NOsh_parsePRINT:  Ran out of tokens while parsing PRINT \
01061 section!\n");
01062        return 0;
01063 
01064 }
01065 
01066 VPRIVATE int NOsh_parseELEC(NOsh *thee, Vio *sock) {
01067  
01068  NOsh_calc *calc = VNULL;
01069  
01070     char tok[VMAX_BUFSIZE];
01071  
01072     if (thee == VNULL) {
01073         Vnm_print(2, "NOsh_parseELEC:  Got NULL thee!\n");
01074         return 0;
01075     }
01076  
01077     if (sock == VNULL) {
01078         Vnm_print(2, "NOsh_parseELEC:  Got pointer to NULL socket!\n");
01079         return 0;
01080     } 
01081  
01082     if (thee->parsed) {
01083         Vnm_print(2, "NOsh_parseELEC:  Already parsed an input file!\n");
01084         return 0;
01085     }
01086  
01087     /* Get a pointer to the latest ELEC calc object and update the ELEC 
01088   statement number */
01089     if (thee->nelec >= NOSH_MAXCALC) {
01090         Vnm_print(2, "NOsh:  Too many electrostatics calculations in this \
01091 run!\n");
01092         Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n", 
01093       NOSH_MAXCALC);
01094         return 1;
01095     }
01096  
01097     /* The next token HAS to be the method OR "name" */
01098  if (Vio_scanf(sock, "%s", tok) == 1) {
01099      if (Vstring_strcasecmp(tok, "name") == 0) {
01100       Vio_scanf(sock, "%s", tok);
01101             strncpy(thee->elecname[thee->nelec], tok, VMAX_ARGLEN);
01102    if (Vio_scanf(sock, "%s", tok) != 1) {
01103     Vnm_print(2, "NOsh_parseELEC:  Ran out of tokens while reading \
01104 ELEC section!\n");
01105     return 0;
01106    }
01107   }
01108   if (Vstring_strcasecmp(tok, "mg-manual") == 0) {
01109    thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_MG);
01110    calc = thee->elec[thee->nelec];
01111    (thee->nelec)++; 
01112    calc->mgparm->type = MCT_MANUAL;
01113       return NOsh_parseMG(thee, sock, calc);
01114   } else if (Vstring_strcasecmp(tok, "mg-auto") == 0) {
01115    thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_MG);
01116    calc = thee->elec[thee->nelec];
01117    (thee->nelec)++; 
01118    calc->mgparm->type = MCT_AUTO;
01119       return NOsh_parseMG(thee, sock, calc);
01120   } else if (Vstring_strcasecmp(tok, "mg-para") == 0) {
01121    thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_MG);
01122    calc = thee->elec[thee->nelec];
01123    (thee->nelec)++; 
01124    calc->mgparm->type = MCT_PARALLEL;
01125       return NOsh_parseMG(thee, sock, calc);
01126   } else if (Vstring_strcasecmp(tok, "mg-dummy") == 0) {
01127    thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_MG);
01128    calc = thee->elec[thee->nelec];
01129    (thee->nelec)++; 
01130    calc->mgparm->type = MCT_DUMMY;
01131       return NOsh_parseMG(thee, sock, calc);
01132   } else if (Vstring_strcasecmp(tok, "fe-manual") == 0) {
01133    thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_FEM);
01134    calc = thee->elec[thee->nelec];
01135    (thee->nelec)++; 
01136    calc->femparm->type = FCT_MANUAL;
01137       return NOsh_parseFEM(thee, sock, calc);
01138   } else {
01139       Vnm_print(2, "NOsh_parseELEC: The method (\"mg\" or \"fem\") or \
01140 \"name\" must be the first keyword in the ELEC section\n");
01141    return 0;
01142   } 
01143  } 
01144  
01145     Vnm_print(2, "NOsh_parseELEC:  Ran out of tokens while reading ELEC section!\n");
01146     return 0;
01147  
01148 }
01149 
01150 VPRIVATE int NOsh_parseAPOLAR(NOsh *thee, Vio *sock) {
01151  
01152  NOsh_calc *calc = VNULL;
01153  
01154     char tok[VMAX_BUFSIZE];
01155  
01156     if (thee == VNULL) {
01157         Vnm_print(2, "NOsh_parseAPOLAR:  Got NULL thee!\n");
01158         return 0;
01159     }
01160  
01161     if (sock == VNULL) {
01162         Vnm_print(2, "NOsh_parseAPOLAR:  Got pointer to NULL socket!\n");
01163         return 0;
01164     } 
01165  
01166     if (thee->parsed) {
01167         Vnm_print(2, "NOsh_parseAPOLAR:  Already parsed an input file!\n");
01168         return 0;
01169     }
01170  
01171  /* Get a pointer to the latest ELEC calc object and update the ELEC 
01172   statement number */
01173     if (thee->napol >= NOSH_MAXCALC) {
01174         Vnm_print(2, "NOsh:  Too many non-polar calculations in this \
01175 run!\n");
01176         Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n", 
01177       NOSH_MAXCALC);
01178         return 1;
01179     }
01180  
01181  /* The next token HAS to be the method OR "name" */
01182  if (Vio_scanf(sock, "%s", tok) == 1) {
01183      if (Vstring_strcasecmp(tok, "name") == 0) {
01184       Vio_scanf(sock, "%s", tok);
01185             strncpy(thee->apolname[thee->napol], tok, VMAX_ARGLEN);
01186    
01187    /* Parse the non-polar parameters */
01188    thee->apol[thee->napol] = NOsh_calc_ctor(NCT_APOL);
01189    calc = thee->apol[thee->napol];
01190    (thee->napol)++;
01191    return NOsh_parseAPOL(thee, sock, calc);
01192    
01193    if (Vio_scanf(sock, "%s", tok) != 1) {
01194     Vnm_print(2, "NOsh_parseAPOLAR:  Ran out of tokens while reading \
01195 APOLAR section!\n");
01196     return 0;
01197    }
01198   }
01199  } 
01200    
01201  return 1;
01202  
01203 }
01204 
01205 VPUBLIC int NOsh_setupElecCalc(
01206          NOsh *thee, 
01207          Valist *alist[NOSH_MAXMOL]
01208          ) {
01209  int ielec, imol, i;
01210  NOsh_calc *elec = VNULL;
01211  MGparm *mgparm = VNULL;
01212  Valist *mymol = VNULL;
01213  
01214  VASSERT(thee != VNULL);
01215  for (imol=0; imol<thee->nmol; imol++) {
01216   thee->alist[imol] = alist[imol];
01217  }
01218  
01219  
01220  for (ielec=0; ielec<(thee->nelec); ielec++) {
01221   /* Unload the calculation object containing the ELEC information */
01222   elec = thee->elec[ielec];
01223   
01224   if (((thee->ndiel != 0) || (thee->nkappa != 0) ||
01225     (thee->ncharge != 0) || (thee->npot != 0)) &&
01226     (elec->pbeparm->calcforce != PCF_NO)) {
01227    Vnm_print(2, "NOsh_setupElecCalc:  Calculation of forces disabled because surface \
01228 map is used!\n");
01229    elec->pbeparm->calcforce = PCF_NO;
01230   }
01231 
01232   /* Setup the calculation */
01233   switch (elec->calctype) {
01234    case NCT_MG:
01235     /* Center on the molecules, if requested */
01236     mgparm = elec->mgparm;
01237     VASSERT(mgparm != VNULL);
01238     if (elec->mgparm->cmeth == MCM_MOLECULE) {
01239      VASSERT(mgparm->centmol >= 0);
01240      VASSERT(mgparm->centmol < thee->nmol);
01241      mymol = thee->alist[mgparm->centmol];
01242      VASSERT(mymol != VNULL);
01243      for (i=0; i<3; i++) {
01244       mgparm->center[i] = mymol->center[i];
01245      }
01246     }
01247     if (elec->mgparm->fcmeth == MCM_MOLECULE) {
01248      VASSERT(mgparm->fcentmol >= 0);
01249      VASSERT(mgparm->fcentmol < thee->nmol);
01250      mymol = thee->alist[mgparm->fcentmol];
01251      VASSERT(mymol != VNULL);
01252      for (i=0; i<3; i++) {
01253       mgparm->fcenter[i] = mymol->center[i];
01254      }
01255     }
01256     if (elec->mgparm->ccmeth == MCM_MOLECULE) {
01257      VASSERT(mgparm->ccentmol >= 0);
01258      VASSERT(mgparm->ccentmol < thee->nmol);
01259      mymol = thee->alist[mgparm->ccentmol];
01260      VASSERT(mymol != VNULL);
01261      for (i=0; i<3; i++) {
01262       mgparm->ccenter[i] = mymol->center[i];
01263      }
01264     }
01265     NOsh_setupCalcMG(thee, elec);
01266     break;
01267    case NCT_FEM:
01268     NOsh_setupCalcFEM(thee, elec);
01269     break;
01270    default:
01271     Vnm_print(2, "NOsh_setupCalc:  Invalid calculation type (%d)!\n",
01272         elec->calctype);
01273     return 0;
01274   }
01275   
01276   /* At this point, the most recently-created NOsh_calc object should be the
01277    one we use for results for this ELEC statement.  Assign it. */
01278   /* Associate ELEC statement with the calculation */
01279   thee->elec2calc[ielec] = thee->ncalc-1;
01280   Vnm_print(0, "NOsh_setupCalc:  Mapping ELEC statement %d (%d) to \
01281 calculation %d (%d)\n", ielec, ielec+1, thee->elec2calc[ielec], 
01282       thee->elec2calc[ielec]+1);
01283  }
01284  
01285  return 1;
01286 }
01287 
01288 VPUBLIC int NOsh_setupApolCalc(
01289           NOsh *thee, 
01290           Valist *alist[NOSH_MAXMOL]
01291           ) {
01292  int iapol, imol;
01293  int doCalc = ACD_NO;
01294  NOsh_calc *calc = VNULL;
01295  
01296  VASSERT(thee != VNULL);
01297  for (imol=0; imol<thee->nmol; imol++) {
01298   thee->alist[imol] = alist[imol];
01299  }
01300  
01301  for (iapol=0; iapol<(thee->napol); iapol++) {
01302   /* Unload the calculation object containing the APOL information */
01303   calc = thee->apol[iapol];
01304   
01305   /* Setup the calculation */
01306   switch (calc->calctype) {
01307    case NCT_APOL:
01308     NOsh_setupCalcAPOL(thee, calc);
01309     doCalc = ACD_YES;
01310     break;
01311    default:
01312     Vnm_print(2, "NOsh_setupCalc:  Invalid calculation type (%d)!\n", calc->calctype);
01313     return ACD_ERROR;
01314   }
01315   /* At this point, the most recently-created NOsh_calc object should be the
01316    one we use for results for this APOL statement.  Assign it. */
01317   /* Associate APOL statement with the calculation */
01318   thee->apol2calc[iapol] = thee->ncalc-1;
01319   Vnm_print(0, "NOsh_setupCalc:  Mapping APOL statement %d (%d) to calculation %d (%d)\n", iapol, iapol+1, thee->apol2calc[iapol], thee->apol2calc[iapol]+1);
01320  }
01321  
01322  if(doCalc == ACD_YES){
01323   return ACD_YES;
01324  }else{
01325   return ACD_NO;
01326  }
01327 }
01328 
01329 VPUBLIC int NOsh_parseMG(
01330        NOsh *thee, 
01331        Vio *sock, 
01332        NOsh_calc *elec
01333        ) {
01334  
01335  char tok[VMAX_BUFSIZE];
01336  MGparm *mgparm = VNULL;    
01337  PBEparm *pbeparm = VNULL;    
01338  int rc;
01339     
01340  /* Check the arguments */
01341  if (thee == VNULL) {
01342   Vnm_print(2, "NOsh:  Got NULL thee!\n");
01343   return 0;
01344  }
01345  if (sock == VNULL) {
01346   Vnm_print(2, "NOsh:  Got pointer to NULL socket!\n");
01347   return 0;
01348  }
01349  if (elec == VNULL) {
01350   Vnm_print(2, "NOsh:  Got pointer to NULL elec object!\n");
01351   return 0;
01352  }
01353  mgparm = elec->mgparm;
01354  if (mgparm == VNULL) {
01355   Vnm_print(2, "NOsh:  Got pointer to NULL mgparm object!\n");
01356   return 0;
01357  }
01358  pbeparm = elec->pbeparm;
01359  if (pbeparm == VNULL) {
01360   Vnm_print(2, "NOsh:  Got pointer to NULL pbeparm object!\n");
01361   return 0;
01362  }
01363  
01364  Vnm_print(0, "NOsh_parseMG: Parsing parameters for MG calculation\n");
01365  
01366  /* Parallel stuff */
01367  if (mgparm->type == MCT_PARALLEL) {
01368   mgparm->proc_rank = thee->proc_rank;
01369   mgparm->proc_size = thee->proc_size;
01370   mgparm->setrank = 1;
01371   mgparm->setsize = 1;
01372  }
01373 
01374  
01375  /* Start snarfing tokens from the input stream */
01376  rc = 1;
01377  while (Vio_scanf(sock, "%s", tok) == 1) { 
01378   
01379   Vnm_print(0, "NOsh_parseMG:  Parsing %s...\n", tok);
01380   
01381   /* See if it's an END token */
01382   if (Vstring_strcasecmp(tok, "end") == 0) {
01383    mgparm->parsed = 1;
01384    pbeparm->parsed = 1;
01385    rc = 1;
01386    break;
01387   }
01388   
01389   /* Pass the token through a series of parsers */
01390   rc = PBEparm_parseToken(pbeparm, tok, sock);
01391   if (rc == -1) {
01392    Vnm_print(0, "NOsh_parseMG:  parsePBE error!\n");
01393    break;
01394   } else if (rc == 0) {
01395    /* Pass the token to the generic MG parser */
01396    rc = MGparm_parseToken(mgparm, tok, sock);
01397    if (rc == -1) { 
01398     Vnm_print(0, "NOsh_parseMG:  parseMG error!\n");
01399     break;
01400    } else if (rc == 0) {
01401     /* We ran out of parsers! */
01402     Vnm_print(2, "NOsh:  Unrecognized keyword: %s\n", tok);
01403     break;
01404    }
01405   }
01406  }
01407  
01408  /* Handle various errors arising in the token-snarfing loop -- these all 
01409   just result in simple returns right now */
01410  if (rc == -1) return 0;
01411  if (rc == 0) return 0;
01412  
01413  /* Check the status of the parameter objects */
01414  if ((MGparm_check(mgparm) == VRC_FAILURE) || (!PBEparm_check(pbeparm))) {
01415   Vnm_print(2, "NOsh:  MG parameters not set correctly!\n");
01416   return 0;
01417  }
01418  
01419  return 1;
01420 }
01421 
01422 VPRIVATE int NOsh_setupCalcMG(
01423          NOsh *thee,
01424          NOsh_calc *calc
01425          ) {
01426  
01427  MGparm *mgparm = VNULL;
01428  
01429  VASSERT(thee != VNULL);
01430  VASSERT(calc != VNULL);
01431  mgparm = calc->mgparm;
01432  VASSERT(mgparm != VNULL);
01433  
01434  
01435  /* Now we're ready to whatever sorts of post-processing operations that are
01436   necessary for the various types of calculations */
01437  switch (mgparm->type) {
01438   case MCT_MANUAL:
01439    return NOsh_setupCalcMGMANUAL(thee, calc);
01440   case MCT_DUMMY:
01441    return NOsh_setupCalcMGMANUAL(thee, calc);
01442   case MCT_AUTO:
01443    return NOsh_setupCalcMGAUTO(thee, calc);
01444   case MCT_PARALLEL:
01445    return NOsh_setupCalcMGPARA(thee, calc);
01446   default:
01447    Vnm_print(2, "NOsh_setupCalcMG:  undefined MG calculation type (%d)!\n",
01448        mgparm->type);
01449    return 0;
01450  }
01451  
01452  /* Shouldn't get here */
01453  return 0;
01454 }
01455 
01456 VPRIVATE int NOsh_setupCalcFEM(
01457           NOsh *thee,
01458           NOsh_calc *calc
01459           ) {
01460  
01461  VASSERT(thee != VNULL);
01462  VASSERT(calc != VNULL);
01463  VASSERT(calc->femparm != VNULL);
01464  
01465  /* Now we're ready to whatever sorts of post-processing operations that are
01466   * necessary for the various types of calculations */
01467  switch (calc->femparm->type) {
01468   case FCT_MANUAL:
01469    return NOsh_setupCalcFEMANUAL(thee, calc);
01470   default:
01471    Vnm_print(2, "NOsh_parseFEM:  unknown calculation type (%d)!\n",
01472        calc->femparm->type);
01473    return 0;
01474  }
01475  
01476  /* Shouldn't get here */
01477  return 0;
01478 }
01479 
01480 
01481 VPRIVATE int NOsh_setupCalcMGMANUAL(
01482            NOsh *thee, 
01483            NOsh_calc *elec
01484            ) {
01485  
01486  MGparm *mgparm = VNULL;
01487  PBEparm *pbeparm = VNULL;
01488  NOsh_calc *calc = VNULL;
01489  
01490  if (thee == VNULL) {
01491   Vnm_print(2, "NOsh_setupCalcMGMANUAL:  Got NULL thee!\n");
01492   return 0;
01493  }
01494  if (elec == VNULL) {
01495   Vnm_print(2, "NOsh_setupCalcMGMANUAL:  Got NULL calc!\n");
01496   return 0;
01497  }
01498  mgparm = elec->mgparm;
01499  if (mgparm == VNULL) {
01500   Vnm_print(2, "NOsh_setupCalcMGMANUAL:  Got NULL mgparm -- was this calculation \
01501 set up?\n");
01502   return 0;
01503  }
01504  pbeparm = elec->pbeparm;
01505  if (pbeparm == VNULL) {
01506   Vnm_print(2, "NOsh_setupCalcMGMANUAL:  Got NULL pbeparm -- was this calculation \
01507 set up?\n");
01508   return 0;
01509  }
01510  
01511  /* Set up missing MG parameters */
01512  if (mgparm->setgrid == 0) {
01513   VASSERT(mgparm->setglen);
01514   mgparm->grid[0] = mgparm->glen[0]/((double)(mgparm->dime[0]-1));
01515   mgparm->grid[1] = mgparm->glen[1]/((double)(mgparm->dime[1]-1));
01516   mgparm->grid[2] = mgparm->glen[2]/((double)(mgparm->dime[2]-1));
01517  }
01518  if (mgparm->setglen == 0) {
01519   VASSERT(mgparm->setgrid);
01520   mgparm->glen[0] = mgparm->grid[0]*((double)(mgparm->dime[0]-1));
01521   mgparm->glen[1] = mgparm->grid[1]*((double)(mgparm->dime[1]-1));
01522   mgparm->glen[2] = mgparm->grid[2]*((double)(mgparm->dime[2]-1)); 
01523  }
01524  
01525  /* Check to see if he have any room left for this type of calculation, if 
01526   so: set the calculation type, update the number of calculations of this type, 
01527   and parse the rest of the section */
01528  if (thee->ncalc >= NOSH_MAXCALC) {
01529   Vnm_print(2, "NOsh:  Too many calculations in this run!\n");
01530   Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
01531       NOSH_MAXCALC);
01532   return 0;
01533  }
01534  
01535     /* Get the next calculation object and increment the number of calculations */
01536  thee->calc[thee->ncalc] = NOsh_calc_ctor(NCT_MG);
01537  calc = thee->calc[thee->ncalc];
01538  (thee->ncalc)++;
01539  
01540 
01541  
01542  /* Copy over contents of ELEC */
01543  NOsh_calc_copy(calc, elec);
01544  
01545  
01546     return 1;
01547 }
01548 
01549 VPUBLIC int NOsh_setupCalcMGAUTO(
01550          NOsh *thee,
01551          NOsh_calc *elec
01552          ) {
01553  
01554  NOsh_calc *calcf = VNULL;
01555  NOsh_calc *calcc = VNULL;
01556  double fgrid[3], cgrid[3];
01557  double d[3], minf[3], maxf[3], minc[3], maxc[3];
01558  double redfrac, redrat[3], td;
01559  int ifocus, nfocus, tnfocus[3];
01560  int j;
01561  int icalc;
01562  int dofix;
01563  
01564  /* A comment about the coding style in this function.  I use lots and lots
01565   and lots of pointer deferencing.  I could (and probably should) save 
01566   these in temporary variables.  However, since there are so many MGparm, 
01567   etc. and NOsh_calc, etc. objects running around in this function, the 
01568   current scheme is easiest to debug. */
01569 
01570  
01571  if (thee == VNULL) {
01572   Vnm_print(2, "NOsh_setupCalcMGAUTO:  Got NULL thee!\n");
01573   return 0;
01574  }
01575  if (elec == VNULL) {
01576   Vnm_print(2, "NOsh_setupCalcMGAUTO:  Got NULL elec!\n");
01577   return 0;
01578  }
01579  if (elec->mgparm == VNULL) {
01580   Vnm_print(2, "NOsh_setupCalcMGAUTO:  Got NULL mgparm!\n");
01581   return 0;
01582  }
01583  if (elec->pbeparm == VNULL) {
01584   Vnm_print(2, "NOsh_setupCalcMGAUTO:  Got NULL pbeparm!\n");
01585   return 0;
01586  }
01587  
01588  Vnm_print(0, "NOsh_setupCalcMGAUTO(%s, %d):  coarse grid center = %g %g %g\n",
01589      __FILE__, __LINE__, 
01590      elec->mgparm->ccenter[0],
01591      elec->mgparm->ccenter[1],
01592      elec->mgparm->ccenter[2]);
01593  Vnm_print(0, "NOsh_setupCalcMGAUTO(%s, %d):  fine grid center = %g %g %g\n",
01594      __FILE__, __LINE__, 
01595      elec->mgparm->fcenter[0],
01596      elec->mgparm->fcenter[1],
01597      elec->mgparm->fcenter[2]);
01598  
01599  /* Calculate the grid spacing on the coarse and fine levels */
01600  for (j=0; j<3; j++) {
01601   cgrid[j] = (elec->mgparm->cglen[j])/((double)(elec->mgparm->dime[j]-1));
01602   fgrid[j] = (elec->mgparm->fglen[j])/((double)(elec->mgparm->dime[j]-1));
01603   d[j] = elec->mgparm->fcenter[j] - elec->mgparm->ccenter[j];
01604  }
01605  Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  Coarse grid spacing = %g, %g, %g\n", 
01606      __FILE__, __LINE__, cgrid[0], cgrid[1], cgrid[2]);
01607  Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  Fine grid spacing = %g, %g, %g\n",
01608      __FILE__, __LINE__, fgrid[0], fgrid[1], fgrid[2]);
01609  Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  Displacement between fine and \
01610 coarse grids = %g, %g, %g\n", __FILE__, __LINE__, d[0], d[1], d[2]);
01611  
01612  /* Now calculate the number of focusing levels, never reducing the grid 
01613   spacing by more than redfrac at each level */
01614  for (j=0; j<3; j++) {
01615   if (fgrid[j]/cgrid[j] < VREDFRAC) {
01616    redfrac = fgrid[j]/cgrid[j];
01617    td = log(redfrac)/log(VREDFRAC);
01618    tnfocus[j] = (int)ceil(td) + 1;
01619   } else tnfocus[j] = 2;
01620  }
01621  nfocus = VMAX2(VMAX2(tnfocus[0], tnfocus[1]), tnfocus[2]);
01622  
01623  /* Now set redrat to the actual value by which the grid spacing is reduced 
01624   at each level of focusing */
01625  for (j=0; j<3; j++) {
01626   redrat[j] = VPOW((fgrid[j]/cgrid[j]), 1.0/((double)nfocus-1.0));
01627  }
01628  Vnm_print(0, "NOsh:  %d levels of focusing with %g, %g, %g reductions\n",
01629      nfocus, redrat[0], redrat[1], redrat[2]);
01630  
01631  /* Now that we know how many focusing levels to use, we're ready to set up 
01632   the parameter objects */
01633  if (nfocus > (NOSH_MAXCALC-(thee->ncalc))) {
01634   Vnm_print(2, "NOsh:  Require more calculations than max (%d)!\n",
01635       NOSH_MAXCALC);
01636   return 0;
01637  } 
01638 
01639  for (ifocus=0; ifocus<nfocus; ifocus++) {
01640   
01641   /* Generate the new calc object */
01642   icalc = thee->ncalc;
01643   thee->calc[icalc] = NOsh_calc_ctor(NCT_MG);
01644   (thee->ncalc)++;
01645   
01646   /* This is the _current_ NOsh_calc object */
01647   calcf = thee->calc[icalc];
01648   /* This is the _previous_ Nosh_calc object */
01649   if (ifocus != 0) {
01650    calcc = thee->calc[icalc-1];
01651   } else {
01652    calcc = VNULL;
01653   }
01654   
01655   /* Copy over most of the parameters from the ELEC object */
01656   NOsh_calc_copy(calcf, elec);
01657   
01658   /* Set up the grid lengths and spacings */
01659   if (ifocus == 0) {
01660    for (j=0; j<3; j++) {
01661     calcf->mgparm->grid[j] = cgrid[j];
01662     calcf->mgparm->glen[j] = elec->mgparm->cglen[j];
01663    }
01664   } else {
01665    for (j=0; j<3; j++) {
01666     calcf->mgparm->grid[j] = redrat[j]*(calcc->mgparm->grid[j]);
01667                 calcf->mgparm->glen[j] = redrat[j]*(calcc->mgparm->glen[j]);
01668             }
01669         }
01670         calcf->mgparm->setgrid = 1;
01671         calcf->mgparm->setglen = 1;
01672   
01673   /* Get centers and centering method from coarse and fine meshes */
01674         if (ifocus == 0) {
01675    calcf->mgparm->cmeth = elec->mgparm->ccmeth;
01676    calcf->mgparm->centmol = elec->mgparm->ccentmol;
01677    for (j=0; j<3; j++) {
01678     calcf->mgparm->center[j] = elec->mgparm->ccenter[j];
01679    }
01680   } else if (ifocus == (nfocus-1)) {
01681    calcf->mgparm->cmeth = elec->mgparm->fcmeth;
01682    calcf->mgparm->centmol = elec->mgparm->fcentmol;
01683    for (j=0; j<3; j++) {
01684     calcf->mgparm->center[j] = elec->mgparm->fcenter[j];
01685    }
01686   } else {
01687    calcf->mgparm->cmeth = MCM_FOCUS;
01688    /* TEMPORARILY move the current grid center 
01689    to the fine grid center.  In general, this will move portions of 
01690    the current mesh off the immediately-coarser mesh.  We'll fix that
01691    in the next step. */
01692    for (j=0; j<3; j++) {
01693     calcf->mgparm->center[j] = elec->mgparm->fcenter[j];
01694    }
01695   }
01696 
01697   
01698   /* As mentioned above, it is highly likely that the previous "jump" 
01699    to the fine grid center put portions of the current mesh off the 
01700    previous (coarser) mesh.  Fix this by displacing the current mesh 
01701    back onto the previous coarser mesh.  */
01702   if (ifocus != 0) {
01703    Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  starting mesh \
01704 repositioning.\n", __FILE__, __LINE__);
01705    Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  coarse mesh center = \
01706 %g %g %g\n", __FILE__, __LINE__, 
01707        calcc->mgparm->center[0], 
01708          calcc->mgparm->center[1],
01709          calcc->mgparm->center[2]);
01710    Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  coarse mesh upper corner = \
01711 %g %g %g\n", __FILE__, __LINE__, 
01712        calcc->mgparm->center[0]+0.5*(calcc->mgparm->glen[0]), 
01713          calcc->mgparm->center[1]+0.5*(calcc->mgparm->glen[1]),
01714          calcc->mgparm->center[2]+0.5*(calcc->mgparm->glen[2]));
01715    Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  coarse mesh lower corner = \
01716 %g %g %g\n", __FILE__, __LINE__, 
01717        calcc->mgparm->center[0]-0.5*(calcc->mgparm->glen[0]), 
01718          calcc->mgparm->center[1]-0.5*(calcc->mgparm->glen[1]),
01719          calcc->mgparm->center[2]-0.5*(calcc->mgparm->glen[2]));
01720    Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  initial fine mesh upper corner = \
01721 %g %g %g\n", __FILE__, __LINE__, 
01722        calcf->mgparm->center[0]+0.5*(calcf->mgparm->glen[0]), 
01723          calcf->mgparm->center[1]+0.5*(calcf->mgparm->glen[1]),
01724          calcf->mgparm->center[2]+0.5*(calcf->mgparm->glen[2]));
01725    Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  initial fine mesh lower corner = \
01726 %g %g %g\n", __FILE__, __LINE__, 
01727        calcf->mgparm->center[0]-0.5*(calcf->mgparm->glen[0]), 
01728          calcf->mgparm->center[1]-0.5*(calcf->mgparm->glen[1]),
01729          calcf->mgparm->center[2]-0.5*(calcf->mgparm->glen[2]));
01730    for (j=0; j<3; j++) {
01731     /* Check if we've fallen off of the lower end of the mesh */
01732     dofix = 0;
01733     minf[j] = calcf->mgparm->center[j] 
01734      - 0.5*(calcf->mgparm->glen[j]);
01735     minc[j] = calcc->mgparm->center[j] 
01736      - 0.5*(calcc->mgparm->glen[j]);
01737     d[j] = minc[j] - minf[j];
01738     if (d[j] >= VSMALL) {
01739      if (ifocus == (nfocus-1)) {
01740       Vnm_print(2, "NOsh_setupCalcMGAUTO:  Error!  Finest \
01741 mesh has fallen off the coarser meshes!\n");
01742       Vnm_print(2, "NOsh_setupCalcMGAUTO:  difference in min %d-\
01743 direction = %g\n", j, d[j]);
01744       Vnm_print(2, "NOsh_setupCalcMGAUTO:  min fine = %g %g %g\n",
01745           minf[0], minf[1], minf[2]);
01746       Vnm_print(2, "NOsh_setupCalcMGAUTO:  min coarse = %g %g %g\n",
01747           minc[0], minc[1], minc[2]);
01748       VASSERT(0);
01749      } else {
01750       Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  ifocus = %d, \
01751 fixing mesh min violation (%g in %d-direction).\n", __FILE__, __LINE__, ifocus, 
01752           d[j], j);
01753       calcf->mgparm->center[j] += d[j];
01754       dofix = 1;
01755      }
01756     }
01757     /* Check if we've fallen off of the upper end of the mesh */
01758     maxf[j] = calcf->mgparm->center[j] \
01759      + 0.5*(calcf->mgparm->glen[j]);
01760     maxc[j] = calcc->mgparm->center[j] \
01761      + 0.5*(calcc->mgparm->glen[j]);
01762     d[j] = maxf[j] - maxc[j];
01763     if (d[j] >= VSMALL) {
01764      if (ifocus == (nfocus-1)) {
01765       Vnm_print(2, "NOsh_setupCalcMGAUTO:  Error!  Finest \
01766 mesh has fallen off the coarser meshes!\n");
01767       Vnm_print(2, "NOsh_setupCalcMGAUTO:  difference in %d-\
01768 direction = %g\n", j, d[j]);
01769       VASSERT(0);
01770      } else {
01771       /* If we already fixed the lower boundary and we now need
01772       to fix the upper boundary, we have a serious problem. */
01773       if (dofix) {
01774        Vnm_print(2, "NOsh_setupCalcMGAUTO:  Error!  Both \
01775 ends of the finer mesh do not fit in the bigger mesh!\n");
01776        VASSERT(0);
01777       }
01778       Vnm_print(0, "NOsh_setupCalcMGAUTO(%s, %d):  ifocus = %d, \
01779 fixing mesh max violation (%g in %d-direction).\n", __FILE__, __LINE__, ifocus, 
01780           d[j], j);
01781       calcf->mgparm->center[j] -= d[j];
01782       dofix = 1;
01783      }
01784     }
01785    }
01786    Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  final fine mesh upper corner = \
01787 %g %g %g\n", __FILE__, __LINE__, 
01788        calcf->mgparm->center[0]+0.5*(calcf->mgparm->glen[0]), 
01789          calcf->mgparm->center[1]+0.5*(calcf->mgparm->glen[1]),
01790          calcf->mgparm->center[2]+0.5*(calcf->mgparm->glen[2]));
01791    Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  final fine mesh lower corner = \
01792 %g %g %g\n", __FILE__, __LINE__, 
01793        calcf->mgparm->center[0]-0.5*(calcf->mgparm->glen[0]), 
01794          calcf->mgparm->center[1]-0.5*(calcf->mgparm->glen[1]),
01795          calcf->mgparm->center[2]-0.5*(calcf->mgparm->glen[2]));
01796   }
01797   
01798   /* Finer levels have focusing boundary conditions */
01799   if (ifocus != 0) calcf->pbeparm->bcfl = BCFL_FOCUS;
01800   
01801   /* Only the finest level handles I/O and needs to worry about disjoint
01802    partitioning */
01803   if (ifocus != (nfocus-1)) calcf->pbeparm->numwrite = 0;
01804   
01805   /* Reset boundary flags for everything except parallel focusing */ 
01806         if (calcf->mgparm->type != MCT_PARALLEL)  {
01807    Vnm_print(0, "NOsh_setupMGAUTO:  Resetting boundary flags\n");
01808    for (j=0; j<6; j++) calcf->mgparm->partDisjOwnSide[j] = 0;
01809    for (j=0; j<3; j++) {
01810     calcf->mgparm->partDisjCenter[j] = 0;
01811     calcf->mgparm->partDisjLength[j] = calcf->mgparm->glen[j];
01812    }
01813         }
01814   
01815   
01816         calcf->mgparm->parsed = 1;
01817     }
01818  
01819  
01820     return 1;
01821 }
01822 
01823 /* Author:   Nathan Baker and Todd Dolinsky */
01824 VPUBLIC int NOsh_setupCalcMGPARA(
01825          NOsh *thee, 
01826          NOsh_calc *elec
01827          ) {
01828  
01829  /* NEW (25-Jul-2006):  This code should produce modify the ELEC statement
01830  and pass it on to MGAUTO for further processing. */
01831  
01832  MGparm *mgparm = VNULL;
01833  double ofrac;
01834  double hx, hy, hzed;
01835  double xofrac, yofrac, zofrac;
01836  int rank, size, npx, npy, npz, nproc, ip, jp, kp;
01837  int xeffGlob, yeffGlob, zeffGlob, xDisj, yDisj, zDisj;
01838  int xigminDisj, xigmaxDisj, yigminDisj, yigmaxDisj, zigminDisj, zigmaxDisj;
01839  int xigminOlap, xigmaxOlap, yigminOlap, yigmaxOlap, zigminOlap, zigmaxOlap;
01840  int xOlapReg, yOlapReg, zOlapReg;
01841  double xlenDisj, ylenDisj, zlenDisj;
01842  double xcentDisj, ycentDisj, zcentDisj;
01843  double xcentOlap, ycentOlap, zcentOlap;
01844  double xlenOlap, ylenOlap, zlenOlap;
01845  double xminOlap, xmaxOlap, yminOlap, ymaxOlap, zminOlap, zmaxOlap;
01846  double xminDisj, xmaxDisj, yminDisj, ymaxDisj, zminDisj, zmaxDisj;
01847  double xcent, ycent, zcent;
01848  
01849  /* Grab some useful variables */
01850  VASSERT(thee != VNULL);
01851  VASSERT(elec != VNULL);
01852  mgparm = elec->mgparm;
01853  VASSERT(mgparm != VNULL);
01854  
01855  /* Grab some useful variables */
01856     ofrac = mgparm->ofrac;  
01857     npx = mgparm->pdime[0]; 
01858     npy = mgparm->pdime[1]; 
01859     npz = mgparm->pdime[2]; 
01860     nproc = npx*npy*npz;
01861  
01862  /* If this is not an asynchronous calculation, then we need to make sure we
01863   have all the necessary MPI information */
01864     if (mgparm->setasync == 0) {
01865   
01866 #ifndef HAVE_MPI_H
01867   
01868         Vnm_tprint(2, "NOsh_setupCalcMGPARA:  Oops!  You're trying to perform \
01869 an 'mg-para' (parallel) calculation\n");
01870         Vnm_tprint(2, "NOsh_setupCalcMGPARA:  with a version of APBS that wasn't \
01871 compiled with MPI!\n");
01872   Vnm_tprint(2, "NOsh_setupCalcMGPARA:  Perhaps you meant to use the \
01873 'async' flag?\n");
01874         Vnm_tprint(2, "NOsh_setupCalcMGPARA:  Bailing out!\n");
01875   
01876         return 0;
01877   
01878 #endif
01879   
01880   rank = thee->proc_rank;
01881   size = thee->proc_size;
01882   Vnm_print(0, "NOsh_setupCalcMGPARA:  Hello from processor %d of %d\n", rank,
01883       size);
01884   
01885   /* Check to see if we have too many processors.  If so, then simply set
01886    this processor to duplicating the work of processor 0. */
01887   if (rank > (nproc-1)) {
01888    Vnm_print(2, "NOsh_setupMGPARA:  There are more processors available than\
01889 the %d you requested.\n", nproc);
01890    Vnm_print(2, "NOsh_setupMGPARA:  Eliminating processor %d\n", rank);
01891    thee->bogus = 1;
01892    rank = 0;
01893   }
01894   
01895   /* Check to see if we have too few processors.  If so, this is a fatal 
01896    error. */
01897   if (size < nproc) {
01898    Vnm_print(2, "NOsh_setupMGPARA:  There are too few processors (%d) to \
01899 satisfy requirements (%d)\n", size, nproc);
01900    return 0;
01901   }
01902   
01903   Vnm_print(0, "NOsh_setupMGPARA:  Hello (again) from processor %d of %d\n", 
01904       rank, size);
01905   
01906     } else { /* Setting up for an asynchronous calculation. */
01907   
01908   rank = mgparm->async;
01909   
01910   thee->ispara = 1;
01911   thee->proc_rank = rank;
01912 
01913         /* Check to see if the async id is greater than the number of
01914   * processors.  If so, this is a fatal error. */
01915         if (rank > (nproc-1)) {
01916             Vnm_print(2, "NOsh_setupMGPARA:  The processor id you requested (%d) \
01917 is not within the range of processors available (0-%d)\n", rank, (nproc-1));
01918             return 0;
01919         }
01920     }
01921  
01922     /* Calculate the processor's coordinates in the processor grid */
01923  kp = (int)floor(rank/(npx*npy));
01924  jp = (int)floor((rank-kp*npx*npy)/npx);
01925  ip = rank - kp*npx*npy - jp*npx;
01926  Vnm_print(0, "NOsh_setupMGPARA:  Hello world from PE (%d, %d, %d)\n", 
01927      ip, jp, kp);
01928  
01929  /* Calculate effective overlap fractions for uneven processor distributions */
01930  if (npx == 1) xofrac = 0.0;
01931  else xofrac = ofrac;
01932  if (npy == 1) yofrac = 0.0;
01933  else yofrac = ofrac;
01934  if (npz == 1) zofrac = 0.0;
01935  else zofrac = ofrac;
01936  
01937     /* Calculate the global grid size and spacing */
01938     xDisj = (int)VFLOOR(mgparm->dime[0]/(1 + 2*xofrac) + 0.5);
01939     xeffGlob = npx*xDisj;
01940     hx = mgparm->fglen[0]/(double)(xeffGlob-1);
01941     yDisj = (int)VFLOOR(mgparm->dime[1]/(1 + 2*yofrac) + 0.5);
01942     yeffGlob = npy*yDisj;
01943     hy = mgparm->fglen[1]/(double)(yeffGlob-1);
01944     zDisj = (int)VFLOOR(mgparm->dime[2]/(1 + 2*zofrac) + 0.5);
01945     zeffGlob = npz*zDisj;
01946     hzed = mgparm->fglen[2]/(double)(zeffGlob-1);
01947     Vnm_print(0, "NOsh_setupMGPARA:  Global Grid size = (%d, %d, %d)\n",
01948               xeffGlob, yeffGlob, zeffGlob);
01949     Vnm_print(0, "NOsh_setupMGPARA:  Global Grid Spacing = (%.3f, %.3f, %.3f)\n",
01950               hx, hy, hzed);
01951     Vnm_print(0, "NOsh_setupMGPARA:  Processor Grid Size = (%d, %d, %d)\n",
01952               xDisj, yDisj, zDisj);
01953  
01954     /* Calculate the maximum and minimum processor grid points */ 
01955     xigminDisj = ip*xDisj;
01956     xigmaxDisj = xigminDisj + xDisj - 1;
01957     yigminDisj = jp*yDisj;
01958     yigmaxDisj = yigminDisj + yDisj - 1;
01959     zigminDisj = kp*zDisj;
01960     zigmaxDisj = zigminDisj + zDisj - 1;
01961     Vnm_print(0, "NOsh_setupMGPARA:  Min Grid Points for this proc. (%d, %d, %d)\n",
01962               xigminDisj, yigminDisj, zigminDisj);
01963     Vnm_print(0, "NOsh_setupMGPARA:  Max Grid Points for this proc. (%d, %d, %d)\n",
01964               xigmaxDisj, yigmaxDisj, zigmaxDisj);
01965  
01966  
01967     /* Calculate the disjoint partition length and center displacement */
01968     xminDisj = VMAX2(hx*(xigminDisj-0.5), 0.0);
01969     xmaxDisj = VMIN2(hx*(xigmaxDisj+0.5), mgparm->fglen[0]);
01970     xlenDisj = xmaxDisj - xminDisj;
01971     yminDisj = VMAX2(hy*(yigminDisj-0.5), 0.0);
01972     ymaxDisj = VMIN2(hy*(yigmaxDisj+0.5), mgparm->fglen[1]);
01973     ylenDisj = ymaxDisj - yminDisj;
01974     zminDisj = VMAX2(hzed*(zigminDisj-0.5), 0.0);
01975     zmaxDisj = VMIN2(hzed*(zigmaxDisj+0.5), mgparm->fglen[2]);
01976     zlenDisj = zmaxDisj - zminDisj;       
01977  
01978     xcent = 0.5*mgparm->fglen[0];
01979     ycent = 0.5*mgparm->fglen[1];
01980     zcent = 0.5*mgparm->fglen[2];
01981     
01982     xcentDisj = xminDisj + 0.5*xlenDisj - xcent;
01983     ycentDisj = yminDisj + 0.5*ylenDisj - ycent;
01984     zcentDisj = zminDisj + 0.5*zlenDisj - zcent;
01985     if (VABS(xcentDisj) < VSMALL) xcentDisj = 0.0;
01986     if (VABS(ycentDisj) < VSMALL) ycentDisj = 0.0;
01987     if (VABS(zcentDisj) < VSMALL) zcentDisj = 0.0;
01988  
01989     Vnm_print(0, "NOsh_setupMGPARA:  Disj part length = (%g, %g, %g)\n", 
01990      xlenDisj, ylenDisj, zlenDisj);
01991     Vnm_print(0, "NOsh_setupMGPARA:  Disj part center displacement = (%g, %g, %g)\n", 
01992      xcentDisj, ycentDisj, zcentDisj);
01993  
01994     /* Calculate the overlapping partition length and center displacement */
01995     xOlapReg = 0;
01996     yOlapReg = 0;
01997     zOlapReg = 0;
01998     if (npx != 1) xOlapReg = (int)VFLOOR(xofrac*mgparm->fglen[0]/npx/hx + 0.5) + 1;
01999     if (npy != 1) yOlapReg = (int)VFLOOR(yofrac*mgparm->fglen[1]/npy/hy + 0.5) + 1;
02000     if (npz != 1) zOlapReg = (int)VFLOOR(zofrac*mgparm->fglen[2]/npz/hzed + 0.5) + 1;
02001  
02002     Vnm_print(0, "NOsh_setupMGPARA:  No. of Grid Points in Overlap (%d, %d, %d)\n",
02003               xOlapReg, yOlapReg, zOlapReg);
02004  
02005     if (ip == 0) xigminOlap = 0;
02006     else if (ip == (npx - 1)) xigminOlap = xeffGlob - mgparm->dime[0];
02007     else xigminOlap = xigminDisj - xOlapReg;
02008     xigmaxOlap = xigminOlap + mgparm->dime[0] - 1;
02009  
02010     if (jp == 0) yigminOlap = 0;
02011     else if (jp == (npy - 1)) yigminOlap = yeffGlob - mgparm->dime[1];
02012     else yigminOlap = yigminDisj - yOlapReg;
02013     yigmaxOlap = yigminOlap + mgparm->dime[1] - 1;
02014  
02015     if (kp == 0) zigminOlap = 0;
02016     else if (kp == (npz - 1)) zigminOlap = zeffGlob - mgparm->dime[2];
02017     else zigminOlap = zigminDisj - zOlapReg;
02018     zigmaxOlap = zigminOlap + mgparm->dime[2] - 1;
02019     
02020     Vnm_print(0, "NOsh_setupMGPARA:  Min Grid Points with Overlap (%d, %d, %d)\n",
02021               xigminOlap, yigminOlap, zigminOlap);
02022     Vnm_print(0, "NOsh_setupMGPARA:  Max Grid Points with Overlap (%d, %d, %d)\n",
02023               xigmaxOlap, yigmaxOlap, zigmaxOlap);
02024  
02025     xminOlap = hx * xigminOlap;
02026     xmaxOlap = hx * xigmaxOlap;
02027     yminOlap = hy * yigminOlap;
02028     ymaxOlap = hy * yigmaxOlap;
02029     zminOlap = hzed * zigminOlap;
02030     zmaxOlap = hzed * zigmaxOlap;
02031  
02032     xlenOlap = xmaxOlap - xminOlap;
02033     ylenOlap = ymaxOlap - yminOlap;
02034     zlenOlap = zmaxOlap - zminOlap;
02035  
02036     xcentOlap = (xminOlap + 0.5*xlenOlap) - xcent;
02037     ycentOlap = (yminOlap + 0.5*ylenOlap) - ycent;
02038     zcentOlap = (zminOlap + 0.5*zlenOlap) - zcent;
02039     if (VABS(xcentOlap) < VSMALL) xcentOlap = 0.0;
02040     if (VABS(ycentOlap) < VSMALL) ycentOlap = 0.0;
02041     if (VABS(zcentOlap) < VSMALL) zcentOlap = 0.0;
02042     
02043     Vnm_print(0, "NOsh_setupMGPARA:  Olap part length = (%g, %g, %g)\n", 
02044      xlenOlap, ylenOlap, zlenOlap);
02045     Vnm_print(0, "NOsh_setupMGPARA:  Olap part center displacement = (%g, %g, %g)\n", 
02046      xcentOlap, ycentOlap, zcentOlap);
02047  
02048  
02049     /* Calculate the boundary flags:
02050   Flags are set to 1 when another processor is present along the boundary
02051   Flags are otherwise set to 0. */
02052  
02053     if (ip == 0) mgparm->partDisjOwnSide[VAPBS_LEFT] = 0;
02054  else mgparm->partDisjOwnSide[VAPBS_LEFT] = 1;
02055  if (ip == (npx-1)) mgparm->partDisjOwnSide[VAPBS_RIGHT] = 0;
02056  else mgparm->partDisjOwnSide[VAPBS_RIGHT] = 1;
02057  if (jp == 0) mgparm->partDisjOwnSide[VAPBS_BACK] = 0;
02058  else mgparm->partDisjOwnSide[VAPBS_BACK] = 1;
02059  if (jp == (npy-1)) mgparm->partDisjOwnSide[VAPBS_FRONT] = 0;
02060  else mgparm->partDisjOwnSide[VAPBS_FRONT] = 1;
02061  if (kp == 0) mgparm->partDisjOwnSide[VAPBS_DOWN] = 0;
02062  else mgparm->partDisjOwnSide[VAPBS_DOWN] = 1;
02063  if (kp == (npz-1)) mgparm->partDisjOwnSide[VAPBS_UP] = 0;
02064  else mgparm->partDisjOwnSide[VAPBS_UP] = 1;       
02065  
02066  Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[LEFT] = %d\n", 
02067      mgparm->partDisjOwnSide[VAPBS_LEFT]);
02068  Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[RIGHT] = %d\n", 
02069      mgparm->partDisjOwnSide[VAPBS_RIGHT]);
02070  Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[FRONT] = %d\n", 
02071      mgparm->partDisjOwnSide[VAPBS_FRONT]);
02072  Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[BACK] = %d\n", 
02073      mgparm->partDisjOwnSide[VAPBS_BACK]);
02074  Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[UP] = %d\n", 
02075      mgparm->partDisjOwnSide[VAPBS_UP]);
02076  Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[DOWN] = %d\n", 
02077      mgparm->partDisjOwnSide[VAPBS_DOWN]);
02078  
02079  /* Set the mesh parameters */ 
02080  mgparm->fglen[0] = xlenOlap;
02081  mgparm->fglen[1] = ylenOlap;
02082  mgparm->fglen[2] = zlenOlap;
02083  mgparm->partDisjLength[0] = xlenDisj;
02084  mgparm->partDisjLength[1] = ylenDisj;
02085  mgparm->partDisjLength[2] = zlenDisj;
02086  mgparm->partDisjCenter[0] = mgparm->fcenter[0] + xcentDisj;
02087  mgparm->partDisjCenter[1] = mgparm->fcenter[1] + ycentDisj;
02088  mgparm->partDisjCenter[2] = mgparm->fcenter[2] + zcentDisj;
02089  mgparm->fcenter[0] += xcentOlap;
02090  mgparm->fcenter[1] += ycentOlap;
02091  mgparm->fcenter[2] += zcentOlap;
02092  
02093  Vnm_print(0, "NOsh_setupCalcMGPARA (%s, %d):  Set up *relative* partition \
02094 centers...\n", __FILE__, __LINE__);
02095  Vnm_print(0, "NOsh_setupCalcMGPARA (%s, %d):  Absolute centers will be set \
02096 in  NOsh_setupMGAUTO\n", __FILE__, __LINE__);
02097  Vnm_print(0, "NOsh_setupCalcMGPARA (%s, %d):  partDisjCenter = %g %g %g\n",
02098      __FILE__, __LINE__,
02099      mgparm->partDisjCenter[0],
02100      mgparm->partDisjCenter[1],
02101      mgparm->partDisjCenter[2]);
02102  Vnm_print(0, "NOsh_setupCalcMGPARA (%s, %d):  ccenter = %g %g %g\n",
02103      __FILE__, __LINE__,
02104      mgparm->ccenter[0],
02105      mgparm->ccenter[1],
02106      mgparm->ccenter[2]);
02107  Vnm_print(0, "NOsh_setupCalcMGPARA (%s, %d):  fcenter = %g %g %g\n",
02108      __FILE__, __LINE__,
02109      mgparm->fcenter[0],
02110      mgparm->fcenter[1],
02111      mgparm->fcenter[2]);
02112      
02113  
02114  /* Setup the automatic focusing calculations associated with this processor */
02115  return NOsh_setupCalcMGAUTO(thee, elec);
02116 
02117 }
02118 
02119 VPUBLIC int NOsh_parseFEM(
02120         NOsh *thee, 
02121         Vio *sock, 
02122         NOsh_calc *elec
02123         ) {
02124  
02125  char tok[VMAX_BUFSIZE];
02126  FEMparm *feparm = VNULL;    
02127  PBEparm *pbeparm = VNULL;    
02128  int rc;
02129  Vrc_Codes vrc;
02130  
02131  /* Check the arguments */
02132  if (thee == VNULL) {
02133   Vnm_print(2, "NOsh_parseFEM:  Got NULL thee!\n");
02134   return 0;
02135  }
02136  if (sock == VNULL) {
02137   Vnm_print(2, "NOsh_parseFEM:  Got pointer to NULL socket!\n");
02138   return 0;
02139  }
02140  if (elec == VNULL) {
02141   Vnm_print(2, "NOsh_parseFEM:  Got pointer to NULL elec object!\n");
02142   return 0;
02143  }
02144  feparm = elec->femparm;
02145  if (feparm == VNULL) {
02146   Vnm_print(2, "NOsh_parseFEM:  Got pointer to NULL feparm object!\n");
02147   return 0;
02148  }
02149  pbeparm = elec->pbeparm;
02150  if (feparm == VNULL) {
02151   Vnm_print(2, "NOsh_parseFEM:  Got pointer to NULL pbeparm object!\n");
02152   return 0;
02153  }
02154  
02155  Vnm_print(0, "NOsh_parseFEM: Parsing parameters for FEM calculation\n");
02156 
02157  /* Start snarfing tokens from the input stream */
02158  rc = 1;
02159  while (Vio_scanf(sock, "%s", tok) == 1) { 
02160   
02161   Vnm_print(0, "NOsh_parseFEM:  Parsing %s...\n", tok);
02162   
02163   /* See if it's an END token */
02164   if (Vstring_strcasecmp(tok, "end") == 0) {
02165    feparm->parsed = 1;
02166    pbeparm->parsed = 1;
02167    rc = 1;
02168    break;
02169   }
02170   
02171   /* Pass the token through a series of parsers */
02172   rc = PBEparm_parseToken(pbeparm, tok, sock);
02173   if (rc == -1) {
02174    Vnm_print(0, "NOsh_parseFEM:  parsePBE error!\n");
02175    break;
02176   } else if (rc == 0) {
02177    /* Pass the token to the generic MG parser */
02178    vrc = FEMparm_parseToken(feparm, tok, sock);
02179    if (vrc == VRC_FAILURE) { 
02180     Vnm_print(0, "NOsh_parseFEM:  parseMG error!\n");
02181     break;
02182    } else if (vrc == VRC_WARNING) {
02183     /* We ran out of parsers! */
02184     Vnm_print(2, "NOsh:  Unrecognized keyword: %s\n", tok);
02185     break;
02186    }
02187   }
02188  }
02189  
02190  /* Handle various errors arising in the token-snarfing loop -- these all
02191   * just result in simple returns right now */
02192  if (rc == -1) return 0;
02193  if (rc == 0) return 0;
02194  
02195  /* Check the status of the parameter objects */
02196  if ((!FEMparm_check(feparm)) || (!PBEparm_check(pbeparm))) {
02197   Vnm_print(2, "NOsh:  FEM parameters not set correctly!\n");
02198   return 0;
02199  }
02200  
02201  return 1;
02202  
02203 }
02204 
02205 VPRIVATE int NOsh_setupCalcFEMANUAL(
02206            NOsh *thee, 
02207            NOsh_calc *elec
02208            ) {
02209  
02210  FEMparm *feparm = VNULL;
02211  PBEparm *pbeparm = VNULL;
02212  NOsh_calc *calc = VNULL;
02213  
02214  VASSERT(thee != VNULL);
02215  VASSERT(elec != VNULL);
02216  feparm = elec->femparm;
02217  VASSERT(feparm != VNULL);
02218  pbeparm = elec->pbeparm;
02219  VASSERT(pbeparm);
02220  
02221  /* Check to see if he have any room left for this type of
02222   * calculation, if so: set the calculation type, update the number
02223   * of calculations of this type, and parse the rest of the section
02224   */
02225  if (thee->ncalc >= NOSH_MAXCALC) {
02226   Vnm_print(2, "NOsh:  Too many calculations in this run!\n");
02227   Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
02228       NOSH_MAXCALC);
02229   return 0;
02230  }
02231  thee->calc[thee->ncalc] = NOsh_calc_ctor(NCT_FEM);
02232  calc = thee->calc[thee->ncalc];
02233  (thee->ncalc)++;
02234  
02235  /* Copy over contents of ELEC */
02236  NOsh_calc_copy(calc, elec);
02237  
02238  
02239  return 1;
02240 }
02241 
02242 VPUBLIC int NOsh_parseAPOL(
02243         NOsh *thee, 
02244         Vio *sock, 
02245         NOsh_calc *elec
02246         ) {
02247  
02248  char tok[VMAX_BUFSIZE];
02249  APOLparm *apolparm = VNULL;   
02250  int rc;
02251  
02252  /* Check the arguments */
02253  if (thee == VNULL) {
02254   Vnm_print(2, "NOsh_parseAPOL:  Got NULL thee!\n");
02255   return 0;
02256  }
02257  if (sock == VNULL) {
02258   Vnm_print(2, "NOsh_parseAPOL:  Got pointer to NULL socket!\n");
02259   return 0;
02260  }
02261  if (elec == VNULL) {
02262   Vnm_print(2, "NOsh_parseAPOL:  Got pointer to NULL elec object!\n");
02263   return 0;
02264  }
02265  apolparm = elec->apolparm;
02266  if (apolparm == VNULL) {
02267   Vnm_print(2, "NOsh_parseAPOL:  Got pointer to NULL feparm object!\n");
02268   return 0;
02269  }
02270  
02271  Vnm_print(0, "NOsh_parseAPOL: Parsing parameters for APOL calculation\n");
02272  
02273  /* Start snarfing tokens from the input stream */
02274  rc = 1;
02275  while (Vio_scanf(sock, "%s", tok) == 1) { 
02276   
02277   Vnm_print(0, "NOsh_parseAPOL:  Parsing %s...\n", tok);
02278   /* See if it's an END token */
02279   if (Vstring_strcasecmp(tok, "end") == 0) {
02280    apolparm->parsed = 1;
02281    rc = 1;
02282    break;
02283   }
02284   
02285   /* Pass the token through a series of parsers */
02286   /* Pass the token to the generic non-polar parser */
02287   rc = APOLparm_parseToken(apolparm, tok, sock);
02288   if (rc == -1) { 
02289    Vnm_print(0, "NOsh_parseFEM:  parseMG error!\n");
02290    break;
02291   } else if (rc == 0) {
02292    /* We ran out of parsers! */
02293    Vnm_print(2, "NOsh:  Unrecognized keyword: %s\n", tok);
02294    break;
02295   }
02296   
02297  }
02298  
02299  /* Handle various errors arising in the token-snarfing loop -- these all
02300   * just result in simple returns right now */
02301  if (rc == -1) return 0;
02302  if (rc == 0) return 0;
02303  
02304  /* Check the status of the parameter objects */
02305  if (!APOLparm_check(apolparm)) {
02306   Vnm_print(2, "NOsh:  APOL parameters not set correctly!\n");
02307   return 0;
02308  }
02309  
02310  return 1;
02311  
02312 }
02313 
02314 VPRIVATE int NOsh_setupCalcAPOL(
02315         NOsh *thee, 
02316         NOsh_calc *apol
02317         ) {
02318  
02319  NOsh_calc *calc = VNULL;
02320   
02321  VASSERT(thee != VNULL);
02322  VASSERT(apol != VNULL);
02323  
02324  /* Check to see if he have any room left for this type of
02325   * calculation, if so: set the calculation type, update the number
02326   * of calculations of this type, and parse the rest of the section
02327   */
02328  if (thee->ncalc >= NOSH_MAXCALC) {
02329   Vnm_print(2, "NOsh:  Too many calculations in this run!\n");
02330   Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
02331       NOSH_MAXCALC);
02332   return 0;
02333  }
02334  thee->calc[thee->ncalc] = NOsh_calc_ctor(NCT_APOL);
02335  calc = thee->calc[thee->ncalc];
02336  (thee->ncalc)++;
02337  
02338  /* Copy over contents of APOL */
02339  NOsh_calc_copy(calc, apol); 
02340  
02341  return 1;
02342 }

Generated on Wed Oct 20 2010 12:01:33 for APBS by  doxygen 1.7.2