text: /**
   *  @file    pbeparm.c
   *  @ingroup PBEparm
   *  @author  Nathan Baker
   *  @brief   Class PBEparm methods
   *  @version $Id$
   *  @attention
   *  @verbatim
   *
   * APBS -- Adaptive Poisson-Boltzmann Solver
   *
   *  Nathan A. Baker (nathan.baker@pnnl.gov)
   *  Pacific Northwest National Laboratory
   *
   *  Additional contributing authors listed in the code documentation.
   *
   * Copyright (c) 2010-2020 Battelle Memorial Institute. Developed at the
   * Pacific Northwest National Laboratory, operated by Battelle Memorial
   * Institute, Pacific Northwest Division for the U.S. Department of Energy.
   *
   * Portions Copyright (c) 2002-2010, Washington University in St. Louis.
   * Portions Copyright (c) 2002-2020, Nathan A. Baker.
   * Portions Copyright (c) 1999-2002, The Regents of the University of
   * California.
   * Portions Copyright (c) 1995, Michael Holst.
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   * Redistributions of source code must retain the above copyright notice, this
   * list of conditions and the following disclaimer.
   *
   * Redistributions in binary form must reproduce the above copyright notice,
   * this list of conditions and the following disclaimer in the documentation
   * and/or other materials provided with the distribution.
   *
   * Neither the name of the developer nor the names of its contributors may be
   * used to endorse or promote products derived from this software without
   * specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   * THE POSSIBILITY OF SUCH DAMAGE.
   *
   * @endverbatim
   */
  
  #include "pbeparm.h"
  
  VEMBED(rcsid="$Id$")
  
  #if !defined(VINLINE_MGPARM)
  
  #endif /* if !defined(VINLINE_MGPARM) */
  
  VPUBLIC double PBEparm_getIonCharge(PBEparm *thee, int i) {
      VASSERT(thee != VNULL);
      VASSERT(i < thee->nion);
      return thee->ionq[i];
  }
  
  VPUBLIC double PBEparm_getIonConc(PBEparm *thee, int i) {
      VASSERT(thee != VNULL);
      VASSERT(i < thee->nion);
      return thee->ionc[i];
  }
  
  VPUBLIC double PBEparm_getIonRadius(PBEparm *thee, int i) {
      VASSERT(thee != VNULL);
      VASSERT(i < thee->nion);
      return thee->ionr[i];
  }
  
  /*----------------------------------------------------------------------*/
  /* Added by Michael Grabe                                               */
  /*----------------------------------------------------------------------*/
  
  VPUBLIC double PBEparm_getzmem(PBEparm *thee) {
      VASSERT(thee != VNULL);
      return thee->zmem;
  }
  VPUBLIC double PBEparm_getLmem(PBEparm *thee) {
      VASSERT(thee != VNULL);
      return thee->Lmem;
  }
  VPUBLIC double PBEparm_getmembraneDiel(PBEparm *thee) {
      VASSERT(thee != VNULL);
      return thee->mdie;
  }
  VPUBLIC double PBEparm_getmemv(PBEparm *thee) {
      VASSERT(thee != VNULL);
      return thee->memv;
  }
  
  VPUBLIC PBEparm* PBEparm_ctor() {
  
      /* Set up the structure */
      PBEparm *thee = VNULL;
      thee = (PBEparm*)Vmem_malloc(VNULL, 1, sizeof(PBEparm));
      VASSERT( thee != VNULL);
      VASSERT( PBEparm_ctor2(thee) );
  
      return thee;
  }
  
  VPUBLIC int PBEparm_ctor2(PBEparm *thee) {
  
      int i;
  
      if (thee == VNULL) return 0;
  
      thee->parsed = 0;
  
      thee->setmolid = 0;
      thee->setpbetype = 0;
      thee->setbcfl = 0;
      thee->setnion = 0;
      for (i=0; i<MAXION; i++){
          thee->setion[i] = 0;
          thee->ionq[i] = 0.0;
          thee->ionc[i] = 0.0;
          thee->ionr[i] = 0.0;
      }
      thee->setpdie = 0;
      thee->setsdie = 0;
      thee->setsrfm = 0;
      thee->setsrad = 0;
      thee->setswin = 0;
      thee->settemp = 0;
      thee->setcalcenergy = 0;
      thee->setcalcforce = 0;
      thee->setsdens = 0;
      thee->numwrite = 0;
      thee->setwritemat = 0;
      thee->nion = 0;
      thee->sdens = 0;
      thee->swin = 0;
      thee->srad = 1.4;
      thee->useDielMap = 0;
      thee->useKappaMap = 0;
      thee->usePotMap = 0;
      thee->useChargeMap = 0;
  
      /*----------------------------------------------*/
      /* Added by Michael Grabe                       */
      /*----------------------------------------------*/
  
      thee->setzmem = 0;
      thee->setLmem = 0;
      thee->setmdie = 0;
      thee->setmemv = 0;
  
      /*----------------------------------------------*/
  
      thee->smsize = 0.0;
      thee->smvolume = 0.0;
  
      thee->setsmsize = 0;
      thee->setsmvolume = 0;
  
      return 1;
  }
  
  VPUBLIC void PBEparm_dtor(PBEparm **thee) {
      if ((*thee) != VNULL) {
          PBEparm_dtor2(*thee);
          Vmem_free(VNULL, 1, sizeof(PBEparm), (void **)thee);
          (*thee) = VNULL;
      }
  }
  
  VPUBLIC void PBEparm_dtor2(PBEparm *thee) { ; }
  
  VPUBLIC int PBEparm_check(PBEparm *thee) {
  
      int i;
  
      /* Check to see if we were even filled... */
      if (!thee->parsed) {
          Vnm_print(2, "PBEparm_check:  not filled!\n");
          return 0;
      }
  
      if (!thee->setmolid) {
          Vnm_print(2, "PBEparm_check:  MOL not set!\n");
          return 0;
      }
      if (!thee->setpbetype) {
          Vnm_print(2, "PBEparm_check:  LPBE/NPBE/LRPBE/NRPBE/SMPBE not set!\n");
          return 0;
      }
      if (!thee->setbcfl) {
          Vnm_print(2, "PBEparm_check:  BCFL not set!\n");
          return 0;
      }
      if (!thee->setnion) {
          thee->setnion = 1;
          thee->nion = 0;
      }
      for (i=0; i<thee->nion; i++) {
          if (!thee->setion[i]) {
              Vnm_print(2, "PBEparm_check: ION #%d not set!\n",i);
              return 0;
          }
      }
      if (!thee->setpdie) {
          Vnm_print(2, "PBEparm_check: PDIE not set!\n");
          return 0;
      }
      if (((thee->srfm==VSM_MOL) || (thee->srfm==VSM_MOLSMOOTH)) \
        && (!thee->setsdens) && (thee->srad > VSMALL)) {
          Vnm_print(2, "PBEparm_check: SDENS not set!\n");
          return 0;
      }
      if (!thee->setsdie) {
          Vnm_print(2, "PBEparm_check: SDIE not set!\n");
          return 0;
      }
      if (!thee->setsrfm) {
          Vnm_print(2, "PBEparm_check: SRFM not set!\n");
          return 0;
      }
      if (((thee->srfm==VSM_MOL) || (thee->srfm==VSM_MOLSMOOTH)) \
        && (!thee->setsrad)) {
          Vnm_print(2, "PBEparm_check: SRAD not set!\n");
          return 0;
      }
      if ((thee->srfm==VSM_SPLINE) && (!thee->setswin)) {
          Vnm_print(2, "PBEparm_check: SWIN not set!\n");
          return 0;
      }
      if ((thee->srfm==VSM_SPLINE3) && (!thee->setswin)) {
          Vnm_print(2, "PBEparm_check: SWIN not set!\n");
          return 0;
      }
      if ((thee->srfm==VSM_SPLINE4) && (!thee->setswin)) {
          Vnm_print(2, "PBEparm_check: SWIN not set!\n");
          return 0;
      }
      if (!thee->settemp) {
          Vnm_print(2, "PBEparm_check: TEMP not set!\n");
          return 0;
      }
      if (!thee->setcalcenergy) thee->calcenergy = PCE_NO;
      if (!thee->setcalcforce) thee->calcforce = PCF_NO;
      if (!thee->setwritemat) thee->writemat = 0;
  
      /*--------------------------------------------------------*/
      /* Added by Michael Grabe                                 */
      /*--------------------------------------------------------*/
  
      if ((!thee->setzmem) && (thee->bcfl == 3)){
          Vnm_print(2, "PBEparm_check: ZMEM not set!\n");
          return 0;
      }
      if ((!thee->setLmem) && (thee->bcfl == 3)){
          Vnm_print(2, "PBEparm_check: LMEM not set!\n");
          return 0;
      }
      if ((!thee->setmdie) && (thee->bcfl == 3)){
          Vnm_print(2, "PBEparm_check: MDIE not set!\n");
          return 0;
      }
      if ((!thee->setmemv) && (thee->bcfl == 3)){
          Vnm_print(2, "PBEparm_check: MEMV not set!\n");
          return 0;
      }
  
      /*--------------------------------------------------------*/
  
      return 1;
  }
  
  VPUBLIC void PBEparm_copy(PBEparm *thee, PBEparm *parm) {
  
      int i, j;
  
      VASSERT(thee != VNULL);
      VASSERT(parm != VNULL);
  
      thee->molid = parm->molid;
      thee->setmolid = parm->setmolid;
      thee->useDielMap = parm->useDielMap;
      thee->dielMapID = parm->dielMapID;
      thee->useKappaMap = parm->useKappaMap;
      thee->kappaMapID = parm->kappaMapID;
      thee->usePotMap = parm->usePotMap;
      thee->potMapID = parm->potMapID;
      thee->useChargeMap = parm->useChargeMap;
      thee->chargeMapID = parm->chargeMapID;
      thee->pbetype = parm->pbetype;
      thee->setpbetype = parm->setpbetype;
      thee->bcfl = parm->bcfl;
      thee->setbcfl = parm->setbcfl;
      thee->nion = parm->nion;
      thee->setnion = parm->setnion;
      for (i=0; i<MAXION; i++) {
          thee->ionq[i] = parm->ionq[i];
          thee->ionc[i] = parm->ionc[i];
          thee->ionr[i] = parm->ionr[i];
          thee->setion[i] = parm->setion[i];
      };
      thee->pdie = parm->pdie;
      thee->setpdie = parm->setpdie;
      thee->sdens = parm->sdens;
      thee->setsdens = parm->setsdens;
      thee->sdie = parm->sdie;
      thee->setsdie = parm->setsdie;
      thee->srfm = parm->srfm;
      thee->setsrfm = parm->setsrfm;
      thee->srad = parm->srad;
      thee->setsrad = parm->setsrad;
      thee->swin = parm->swin;
      thee->setswin = parm->setswin;
      thee->temp = parm->temp;
      thee->settemp = parm->settemp;
      thee->calcenergy = parm->calcenergy;
      thee->setcalcenergy = parm->setcalcenergy;
      thee->calcforce = parm->calcforce;
      thee->setcalcforce = parm->setcalcforce;
  
      /*----------------------------------------------------*/
      /* Added by Michael Grabe                             */
      /*----------------------------------------------------*/
  
      thee->zmem = parm->zmem;
      thee->setzmem = parm->setzmem;
      thee->Lmem = parm->Lmem;
      thee->setLmem = parm->setLmem;
      thee->mdie = parm->mdie;
      thee->setmdie = parm->setmdie;
      thee->memv = parm->memv;
      thee->setmemv = parm->setmemv;
  
      /*----------------------------------------------------*/
  
      thee->numwrite = parm->numwrite;
      for (i=0; i<PBEPARM_MAXWRITE; i++) {
          thee->writetype[i] = parm->writetype[i];
          thee->writefmt[i] = parm->writefmt[i];
          for (j=0; j<VMAX_ARGLEN; j++)
            thee->writestem[i][j] = parm->writestem[i][j];
      }
      thee->writemat = parm->writemat;
      thee->setwritemat = parm->setwritemat;
      for (i=0; i<VMAX_ARGLEN; i++) thee->writematstem[i] = parm->writematstem[i];
      thee->writematflag = parm->writematflag;
  
      thee->smsize = parm->smsize;
      thee->smvolume = parm->smvolume;
  
      thee->setsmsize = parm->setsmsize;
      thee->setsmvolume = parm->setsmvolume;
  
      thee->parsed = parm->parsed;
  
  }
  
  VPRIVATE int PBEparm_parseLPBE(PBEparm *thee, Vio *sock) {
      Vnm_print(0, "NOsh: parsed lpbe\n");
      thee->pbetype = PBE_LPBE;
      thee->setpbetype = 1;
      return 1;
  }
  
  VPRIVATE int PBEparm_parseNPBE(PBEparm *thee, Vio *sock) {
      Vnm_print(0, "NOsh: parsed npbe\n");
      thee->pbetype = PBE_NPBE;
      thee->setpbetype = 1;
      return 1;
  }
  
  VPRIVATE int PBEparm_parseMOL(PBEparm *thee, Vio *sock) {
      int ti;
      char tok[VMAX_BUFSIZE];
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (sscanf(tok, "%d", &ti) == 0) {
          Vnm_print(2, "NOsh:  Read non-int (%s) while parsing MOL \
  keyword!\n", tok);
          return -1;
      }
      thee->molid = ti;
      thee->setmolid = 1;
      return 1;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseLRPBE(PBEparm *thee, Vio *sock) {
      Vnm_print(0, "NOsh: parsed lrpbe\n");
      thee->pbetype = PBE_LRPBE;
      thee->setpbetype = 1;
      return 1;
  }
  
  VPRIVATE int PBEparm_parseNRPBE(PBEparm *thee, Vio *sock) {
      Vnm_print(0, "NOsh: parsed nrpbe\n");
      thee->pbetype = PBE_NRPBE;
      thee->setpbetype = 1;
      return 1;
  }
  
  VPRIVATE int PBEparm_parseSMPBE(PBEparm *thee, Vio *sock) {
  
      int i;
  
      char type[VMAX_BUFSIZE]; /* vol or size (keywords) */
      char value[VMAX_BUFSIZE]; /* floating point value */
  
      char setVol = 1;
      char setSize = 1;
      char keyValuePairs = 2;
  
      double size, volume;
  
      for(i=0;i<keyValuePairs;i++){
  
          /* The line two tokens at a time */
          VJMPERR1(Vio_scanf(sock, "%s", type) == 1);
          VJMPERR1(Vio_scanf(sock, "%s", value) == 1);
  
          if(!strcmp(type,"vol")){
              if ((setVol = sscanf(value, "%lf", &volume)) == 0){
                  Vnm_print(2,"NOsh:  Read non-float (%s) while parsing smpbe keyword!\n", value);
                  return VRC_FAILURE;
              }
          }else if(!strcmp(type,"size")){
              if ((setSize = sscanf(value, "%lf", &size)) == 0){
                  Vnm_print(2,"NOsh:  Read non-float (%s) while parsing smpbe keyword!\n", value);
                  return VRC_FAILURE;
              }
          }else{
              Vnm_print(2,"NOsh:  Read non-float (%s) while parsing smpbe keyword!\n", value);
              return VRC_FAILURE;
          }
      }
  
      /* If either the volume or size isn't set, throw an error */
      if((setVol == 0) || (setSize == 0)){
          Vnm_print(2,"NOsh:  Error while parsing smpbe keywords! Only size or vol was specified.\n");
          return VRC_FAILURE;
      }
  
      Vnm_print(0, "NOsh: parsed smpbe\n");
      thee->pbetype = PBE_SMPBE;
      thee->setpbetype = 1;
  
      thee->smsize = size;
      thee->setsmsize = 1;
  
      thee->smvolume = volume;
      thee->setsmvolume = 1;
  
      return VRC_SUCCESS;
  
  VERROR1:
      Vnm_print(2, "parsePBE:  ran out of tokens!\n");
      return VRC_FAILURE;
  
  }
  
  VPRIVATE int PBEparm_parseBCFL(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      int ti;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
  
      /* We can either parse int flag... */
      if (sscanf(tok, "%d", &ti) == 1) {
  
          thee->bcfl = (Vbcfl)ti;
          thee->setbcfl = 1;
          /* Warn that this usage is deprecated */
          Vnm_print(2, "parsePBE:  Warning -- parsed deprecated \"bcfl %d\" \
  statement\n", ti);
          Vnm_print(2, "parsePBE:  Please use \"bcfl ");
          switch (thee->bcfl) {
              case BCFL_ZERO:
                  Vnm_print(2, "zero");
                  break;
              case BCFL_SDH:
                  Vnm_print(2, "sdh");
                  break;
              case BCFL_MDH:
                  Vnm_print(2, "mdh");
                  break;
              case BCFL_FOCUS:
                  Vnm_print(2, "focus");
                  break;
              case BCFL_MEM:
                  Vnm_print(2, "mem");
                  break;
              case BCFL_MAP:
                  Vnm_print(2, "map");
                  break;
              default:
                  Vnm_print(2, "UKNOWN");
                  break;
          }
          Vnm_print(2, "\" instead.\n");
          return 1;
  
      /* ...or the word */
      } else {
  
          if (Vstring_strcasecmp(tok, "zero") == 0) {
              thee->bcfl = BCFL_ZERO;
              thee->setbcfl = 1;
              return 1;
          } else if (Vstring_strcasecmp(tok, "sdh") == 0) {
              thee->bcfl = BCFL_SDH;
              thee->setbcfl = 1;
              return 1;
          } else if (Vstring_strcasecmp(tok, "mdh") == 0) {
              thee->bcfl = BCFL_MDH;
              thee->setbcfl = 1;
              return 1;
          } else if (Vstring_strcasecmp(tok, "focus") == 0) {
              thee->bcfl = BCFL_FOCUS;
              thee->setbcfl = 1;
              return 1;
          } else if (Vstring_strcasecmp(tok, "mem") == 0) {
              thee->bcfl = BCFL_MEM;
              thee->setbcfl = 1;
              return 1;
          } else if (Vstring_strcasecmp(tok, "map") == 0) {
              thee->bcfl = BCFL_MAP;
              thee->setbcfl = 1;
              return 1;
          } else {
              Vnm_print(2, "NOsh:  parsed unknown BCFL parameter (%s)!\n",
                tok);
              return -1;
          }
      }
      return 0;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseION(PBEparm *thee, Vio *sock) {
  
      int i;
      int meth = 0;
  
      char tok[VMAX_BUFSIZE];
      char value[VMAX_BUFSIZE];
  
      double tf;
      double charge, conc, radius;
  
      int setCharge = 0;
      int setConc = 0;
      int setRadius = 0;
      int keyValuePairs = 3;
  
      /* Get the initial token for the ION statement */
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
  
      /* Scan the token once to determine the type (old style or new keyValue pair) */
      meth = sscanf(tok, "%lf", &tf);
      /* If tok is a non-zero float value, we are using the old method */
      if(meth != 0){
  
          Vnm_print(2, "NOsh:  Deprecated use of ION keyword! Use key-value pairs\n", tok);
  
          if (sscanf(tok, "%lf", &tf) == 0) {
              Vnm_print(2, "NOsh:  Read non-float (%s) while parsing ION keyword!\n", tok);
              return VRC_FAILURE;
          }
          thee->ionq[thee->nion] = tf;
          VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
          if (sscanf(tok, "%lf", &tf) == 0) {
              Vnm_print(2, "NOsh:  Read non-float (%s) while parsing ION keyword!\n", tok);
              return VRC_FAILURE;
          }
          thee->ionc[thee->nion] = tf;
          VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
          if (sscanf(tok, "%lf", &tf) == 0) {
              Vnm_print(2, "NOsh:  Read non-float (%s) while parsing ION keyword!\n", tok);
              return VRC_FAILURE;
          }
          thee->ionr[thee->nion] = tf;
  
      }else{
  
          /* Three key-value pairs (charge, radius and conc) */
          for(i=0;i<keyValuePairs;i++){
  
              /* Now scan for the value (float) to be used with the key token parsed
               * above the if-else statement */
              VJMPERR1(Vio_scanf(sock, "%s", value) == 1);
              if(!strcmp(tok,"charge")){
                  setCharge = sscanf(value, "%lf", &charge);
                  if (setCharge == 0){
                      Vnm_print(2,"NOsh:  Read non-float (%s) while parsing ION %s keyword!\n", value, tok);
                      return VRC_FAILURE;
                  }
                  thee->ionq[thee->nion] = charge;
              }else if(!strcmp(tok,"radius")){
                  setRadius = sscanf(value, "%lf", &radius);
                  if (setRadius == 0){
                      Vnm_print(2,"NOsh:  Read non-float (%s) while parsing ION %s keyword!\n", value, tok);
                      return VRC_FAILURE;
                  }
                  thee->ionr[thee->nion] = radius;
              }else if(!strcmp(tok,"conc")){
                  setConc = sscanf(value, "%lf", &conc);
                  if (setConc == 0){
                      Vnm_print(2,"NOsh:  Read non-float (%s) while parsing ION %s keyword!\n", value, tok);
                      return VRC_FAILURE;
                  }
                  thee->ionc[thee->nion] = conc;
              }else{
                  Vnm_print(2,"NOsh:  Illegal or missing key-value pair for ION keyword!\n");
                  return VRC_FAILURE;
              }
  
              /* If all three values haven't be set (setValue = 0) then read the next token */
              if((setCharge != 1) || (setConc != 1) || (setRadius != 1)){
                  VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
              }
  
          } /* end for */
      } /* end if */
  
      /* Finally set the setion, nion and setnion flags and return success */
      thee->setion[thee->nion] = 1;
      (thee->nion)++;
      thee->setnion = 1;
      return VRC_SUCCESS;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return VRC_FAILURE;
  }
  
  VPRIVATE int PBEparm_parsePDIE(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      double tf;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (sscanf(tok, "%lf", &tf) == 0) {
          Vnm_print(2, "NOsh:  Read non-float (%s) while parsing PDIE \
  keyword!\n", tok);
          return -1;
      }
      thee->pdie = tf;
      thee->setpdie = 1;
      return 1;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseSDENS(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      double tf;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (sscanf(tok, "%lf", &tf) == 0) {
          Vnm_print(2, "NOsh:  Read non-float (%s) while parsing SDENS \
  keyword!\n", tok);
          return -1;
      }
      thee->sdens = tf;
      thee->setsdens = 1;
      return 1;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseSDIE(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      double tf;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (sscanf(tok, "%lf", &tf) == 0) {
          Vnm_print(2, "NOsh:  Read non-float (%s) while parsing SDIE \
  keyword!\n", tok);
          return -1;
      }
      thee->sdie = tf;
      thee->setsdie = 1;
      return 1;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseSRFM(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      int ti;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
  
      /* Parse old-style int arg */
      if (sscanf(tok, "%d", &ti) == 1) {
          thee->srfm = (Vsurf_Meth)ti;
          thee->setsrfm = 1;
  
          Vnm_print(2, "parsePBE:  Warning -- parsed deprecated \"srfm %d\" \
  statement.\n", ti);
          Vnm_print(2, "parsePBE:  Please use \"srfm ");
          switch (thee->srfm) {
              case VSM_MOL:
                  Vnm_print(2, "mol");
                  break;
              case VSM_MOLSMOOTH:
                  Vnm_print(2, "smol");
                  break;
              case VSM_SPLINE:
                  Vnm_print(2, "spl2");
                  break;
              case VSM_SPLINE3:
                  Vnm_print(2, "spl3");
                  break;
              case VSM_SPLINE4:
                  Vnm_print(2, "spl4");
                  break;
              default:
                  Vnm_print(2, "UNKNOWN");
                  break;
          }
          Vnm_print(2, "\" instead.\n");
          return 1;
  
      /* Parse newer text-based args */
      } else if (Vstring_strcasecmp(tok, "mol") == 0) {
          thee->srfm = VSM_MOL;
          thee->setsrfm = 1;
          return 1;
      } else if (Vstring_strcasecmp(tok, "smol") == 0) {
          thee->srfm = VSM_MOLSMOOTH;
          thee->setsrfm = 1;
          return 1;
      } else if (Vstring_strcasecmp(tok, "spl2") == 0) {
          thee->srfm = VSM_SPLINE;
          thee->setsrfm = 1;
          return 1;
      } else if (Vstring_strcasecmp(tok, "spl3") == 0) {
          thee->srfm = VSM_SPLINE3;
          thee->setsrfm = 1;
          return 1;
      } else if (Vstring_strcasecmp(tok, "spl4") == 0) {
          thee->srfm = VSM_SPLINE4;
          thee->setsrfm = 1;
          return 1;
      } else {
          Vnm_print(2, "NOsh:  Unrecongnized keyword (%s) when parsing \
  srfm!\n", tok);
          return -1;
      }
  
      return 0;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseSRAD(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      double tf;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (sscanf(tok, "%lf", &tf) == 0) {
          Vnm_print(2, "NOsh:  Read non-float (%s) while parsing SRAD \
  keyword!\n", tok);
          return -1;
      }
      thee->srad = tf;
      thee->setsrad = 1;
      return 1;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseSWIN(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      double tf;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (sscanf(tok, "%lf", &tf) == 0) {
          Vnm_print(2, "NOsh:  Read non-float (%s) while parsing SWIN \
  keyword!\n", tok);
          return -1;
      }
      thee->swin = tf;
      thee->setswin = 1;
      return 1;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseTEMP(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      double tf;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (sscanf(tok, "%lf", &tf) == 0) {
          Vnm_print(2, "NOsh:  Read non-float (%s) while parsing TEMP \
  keyword!\n", tok);
          return -1;
      }
      thee->temp = tf;
      thee->settemp = 1;
      return 1;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseUSEMAP(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      int ti;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      Vnm_print(0, "PBEparm_parseToken:  Read %s...\n", tok);
      if (Vstring_strcasecmp(tok, "diel") == 0) {
          thee->useDielMap = 1;
          VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
          if (sscanf(tok, "%d", &ti) == 0) {
              Vnm_print(2, "NOsh:  Read non-int (%s) while parsing \
  USEMAP DIEL keyword!\n", tok);
              return -1;
          }
          thee->dielMapID = ti;
          return 1;
      } else if (Vstring_strcasecmp(tok, "kappa") == 0) {
          thee->useKappaMap = 1;
          VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
          if (sscanf(tok, "%d", &ti) == 0) {
              Vnm_print(2, "NOsh:  Read non-int (%s) while parsing \
  USEMAP KAPPA keyword!\n", tok);
              return -1;
          }
          thee->kappaMapID = ti;
          return 1;
      } else if (Vstring_strcasecmp(tok, "pot") == 0) {
          thee->usePotMap = 1;
          VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
          if (sscanf(tok, "%d", &ti) == 0) {
              Vnm_print(2, "NOsh:  Read non-int (%s) while parsing \
                        USEMAP POT keyword!\n", tok);
              return -1;
          }
          thee->potMapID = ti;
          return 1;
      } else if (Vstring_strcasecmp(tok, "charge") == 0) {
          thee->useChargeMap = 1;
          VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
          if (sscanf(tok, "%d", &ti) == 0) {
              Vnm_print(2, "NOsh:  Read non-int (%s) while parsing \
  USEMAP CHARGE keyword!\n", tok);
              return -1;
          }
          thee->chargeMapID = ti;
          return 1;
      } else {
          Vnm_print(2, "NOsh:  Read undefined keyword (%s) while parsing \
  USEMAP statement!\n", tok);
          return -1;
      }
      return 0;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseCALCENERGY(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      int ti;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      /* Parse number */
      if (sscanf(tok, "%d", &ti) == 1) {
          thee->calcenergy = (PBEparm_calcEnergy)ti;
          thee->setcalcenergy = 1;
  
          Vnm_print(2, "parsePBE:  Warning -- parsed deprecated \"calcenergy \
  %d\" statement.\n", ti);
          Vnm_print(2, "parsePBE:  Please use \"calcenergy ");
          switch (thee->calcenergy) {
              case PCE_NO:
                  Vnm_print(2, "no");
                  break;
              case PCE_TOTAL:
                  Vnm_print(2, "total");
                  break;
              case PCE_COMPS:
                  Vnm_print(2, "comps");
                  break;
              default:
                  Vnm_print(2, "UNKNOWN");
                  break;
          }
          Vnm_print(2, "\" instead.\n");
          return 1;
      } else if (Vstring_strcasecmp(tok, "no") == 0) {
          thee->calcenergy = PCE_NO;
          thee->setcalcenergy = 1;
          return 1;
      } else if (Vstring_strcasecmp(tok, "total") == 0) {
          thee->calcenergy = PCE_TOTAL;
          thee->setcalcenergy = 1;
          return 1;
      } else if (Vstring_strcasecmp(tok, "comps") == 0) {
          thee->calcenergy = PCE_COMPS;
          thee->setcalcenergy = 1;
          return 1;
      } else {
          Vnm_print(2, "NOsh:  Unrecognized parameter (%s) while parsing \
  calcenergy!\n", tok);
          return -1;
      }
      return 0;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseCALCFORCE(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      int ti;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      /* Parse number */
      if (sscanf(tok, "%d", &ti) == 1) {
          thee->calcforce = (PBEparm_calcForce)ti;
          thee->setcalcforce = 1;
  
          Vnm_print(2, "parsePBE:  Warning -- parsed deprecated \"calcforce \
  %d\" statement.\n", ti);
          Vnm_print(2, "parsePBE:  Please use \"calcforce ");
          switch (thee->calcenergy) {
              case PCF_NO:
                  Vnm_print(2, "no");
                  break;
              case PCF_TOTAL:
                  Vnm_print(2, "total");
                  break;
              case PCF_COMPS:
                  Vnm_print(2, "comps");
                  break;
              default:
                  Vnm_print(2, "UNKNOWN");
                  break;
          }
          Vnm_print(2, "\" instead.\n");
          return 1;
      } else if (Vstring_strcasecmp(tok, "no") == 0) {
          thee->calcforce = PCF_NO;
          thee->setcalcforce = 1;
          return 1;
      } else if (Vstring_strcasecmp(tok, "total") == 0) {
          thee->calcforce = PCF_TOTAL;
          thee->setcalcforce = 1;
          return 1;
      } else if (Vstring_strcasecmp(tok, "comps") == 0) {
          thee->calcforce = PCF_COMPS;
          thee->setcalcforce = 1;
          return 1;
      } else {
          Vnm_print(2, "NOsh:  Unrecognized parameter (%s) while parsing \
  calcforce!\n", tok);
          return -1;
      }
      return 0;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  /*----------------------------------------------------------*/
  /* Added by Michael Grabe                                   */
  /*----------------------------------------------------------*/
  
  VPRIVATE int PBEparm_parseZMEM(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      double tf;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (sscanf(tok, "%lf", &tf) == 0) {
          Vnm_print(2, "NOsh:  Read non-float (%s) while parsing ZMEM \
                    keyword!\n", tok);
          return -1;
      }
      thee->zmem = tf;
      thee->setzmem = 1;
      return 1;
  
  VERROR1:
      Vnm_print(2, "parsePBE:  ran out of tokens!\n");
      return -1;
  }
  
  
  VPRIVATE int PBEparm_parseLMEM(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      double tf;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (sscanf(tok, "%lf", &tf) == 0) {
          Vnm_print(2, "NOsh:  Read non-float (%s) while parsing LMEM \
                    keyword!\n", tok);
          return -1;
      }
      thee->Lmem = tf;
      thee->setLmem = 1;
      return 1;
  
  VERROR1:
      Vnm_print(2, "parsePBE:  ran out of tokens!\n");
      return -1;
  }
  
  VPRIVATE int PBEparm_parseMDIE(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      double tf;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (sscanf(tok, "%lf", &tf) == 0) {
          Vnm_print(2, "NOsh:  Read non-float (%s) while parsing MDIE \
                    keyword!\n", tok);
          return -1;
      }
      thee->mdie = tf;
      thee->setmdie  = 1;
      return 1;
  
  VERROR1:
      Vnm_print(2, "parsePBE:  ran out of tokens!\n");
      return -1;
  }
  
  VPRIVATE int PBEparm_parseMEMV(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE];
      double tf;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (sscanf(tok, "%lf", &tf) == 0) {
          Vnm_print(2, "NOsh:  Read non-float (%s) while parsing MEMV \
                    keyword!\n", tok);
          return -1;
      }
      thee->memv = tf;
      thee->setmemv = 1;
      return 1;
  
  VERROR1:
      Vnm_print(2, "parsePBE:  ran out of tokens!\n");
      return -1;
  }
  
  /*----------------------------------------------------------*/
  
  VPRIVATE int PBEparm_parseWRITE(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
      Vdata_Type writetype;
      Vdata_Format writefmt;
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (Vstring_strcasecmp(tok, "pot") == 0) {
          writetype = VDT_POT;
      } else if (Vstring_strcasecmp(tok, "atompot") == 0) {
          writetype = VDT_ATOMPOT;
      }  else if (Vstring_strcasecmp(tok, "charge") == 0) {
          writetype = VDT_CHARGE;
      } else if (Vstring_strcasecmp(tok, "smol") == 0) {
          writetype = VDT_SMOL;
      } else if (Vstring_strcasecmp(tok, "dielx") == 0) {
          writetype = VDT_DIELX;
      } else if (Vstring_strcasecmp(tok, "diely") == 0) {
          writetype = VDT_DIELY;
      } else if (Vstring_strcasecmp(tok, "dielz") == 0) {
          writetype = VDT_DIELZ;
      } else if (Vstring_strcasecmp(tok, "kappa") == 0) {
          writetype = VDT_KAPPA;
      } else if (Vstring_strcasecmp(tok, "sspl") == 0) {
          writetype = VDT_SSPL;
      } else if (Vstring_strcasecmp(tok, "vdw") == 0) {
          writetype = VDT_VDW;
      } else if (Vstring_strcasecmp(tok, "ivdw") == 0) {
          writetype = VDT_IVDW;
      } else if (Vstring_strcasecmp(tok, "lap") == 0) {
          writetype = VDT_LAP;
      } else if (Vstring_strcasecmp(tok, "edens") == 0) {
          writetype = VDT_EDENS;
      } else if (Vstring_strcasecmp(tok, "ndens") == 0) {
          writetype = VDT_NDENS;
      } else if (Vstring_strcasecmp(tok, "qdens") == 0) {
          writetype = VDT_QDENS;
      } else if (Vstring_strcasecmp(tok, "3dmap") == 0) {
  		VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
  		strcpy(thee->pbam_3dmapstem, tok);
  		thee->pbam_3dmapflag = 1;
  		return 1;
      } else {
          Vnm_print(2, "PBEparm_parse:  Invalid data type (%s) to write!\n",
             tok);
          return -1;
      }
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (Vstring_strcasecmp(tok, "dx") == 0) {
          writefmt = VDF_DX;
      }
      else if(Vstring_strcasecmp(tok, "dxbin") == 0){
      	writefmt = VDF_DXBIN;
      } else if (Vstring_strcasecmp(tok, "uhbd") == 0) {
          writefmt = VDF_UHBD;
      } else if (Vstring_strcasecmp(tok, "avs") == 0) {
          writefmt = VDF_AVS;
      } else if (Vstring_strcasecmp(tok, "gz") == 0) {
          writefmt = VDF_GZ;
      } else if (Vstring_strcasecmp(tok, "flat") == 0) {
          writefmt = VDF_FLAT;
      } else {
          Vnm_print(2, "PBEparm_parse:  Invalid data format (%s) to write!\n",
             tok);
          return -1;
      }
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (tok[0]=='"') {
          strcpy(strnew, "");
          while (tok[strlen(tok)-1] != '"') {
              strcat(str, tok);
              strcat(str, " ");
              VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
          }
          strcat(str, tok);
          strncpy(strnew, str+1, strlen(str)-2);
          strcpy(tok, strnew);
      }
      if (thee->numwrite < (PBEPARM_MAXWRITE-1)) {
          strncpy(thee->writestem[thee->numwrite], tok, VMAX_ARGLEN);
          thee->writetype[thee->numwrite] = writetype;
          thee->writefmt[thee->numwrite] = writefmt;
          (thee->numwrite)++;
      } else {
          Vnm_print(2, "PBEparm_parse:  You have exceeded the maximum number of write statements!\n");
          Vnm_print(2, "PBEparm_parse:  Ignoring additional write statements!\n");
      }
      return 1;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  }
  
  VPRIVATE int PBEparm_parseWRITEMAT(PBEparm *thee, Vio *sock) {
      char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (Vstring_strcasecmp(tok, "poisson") == 0) {
          thee->writematflag = 0;
      } else if (Vstring_strcasecmp(tok, "full") == 0) {
          thee->writematflag = 1;
      } else {
          Vnm_print(2, "NOsh:  Invalid format (%s) while parsing \
  WRITEMAT keyword!\n", tok);
          return -1;
      }
  
      VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
      if (tok[0]=='"') {
          strcpy(strnew, "");
          while (tok[strlen(tok)-1] != '"') {
              strcat(str, tok);
              strcat(str, " ");
              VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
          }
          strcat(str, tok);
          strncpy(strnew, str+1, strlen(str)-2);
          strcpy(tok, strnew);
      }
      strncpy(thee->writematstem, tok, VMAX_ARGLEN);
      thee->setwritemat = 1;
      thee->writemat = 1;
      return 1;
  
      VERROR1:
          Vnm_print(2, "parsePBE:  ran out of tokens!\n");
          return -1;
  
  }
  
  VPUBLIC int PBEparm_parseToken(PBEparm *thee, char tok[VMAX_BUFSIZE],
    Vio *sock) {
  
      if (thee == VNULL) {
          Vnm_print(2, "parsePBE:  got NULL thee!\n");
          return -1;
      }
      if (sock == VNULL) {
          Vnm_print(2, "parsePBE:  got NULL socket!\n");
          return -1;
      }
  
      Vnm_print(0, "PBEparm_parseToken:  trying %s...\n", tok);
  
      if (Vstring_strcasecmp(tok, "mol") == 0) {
          return PBEparm_parseMOL(thee, sock);
      } else if (Vstring_strcasecmp(tok, "lpbe") == 0) {
          return PBEparm_parseLPBE(thee, sock);
      } else if (Vstring_strcasecmp(tok, "npbe") == 0) {
          return PBEparm_parseNPBE(thee, sock);
      } else if (Vstring_strcasecmp(tok, "lrpbe") == 0) {
          return PBEparm_parseLRPBE(thee, sock);
      } else if (Vstring_strcasecmp(tok, "nrpbe") == 0) {
          return PBEparm_parseNRPBE(thee, sock);
      } else if (Vstring_strcasecmp(tok, "smpbe") == 0) {
          return PBEparm_parseSMPBE(thee, sock);
      } else if (Vstring_strcasecmp(tok, "bcfl") == 0) {
          return PBEparm_parseBCFL(thee, sock);
      } else if (Vstring_strcasecmp(tok, "ion") == 0) {
          return PBEparm_parseION(thee, sock);
      } else if (Vstring_strcasecmp(tok, "pdie") == 0) {
          return PBEparm_parsePDIE(thee, sock);
      } else if (Vstring_strcasecmp(tok, "sdens") == 0) {
          return PBEparm_parseSDENS(thee, sock);
      } else if (Vstring_strcasecmp(tok, "sdie") == 0) {
          return PBEparm_parseSDIE(thee, sock);
      } else if (Vstring_strcasecmp(tok, "srfm") == 0) {
          return PBEparm_parseSRFM(thee, sock);
      } else if (Vstring_strcasecmp(tok, "srad") == 0) {
          return PBEparm_parseSRAD(thee, sock);
      } else if (Vstring_strcasecmp(tok, "swin") == 0) {
          return PBEparm_parseSWIN(thee, sock);
      } else if (Vstring_strcasecmp(tok, "temp") == 0) {
          return PBEparm_parseTEMP(thee, sock);
      } else if (Vstring_strcasecmp(tok, "usemap") == 0) {
          return PBEparm_parseUSEMAP(thee, sock);
      } else if (Vstring_strcasecmp(tok, "calcenergy") == 0) {
          return PBEparm_parseCALCENERGY(thee, sock);
      } else if (Vstring_strcasecmp(tok, "calcforce") == 0) {
          return PBEparm_parseCALCFORCE(thee, sock);
      } else if (Vstring_strcasecmp(tok, "write") == 0) {
          return PBEparm_parseWRITE(thee, sock);
      } else if (Vstring_strcasecmp(tok, "writemat") == 0) {
          return PBEparm_parseWRITEMAT(thee, sock);
  
      /*----------------------------------------------------------*/
      /* Added by Michael Grabe                                   */
      /*----------------------------------------------------------*/
  
      } else if (Vstring_strcasecmp(tok, "zmem") == 0) {
          return PBEparm_parseZMEM(thee, sock);
      } else if (Vstring_strcasecmp(tok, "Lmem") == 0) {
          return PBEparm_parseLMEM(thee, sock);
      } else if (Vstring_strcasecmp(tok, "mdie") == 0) {
          return PBEparm_parseMDIE(thee, sock);
      } else if (Vstring_strcasecmp(tok, "memv") == 0) {
          return PBEparm_parseMEMV(thee, sock);
      }
  
      /*----------------------------------------------------------*/
  
      return 0;
  
  }
  