1 /**
2  *  @file    mgparm.c
3  *  @ingroup MGparm
4  *  @author  Nathan Baker
5  *  @brief   Class MGparm methods
6  *  @version $Id$
7  *  @attention
8  *  @verbatim
9  *
10  * APBS -- Adaptive Poisson-Boltzmann Solver
11  *
12  *  Nathan A. Baker (nathan.baker@pnnl.gov)
13  *  Pacific Northwest National Laboratory
14  *
15  *  Additional contributing authors listed in the code documentation.
16  *
17  * Copyright (c) 2010-2014 Battelle Memorial Institute. Developed at the
18  * Pacific Northwest National Laboratory, operated by Battelle Memorial
19  * Institute, Pacific Northwest Division for the U.S. Department of Energy.
20  *
21  * Portions Copyright (c) 2002-2010, Washington University in St. Louis.
22  * Portions Copyright (c) 2002-2010, Nathan A. Baker.
23  * Portions Copyright (c) 1999-2002, The Regents of the University of
24  * California.
25  * Portions Copyright (c) 1995, Michael Holst.
26  * All rights reserved.
27  *
28  * Redistribution and use in source and binary forms, with or without
29  * modification, are permitted provided that the following conditions are met:
30  *
31  * Redistributions of source code must retain the above copyright notice, this
32  * list of conditions and the following disclaimer.
33  *
34  * Redistributions in binary form must reproduce the above copyright notice,
35  * this list of conditions and the following disclaimer in the documentation
36  * and/or other materials provided with the distribution.
37  *
38  * Neither the name of the developer nor the names of its contributors may be
39  * used to endorse or promote products derived from this software without
40  * specific prior written permission.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
46  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
47  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
48  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
49  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
50  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
52  * THE POSSIBILITY OF SUCH DAMAGE.
53  *
54  * @endverbatim
55  */
56 
57 #include "mgparm.h"
58 
59 VEMBED(rcsid="$Id$")
60 
61 #if !defined(VINLINE_MGPARM)
62 
63 #endif /* if !defined(VINLINE_MGPARM) */
64 
MGparm_setCenterX(MGparm * thee,double x)65 VPUBLIC void MGparm_setCenterX(MGparm *thee, double x) {
66     VASSERT(thee != VNULL);
67     thee->center[0] = x;
68 }
MGparm_setCenterY(MGparm * thee,double y)69 VPUBLIC void MGparm_setCenterY(MGparm *thee, double y) {
70     VASSERT(thee != VNULL);
71     thee->center[1] = y;
72 }
MGparm_setCenterZ(MGparm * thee,double z)73 VPUBLIC void MGparm_setCenterZ(MGparm *thee, double z) {
74     VASSERT(thee != VNULL);
75     thee->center[2] = z;
76 }
MGparm_getCenterX(MGparm * thee)77 VPUBLIC double MGparm_getCenterX(MGparm *thee) {
78     VASSERT(thee != VNULL);
79     return thee->center[0];
80 }
MGparm_getCenterY(MGparm * thee)81 VPUBLIC double MGparm_getCenterY(MGparm *thee) {
82     VASSERT(thee != VNULL);
83     return thee->center[1];
84 }
MGparm_getCenterZ(MGparm * thee)85 VPUBLIC double MGparm_getCenterZ(MGparm *thee) {
86     VASSERT(thee != VNULL);
87     return thee->center[2];
88 }
MGparm_getNx(MGparm * thee)89 VPUBLIC int MGparm_getNx(MGparm *thee) {
90     VASSERT(thee != VNULL);
91     return thee->dime[0];
92 }
MGparm_getNy(MGparm * thee)93 VPUBLIC int MGparm_getNy(MGparm *thee) {
94     VASSERT(thee != VNULL);
95     return thee->dime[1];
96 }
MGparm_getNz(MGparm * thee)97 VPUBLIC int MGparm_getNz(MGparm *thee) {
98     VASSERT(thee != VNULL);
99     return thee->dime[2];
100 }
MGparm_getHx(MGparm * thee)101 VPUBLIC double MGparm_getHx(MGparm *thee) {
102     VASSERT(thee != VNULL);
103     return thee->grid[0];
104 }
MGparm_getHy(MGparm * thee)105 VPUBLIC double MGparm_getHy(MGparm *thee) {
106     VASSERT(thee != VNULL);
107     return thee->grid[1];
108 }
MGparm_getHz(MGparm * thee)109 VPUBLIC double MGparm_getHz(MGparm *thee) {
110     VASSERT(thee != VNULL);
111     return thee->grid[2];
112 }
113 
MGparm_ctor(MGparm_CalcType type)114 VPUBLIC MGparm* MGparm_ctor(MGparm_CalcType type) {
115 
116     /* Set up the structure */
117     MGparm *thee = VNULL;
118     thee = (MGparm*)Vmem_malloc(VNULL, 1, sizeof(MGparm));
119     VASSERT( thee != VNULL);
120     VASSERT( MGparm_ctor2(thee, type) == VRC_SUCCESS );
121 
122     return thee;
123 }
124 
MGparm_ctor2(MGparm * thee,MGparm_CalcType type)125 VPUBLIC Vrc_Codes MGparm_ctor2(MGparm *thee, MGparm_CalcType type) {
126 
127     int i;
128 
129     if (thee == VNULL) return VRC_FAILURE;
130 
131     for (i=0; i<3; i++) {
132         thee->dime[i] = -1;
133         thee->pdime[i] = 1;
134     }
135 
136     thee->parsed = 0;
137     thee->type = type;
138 
139     /* *** GENERIC PARAMETERS *** */
140     thee->setdime = 0;
141     thee->setchgm = 0;
142 
143     /* *** TYPE 0 PARAMETERS *** */
144     thee->nlev = VMGNLEV;
145     thee->setnlev = 1;
146     thee->etol = 1.0e-6;
147     thee->setetol = 0;
148     thee->setgrid = 0;
149     thee->setglen = 0;
150     thee->setgcent = 0;
151 
152     /* *** TYPE 1 & 2 PARAMETERS *** */
153     thee->setcglen = 0;
154     thee->setfglen = 0;
155     thee->setcgcent = 0;
156     thee->setfgcent = 0;
157 
158     /* *** TYPE 2 PARAMETERS *** */
159     thee->setpdime = 0;
160     thee->setrank = 0;
161     thee->setsize = 0;
162     thee->setofrac = 0;
163     for (i=0; i<6; i++) thee->partDisjOwnSide[i] = 0;
164     thee->setasync = 0;
165 
166     /* *** Default parameters for TINKER *** */
167     thee->chgs = VCM_CHARGE;
168 
169     thee->useAqua = 0;
170     thee->setUseAqua = 0;
171 
172     return VRC_SUCCESS;
173 }
174 
MGparm_dtor(MGparm ** thee)175 VPUBLIC void MGparm_dtor(MGparm **thee) {
176     if ((*thee) != VNULL) {
177         MGparm_dtor2(*thee);
178         Vmem_free(VNULL, 1, sizeof(MGparm), (void **)thee);
179         (*thee) = VNULL;
180     }
181 }
182 
MGparm_dtor2(MGparm * thee)183 VPUBLIC void MGparm_dtor2(MGparm *thee) { ; }
184 
MGparm_check(MGparm * thee)185 VPUBLIC Vrc_Codes MGparm_check(MGparm *thee) {
186 
187     Vrc_Codes rc;
188     int i, tdime[3], ti, tnlev[3], nlev;
189 
190     rc = VRC_SUCCESS;
191 
192     Vnm_print(0, "MGparm_check:  checking MGparm object of type %d.\n",
193               thee->type);
194 
195     /* Check to see if we were even filled... */
196     if (!thee->parsed) {
197         Vnm_print(2, "MGparm_check:  not filled!\n");
198         return VRC_FAILURE;
199     }
200 
201     /* Check generic settings */
202     if (!thee->setdime) {
203         Vnm_print(2, "MGparm_check:  DIME not set!\n");
204         rc = VRC_FAILURE;
205     }
206     if (!thee->setchgm) {
207         Vnm_print(2, "MGparm_check: CHGM not set!\n");
208         return VRC_FAILURE;
209     }
210 
211 
212     /* Check sequential manual & dummy settings */
213     if ((thee->type == MCT_MANUAL) || (thee->type == MCT_DUMMY)) {
214         if ((!thee->setgrid) && (!thee->setglen)) {
215             Vnm_print(2, "MGparm_check:  Neither GRID nor GLEN set!\n");
216             rc = VRC_FAILURE;
217         }
218         if ((thee->setgrid) && (thee->setglen)) {
219             Vnm_print(2, "MGparm_check:  Both GRID and GLEN set!\n");
220             rc = VRC_FAILURE;
221         }
222         if (!thee->setgcent) {
223             Vnm_print(2, "MGparm_check:  GCENT not set!\n");
224             rc = VRC_FAILURE;
225         }
226     }
227 
228     /* Check sequential and parallel automatic focusing settings */
229     if ((thee->type == MCT_AUTO) || (thee->type == MCT_PARALLEL)) {
230         if (!thee->setcglen) {
231             Vnm_print(2, "MGparm_check:  CGLEN not set!\n");
232             rc = VRC_FAILURE;
233         }
234         if (!thee->setfglen) {
235             Vnm_print(2, "MGparm_check:  FGLEN not set!\n");
236             rc = VRC_FAILURE;
237         }
238         if (!thee->setcgcent) {
239             Vnm_print(2, "MGparm_check:  CGCENT not set!\n");
240             rc = VRC_FAILURE;
241         }
242         if (!thee->setfgcent) {
243             Vnm_print(2, "MGparm_check:  FGCENT not set!\n");
244             rc = VRC_FAILURE;
245         }
246     }
247 
248     /* Check parallel automatic focusing settings */
249     if (thee->type == MCT_PARALLEL) {
250         if (!thee->setpdime) {
251             Vnm_print(2, "MGparm_check:  PDIME not set!\n");
252             rc = VRC_FAILURE;
253         }
254         if (!thee->setrank) {
255             Vnm_print(2, "MGparm_check:  PROC_RANK not set!\n");
256             rc = VRC_FAILURE;
257         }
258         if (!thee->setsize) {
259             Vnm_print(2, "MGparm_check:  PROC_SIZE not set!\n");
260             rc = VRC_FAILURE;
261         }
262         if (!thee->setofrac) {
263             Vnm_print(2, "MGparm_check:  OFRAC not set!\n");
264             rc = VRC_FAILURE;
265         }
266     }
267 
268     /* Perform a sanity check on nlev and dime, resetting values as necessary */
269     if (rc == 1) {
270     /* Calculate the actual number of grid points and nlev to satisfy the
271      * formula:  n = c * 2^(l+1) + 1, where n is the number of grid points,
272      * c is an integer, and l is the number of levels */
273     if (thee->type != MCT_DUMMY) {
274         for (i=0; i<3; i++) {
275             /* See if the user picked a reasonable value, if not then fix it */
276             ti = thee->dime[i] - 1;
277             if (ti == VPOW(2, (thee->nlev+1))) {
278                 tnlev[i] = thee->nlev;
279                 tdime[i] = thee->dime[i];
280             } else {
281                 tdime[i] = thee->dime[i];
282                 ti = tdime[i] - 1;
283                 tnlev[i] = 0;
284                 /* Find the maximum number of times this dimension can be
285                  * divided by two */
286                 while (VEVEN(ti)) {
287                     (tnlev[i])++;
288                     ti = (int)ceil(0.5*ti);
289                 }
290                 (tnlev[i])--;
291                 /* We'd like to have at least VMGNLEV levels in the multigrid
292                  * hierarchy.  This means that the dimension needs to be
293                  * c*2^VMGNLEV + 1, where c is an integer. */
294                 if ((tdime[i] > 65) && (tnlev[i] < VMGNLEV)) {
295                     Vnm_print(2, "NOsh:  Bad dime[%d]  = %d (%d nlev)!\n",
296                       i, tdime[i], tnlev[i]);
297                     ti = (int)(tdime[i]/VPOW(2.,(VMGNLEV+1)));
298                     if (ti < 1) ti = 1;
299                     tdime[i] = ti*(int)(VPOW(2.,(VMGNLEV+1))) + 1;
300                     tnlev[i] = 4;
301                     Vnm_print(2, "NOsh:  Reset dime[%d] to %d and (nlev = %d).\n", i, tdime[i], VMGNLEV);
302                 }
303             }
304         }
305     } else { /* We are a dummy calculation, but we still need positive numbers of points */
306         for (i=0; i<3; i++) {
307             tnlev[i] = thee->nlev;
308             tdime[i] = thee->dime[i];
309                 if (thee->dime[i] <= 0) {
310                     Vnm_print(2, "NOsh:  Resetting dime[%d] from %d to 3.\n", i, thee->dime[i]);
311                     thee->dime[i] = 3;
312             }
313         }
314     }
315 
316     /* The actual number of levels we'll be using is the smallest number of
317          * possible levels in any dimensions */
318         nlev = VMIN2(tnlev[0], tnlev[1]);
319         nlev = VMIN2(nlev, tnlev[2]);
320         /* Set the number of levels and dimensions */
321         Vnm_print(0, "NOsh:  nlev = %d, dime = (%d, %d, %d)\n", nlev, tdime[0],
322           tdime[1], tdime[2]);
323         thee->nlev = nlev;
324         if (thee->nlev <= 0) {
325             Vnm_print(2, "MGparm_check:  illegal nlev (%d); check your grid dimensions!\n", thee->nlev);
326             rc = VRC_FAILURE;
327         }
328         if (thee->nlev < 2) {
329             Vnm_print(2, "MGparm_check:  you're using a very small nlev (%d) and therefore\n", thee->nlev);
330             Vnm_print(2, "MGparm_check:  will not get the optimal performance of the multigrid\n");
331             Vnm_print(2, "MGparm_check:  algorithm.  Please check your grid dimensions.\n");
332         }
333         for (i=0; i<3; i++) thee->dime[i] = tdime[i];
334     }
335 
336     if (!thee->setUseAqua) thee->useAqua = 0;
337 
338     return rc;
339 }
340 
MGparm_copy(MGparm * thee,MGparm * parm)341 VPUBLIC void MGparm_copy(MGparm *thee, MGparm *parm) {
342 
343     int i;
344 
345     VASSERT(thee != VNULL);
346     VASSERT(parm != VNULL);
347 
348 
349     thee->type = parm->type;
350     thee->parsed = parm->parsed;
351 
352     /* *** GENERIC PARAMETERS *** */
353     for (i=0; i<3; i++) thee->dime[i] = parm->dime[i];
354     thee->setdime = parm->setdime;
355     thee->chgm = parm->chgm;
356     thee->setchgm = parm->setchgm;
357     thee->chgs = parm->chgs;
358 
359     /* *** TYPE 0 PARMS *** */
360     thee->nlev = parm->nlev;
361     thee->setnlev = parm->setnlev;
362     thee->etol = parm->etol;
363     thee->setetol = parm->setetol;
364     for (i=0; i<3; i++) thee->grid[i] = parm->grid[i];
365     thee->setgrid = parm->setgrid;
366     for (i=0; i<3; i++) thee->glen[i] = parm->glen[i];
367     thee->setglen = parm->setglen;
368     thee->cmeth = parm->cmeth;
369     for (i=0; i<3; i++) thee->center[i] = parm->center[i];
370     thee->setgcent = parm->setgcent;
371     thee->centmol = parm->centmol;
372 
373     /* *** TYPE 1 & 2 PARMS *** */
374     for (i=0; i<3; i++) thee->cglen[i] = parm->cglen[i];
375     thee->setcglen = parm->setcglen;
376     for (i=0; i<3; i++) thee->fglen[i] = parm->fglen[i];
377     thee->setfglen = parm->setfglen;
378     thee->ccmeth = parm->ccmeth;
379     for (i=0; i<3; i++) thee->ccenter[i] = parm->ccenter[i];
380     thee->setcgcent = parm->setcgcent;
381     thee->ccentmol = parm->ccentmol;
382     thee->fcmeth = parm->fcmeth;
383     for (i=0; i<3; i++) thee->fcenter[i] = parm->fcenter[i];
384     thee->setfgcent = parm->setfgcent;
385     thee->fcentmol = parm->fcentmol;
386 
387     /* *** TYPE 2 PARMS *** */
388     for (i=0; i<3; i++)
389       thee->partDisjCenter[i] = parm->partDisjCenter[i];
390     for (i=0; i<3; i++)
391       thee->partDisjLength[i] = parm->partDisjLength[i];
392     for (i=0; i<6; i++)
393       thee->partDisjOwnSide[i] = parm->partDisjOwnSide[i];
394     for (i=0; i<3; i++) thee->pdime[i] = parm->pdime[i];
395     thee->setpdime = parm->setpdime;
396     thee->proc_rank = parm->proc_rank;
397     thee->setrank = parm->setrank;
398     thee->proc_size = parm->proc_size;
399     thee->setsize = parm->setsize;
400     thee->ofrac = parm->ofrac;
401     thee->setofrac = parm->setofrac;
402     thee->setasync = parm->setasync;
403     thee->async = parm->async;
404 
405     thee->nonlintype = parm->nonlintype;
406     thee->setnonlintype = parm->setnonlintype;
407 
408     thee->method = parm->method;
409     thee->method = parm->method;
410 
411     thee->useAqua = parm->useAqua;
412     thee->setUseAqua = parm->setUseAqua;
413 }
414 
MGparm_parseDIME(MGparm * thee,Vio * sock)415 VPRIVATE Vrc_Codes MGparm_parseDIME(MGparm *thee, Vio *sock) {
416 
417     char tok[VMAX_BUFSIZE];
418     int ti;
419 
420     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
421     if (sscanf(tok, "%d", &ti) == 0){
422         Vnm_print(2, "parseMG:  Read non-integer (%s) while parsing DIME \
423 keyword!\n", tok);
424         return VRC_WARNING;
425     } else thee->dime[0] = ti;
426     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
427     if (sscanf(tok, "%d", &ti) == 0) {
428         Vnm_print(2, "NOsh:  Read non-integer (%s) while parsing DIME \
429 keyword!\n", tok);
430         return VRC_WARNING;
431     } else thee->dime[1] = ti;
432     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
433     if (sscanf(tok, "%d", &ti) == 0) {
434         Vnm_print(2, "NOsh:  Read non-integer (%s) while parsing DIME \
435 keyword!\n", tok);
436         return VRC_WARNING;
437     } else thee->dime[2] = ti;
438     thee->setdime = 1;
439     return VRC_SUCCESS;
440 
441     VERROR1:
442         Vnm_print(2, "parseMG:  ran out of tokens!\n");
443         return VRC_WARNING;
444 }
445 
MGparm_parseCHGM(MGparm * thee,Vio * sock)446 VPRIVATE Vrc_Codes MGparm_parseCHGM(MGparm *thee, Vio *sock) {
447 
448     char tok[VMAX_BUFSIZE];
449     Vchrg_Meth ti;
450 
451     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
452     if (sscanf(tok, "%d", (int*)(&ti)) == 1) {
453         thee->chgm = ti;
454         thee->setchgm = 1;
455         Vnm_print(2, "NOsh:  Warning -- parsed deprecated statment \"chgm %d\".\n", ti);
456         Vnm_print(2, "NOsh:  Please use \"chgm ");
457         switch (thee->chgm) {
458             case VCM_TRIL:
459                 Vnm_print(2, "spl0");
460                 break;
461             case VCM_BSPL2:
462                 Vnm_print(2, "spl2");
463                 break;
464             case VCM_BSPL4:
465                 Vnm_print(2, "spl4");
466                 break;
467             default:
468                 Vnm_print(2, "UNKNOWN");
469                 break;
470         }
471         Vnm_print(2, "\" instead!\n");
472         return VRC_SUCCESS;
473     } else if (Vstring_strcasecmp(tok, "spl0") == 0) {
474         thee->chgm = VCM_TRIL;
475         thee->setchgm = 1;
476         return VRC_SUCCESS;
477     } else if (Vstring_strcasecmp(tok, "spl2") == 0) {
478         thee->chgm = VCM_BSPL2;
479         thee->setchgm = 1;
480         return VRC_SUCCESS;
481     } else if (Vstring_strcasecmp(tok, "spl4") == 0) {
482         thee->chgm = VCM_BSPL4;
483         thee->setchgm = 1;
484         return VRC_SUCCESS;
485     } else {
486         Vnm_print(2, "NOsh:  Unrecognized parameter (%s) when parsing \
487 chgm!\n", tok);
488         return VRC_WARNING;
489     }
490     return VRC_WARNING;
491 
492     VERROR1:
493         Vnm_print(2, "parseMG:  ran out of tokens!\n");
494         return VRC_WARNING;
495 }
496 
MGparm_parseNLEV(MGparm * thee,Vio * sock)497 VPRIVATE Vrc_Codes MGparm_parseNLEV(MGparm *thee, Vio *sock) {
498 
499     char tok[VMAX_BUFSIZE];
500     int ti;
501 
502     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
503     if (sscanf(tok, "%d", &ti) == 0) {
504         Vnm_print(2, "NOsh:  Read non-integer (%s) while parsing NLEV \
505 keyword!\n", tok);
506         return VRC_WARNING;
507     } else thee->nlev = ti;
508     thee->setnlev = 1;
509     return VRC_SUCCESS;
510 
511     VERROR1:
512         Vnm_print(2, "parseMG:  ran out of tokens!\n");
513         return VRC_WARNING;
514 }
515 
MGparm_parseETOL(MGparm * thee,Vio * sock)516 VPRIVATE Vrc_Codes MGparm_parseETOL(MGparm *thee, Vio *sock) {
517 
518     char tok[VMAX_BUFSIZE];
519     double tf;
520 
521     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
522     if (sscanf(tok, "%lf", &tf) == 0) {
523         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing etol \
524 keyword!\n", tok);
525         return VRC_WARNING;
526     } else if (tf <= 0.0) {
527         Vnm_print(2, "parseMG:  etol must be greater than 0!\n");
528         return VRC_WARNING;
529     } else thee->etol = tf;
530     thee->setetol = 1;
531     return VRC_SUCCESS;
532 
533     VERROR1:
534         Vnm_print(2, "parseMG:  ran out of tokens!\n");
535         return VRC_WARNING;
536 }
537 
538 
MGparm_parseGRID(MGparm * thee,Vio * sock)539 VPRIVATE Vrc_Codes MGparm_parseGRID(MGparm *thee, Vio *sock) {
540 
541     char tok[VMAX_BUFSIZE];
542     double tf;
543 
544     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
545     if (sscanf(tok, "%lf", &tf) == 0) {
546         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing GRID \
547 keyword!\n", tok);
548         return VRC_WARNING;
549     } else thee->grid[0] = tf;
550     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
551     if (sscanf(tok, "%lf", &tf) == 0) {
552         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing GRID \
553 keyword!\n", tok);
554         return VRC_WARNING;
555     } else thee->grid[1] = tf;
556     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
557     if (sscanf(tok, "%lf", &tf) == 0) {
558         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing GRID \
559 keyword!\n", tok);
560         return VRC_WARNING;
561     } else thee->grid[2] = tf;
562     thee->setgrid = 1;
563     return VRC_SUCCESS;
564 
565     VERROR1:
566         Vnm_print(2, "parseMG:  ran out of tokens!\n");
567         return VRC_WARNING;
568 }
569 
MGparm_parseGLEN(MGparm * thee,Vio * sock)570 VPRIVATE Vrc_Codes MGparm_parseGLEN(MGparm *thee, Vio *sock) {
571 
572     char tok[VMAX_BUFSIZE];
573     double tf;
574 
575     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
576     if (sscanf(tok, "%lf", &tf) == 0) {
577         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing GLEN \
578 keyword!\n", tok);
579         return VRC_WARNING;
580     } else thee->glen[0] = tf;
581     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
582     if (sscanf(tok, "%lf", &tf) == 0) {
583         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing GLEN \
584 keyword!\n", tok);
585         return VRC_WARNING;
586     } else thee->glen[1] = tf;
587     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
588     if (sscanf(tok, "%lf", &tf) == 0) {
589         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing GLEN \
590 keyword!\n", tok);
591         return VRC_WARNING;
592     } else thee->glen[2] = tf;
593     thee->setglen = 1;
594     return VRC_SUCCESS;
595 
596     VERROR1:
597         Vnm_print(2, "parseMG:  ran out of tokens!\n");
598         return VRC_WARNING;
599 }
600 
MGparm_parseGAMMA(MGparm * thee,Vio * sock)601 VPRIVATE Vrc_Codes MGparm_parseGAMMA(MGparm *thee, Vio *sock) {
602 
603     char tok[VMAX_BUFSIZE];
604 
605     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
606     Vnm_print(2, "parseMG:  GAMMA keyword deprecated!\n");
607     Vnm_print(2, "parseMG:  If you are using PyMOL or VMD and still seeing this message,\n");
608     Vnm_print(2, "parseMG:  please contact the developers of those programs regarding this message.\n");
609     return VRC_SUCCESS;
610 
611 VERROR1:
612     Vnm_print(2, "parseMG:  ran out of tokens!\n");
613     return VRC_WARNING;
614 }
615 
MGparm_parseGCENT(MGparm * thee,Vio * sock)616 VPRIVATE Vrc_Codes MGparm_parseGCENT(MGparm *thee, Vio *sock) {
617 
618     char tok[VMAX_BUFSIZE];
619     double tf;
620     int ti;
621 
622     /* If the next token isn't a float, it probably means we want to
623      * center on a molecule */
624     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
625     if (sscanf(tok, "%lf", &tf) == 0) {
626         if (Vstring_strcasecmp(tok, "mol") == 0) {
627             VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
628             if (sscanf(tok, "%d", &ti) == 0) {
629                 Vnm_print(2, "NOsh:  Read non-int (%s) while parsing \
630 GCENT MOL keyword!\n", tok);
631                 return VRC_WARNING;
632             } else {
633                 thee->cmeth = MCM_MOLECULE;
634                 /* Subtract 1 here to convert user numbering (1, 2, 3, ...) into
635                 array index */
636                 thee->centmol = ti - 1;
637             }
638         } else {
639             Vnm_print(2, "NOsh:  Unexpected keyword (%s) while parsing \
640 GCENT!\n", tok);
641             return VRC_WARNING;
642         }
643     } else {
644         thee->center[0] = tf;
645         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
646         if (sscanf(tok, "%lf", &tf) == 0) {
647             Vnm_print(2, "NOsh:  Read non-float (%s) while parsing \
648 GCENT keyword!\n", tok);
649             return VRC_WARNING;
650         }
651         thee->center[1] = tf;
652         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
653         if (sscanf(tok, "%lf", &tf) == 0) {
654             Vnm_print(2, "NOsh:  Read non-float (%s) while parsing \
655 GCENT keyword!\n", tok);
656             return VRC_WARNING;
657         }
658         thee->center[2] = tf;
659     }
660     thee->setgcent = 1;
661     return VRC_SUCCESS;
662 
663     VERROR1:
664         Vnm_print(2, "parseMG:  ran out of tokens!\n");
665         return VRC_WARNING;
666 }
667 
MGparm_parseCGLEN(MGparm * thee,Vio * sock)668 VPRIVATE Vrc_Codes MGparm_parseCGLEN(MGparm *thee, Vio *sock) {
669 
670     char tok[VMAX_BUFSIZE];
671     double tf;
672 
673     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
674     if (sscanf(tok, "%lf", &tf) == 0) {
675         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing CGLEN \
676 keyword!\n", tok);
677         return VRC_WARNING;
678     } else thee->cglen[0] = tf;
679     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
680     if (sscanf(tok, "%lf", &tf) == 0) {
681         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing CGLEN \
682 keyword!\n", tok);
683         return VRC_WARNING;
684     } else thee->cglen[1] = tf;
685     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
686     if (sscanf(tok, "%lf", &tf) == 0) {
687         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing CGLEN \
688 keyword!\n", tok);
689         return VRC_WARNING;
690     } else thee->cglen[2] = tf;
691     thee->setcglen = 1;
692     return VRC_SUCCESS;
693 
694     VERROR1:
695         Vnm_print(2, "parseMG:  ran out of tokens!\n");
696         return VRC_WARNING;
697 }
698 
MGparm_parseFGLEN(MGparm * thee,Vio * sock)699 VPRIVATE Vrc_Codes MGparm_parseFGLEN(MGparm *thee, Vio *sock) {
700 
701     char tok[VMAX_BUFSIZE];
702     double tf;
703 
704     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
705     if (sscanf(tok, "%lf", &tf) == 0) {
706         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing FGLEN \
707 keyword!\n", tok);
708         return VRC_WARNING;
709     } else thee->fglen[0] = tf;
710     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
711     if (sscanf(tok, "%lf", &tf) == 0) {
712         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing FGLEN \
713 keyword!\n", tok);
714         return VRC_WARNING;
715     } else thee->fglen[1] = tf;
716     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
717     if (sscanf(tok, "%lf", &tf) == 0) {
718         Vnm_print(2, "NOsh:  Read non-float (%s) while parsing FGLEN \
719 keyword!\n", tok);
720         return VRC_WARNING;
721     } else thee->fglen[2] = tf;
722     thee->setfglen = 1;
723     return VRC_SUCCESS;
724 
725     VERROR1:
726         Vnm_print(2, "parseMG:  ran out of tokens!\n");
727         return VRC_WARNING;
728 }
729 
MGparm_parseCGCENT(MGparm * thee,Vio * sock)730 VPRIVATE Vrc_Codes MGparm_parseCGCENT(MGparm *thee, Vio *sock) {
731 
732     char tok[VMAX_BUFSIZE];
733     double tf;
734     int ti;
735 
736     /* If the next token isn't a float, it probably means we want to
737      * center on a molecule */
738     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
739     if (sscanf(tok, "%lf", &tf) == 0) {
740         if (Vstring_strcasecmp(tok, "mol") == 0) {
741             VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
742             if (sscanf(tok, "%d", &ti) == 0) {
743                 Vnm_print(2, "NOsh:  Read non-int (%s) while parsing \
744 CGCENT MOL keyword!\n", tok);
745                 return VRC_WARNING;
746             } else {
747                 thee->ccmeth = MCM_MOLECULE;
748                 /* Subtract 1 here to convert user numbering (1, 2, 3, ...) into
749                 array index */
750                 thee->ccentmol = ti - 1;
751             }
752         } else {
753             Vnm_print(2, "NOsh:  Unexpected keyword (%s) while parsing \
754 CGCENT!\n", tok);
755             return VRC_WARNING;
756             }
757     } else {
758         thee->ccenter[0] = tf;
759         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
760         if (sscanf(tok, "%lf", &tf) == 0) {
761             Vnm_print(2, "NOsh:  Read non-float (%s) while parsing \
762 CGCENT keyword!\n", tok);
763             return VRC_WARNING;
764         }
765         thee->ccenter[1] = tf;
766         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
767         if (sscanf(tok, "%lf", &tf) == 0) {
768             Vnm_print(2, "NOsh:  Read non-float (%s) while parsing \
769 CGCENT keyword!\n", tok);
770             return VRC_WARNING;
771         }
772         thee->ccenter[2] = tf;
773     }
774     thee->setcgcent = 1;
775     return VRC_SUCCESS;
776 
777     VERROR1:
778         Vnm_print(2, "parseMG:  ran out of tokens!\n");
779         return VRC_WARNING;
780 }
781 
MGparm_parseFGCENT(MGparm * thee,Vio * sock)782 VPRIVATE Vrc_Codes MGparm_parseFGCENT(MGparm *thee, Vio *sock) {
783 
784     char tok[VMAX_BUFSIZE];
785     double tf;
786     int ti;
787 
788     /* If the next token isn't a float, it probably means we want to
789      * center on a molecule */
790     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
791     if (sscanf(tok, "%lf", &tf) == 0) {
792         if (Vstring_strcasecmp(tok, "mol") == 0) {
793             VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
794             if (sscanf(tok, "%d", &ti) == 0) {
795                  Vnm_print(2, "NOsh:  Read non-int (%s) while parsing \
796 FGCENT MOL keyword!\n", tok);
797                  return VRC_WARNING;
798             } else {
799                 thee->fcmeth = MCM_MOLECULE;
800                 /* Subtract 1 here to convert user numbering (1, 2, 3, ...) into
801                 array index */
802                 thee->fcentmol = ti - 1;
803             }
804         } else {
805             Vnm_print(2, "NOsh:  Unexpected keyword (%s) while parsing \
806 FGCENT!\n", tok);
807             return VRC_WARNING;
808         }
809     } else {
810         thee->fcenter[0] = tf;
811         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
812         if (sscanf(tok, "%lf", &tf) == 0) {
813             Vnm_print(2, "NOsh:  Read non-float (%s) while parsing \
814 FGCENT keyword!\n", tok);
815             return VRC_WARNING;
816         }
817         thee->fcenter[1] = tf;
818         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
819         if (sscanf(tok, "%lf", &tf) == 0) {
820             Vnm_print(2, "NOsh:  Read non-float (%s) while parsing \
821 FGCENT keyword!\n", tok);
822             return VRC_WARNING;
823         }
824         thee->fcenter[2] = tf;
825     }
826     thee->setfgcent = 1;
827     return VRC_SUCCESS;
828 
829     VERROR1:
830         Vnm_print(2, "parseMG:  ran out of tokens!\n");
831         return VRC_WARNING;
832 }
833 
MGparm_parsePDIME(MGparm * thee,Vio * sock)834 VPRIVATE Vrc_Codes MGparm_parsePDIME(MGparm *thee, Vio *sock) {
835 
836     char tok[VMAX_BUFSIZE];
837     int ti;
838 
839     /* Read the number of grid points */
840     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
841     if (sscanf(tok, "%d", &ti) == 0) {
842         Vnm_print(2, "NOsh:  Read non-integer (%s) while parsing PDIME \
843 keyword!\n", tok);
844         return VRC_WARNING;
845     } else {
846         thee->pdime[0] = ti;
847     }
848     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
849     if (sscanf(tok, "%d", &ti) == 0) {
850         Vnm_print(2, "NOsh:  Read non-integer (%s) while parsing PDIME \
851 keyword!\n", tok);
852         return VRC_WARNING;
853     } else {
854         thee->pdime[1] = ti;
855     }
856     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
857     if (sscanf(tok, "%d", &ti) == 0) {
858         Vnm_print(2, "NOsh:  Read non-integer (%s) while parsing PDIME \
859 keyword!\n", tok);
860         return VRC_WARNING;
861     } else {
862         thee->pdime[2] = ti;
863     }
864     thee->setpdime = 1;
865     return VRC_SUCCESS;
866 
867     VERROR1:
868         Vnm_print(2, "parseMG:  ran out of tokens!\n");
869         return VRC_WARNING;
870 }
871 
MGparm_parseOFRAC(MGparm * thee,Vio * sock)872 VPRIVATE Vrc_Codes MGparm_parseOFRAC(MGparm *thee, Vio *sock) {
873 
874     char tok[VMAX_BUFSIZE];
875     double tf;
876 
877     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
878     if (sscanf(tok, "%lf", &tf) == 0) {
879         Vnm_print(2, "NOsh:  Read non-int (%s) while parsing OFRAC \
880 keyword!\n", tok);
881         return VRC_WARNING;
882     }
883     thee->ofrac = tf;
884     thee->setofrac = 1;
885     return VRC_SUCCESS;
886 
887     VERROR1:
888         Vnm_print(2, "parseMG:  ran out of tokens!\n");
889         return VRC_WARNING;
890 }
891 
MGparm_parseASYNC(MGparm * thee,Vio * sock)892 VPRIVATE Vrc_Codes MGparm_parseASYNC(MGparm *thee, Vio *sock) {
893 
894     char tok[VMAX_BUFSIZE];
895     int ti;
896 
897     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
898     if (sscanf(tok, "%i", &ti) == 0) {
899         Vnm_print(2, "NOsh:  Read non-integer (%s) while parsing ASYNC \
900 keyword!\n", tok);
901         return VRC_WARNING;
902     }
903     thee->async = ti;
904     thee->setasync = 1;
905     return VRC_SUCCESS;
906 
907     VERROR1:
908         Vnm_print(2, "parseMG:  ran out of tokens!\n");
909         return VRC_WARNING;
910 }
911 
MGparm_parseUSEAQUA(MGparm * thee,Vio * sock)912 VPRIVATE Vrc_Codes MGparm_parseUSEAQUA(MGparm *thee, Vio *sock) {
913     Vnm_print(0, "NOsh: parsed useaqua\n");
914     thee->useAqua = 1;
915     thee->setUseAqua = 1;
916     return VRC_SUCCESS;
917 }
918 
MGparm_parseToken(MGparm * thee,char tok[VMAX_BUFSIZE],Vio * sock)919 VPUBLIC Vrc_Codes MGparm_parseToken(MGparm *thee, char tok[VMAX_BUFSIZE],
920   Vio *sock) {
921 
922     if (thee == VNULL) {
923         Vnm_print(2, "parseMG:  got NULL thee!\n");
924         return VRC_WARNING;
925     }
926     if (sock == VNULL) {
927         Vnm_print(2, "parseMG:  got NULL socket!\n");
928         return VRC_WARNING;
929     }
930 
931     Vnm_print(0, "MGparm_parseToken:  trying %s...\n", tok);
932 
933 
934     if (Vstring_strcasecmp(tok, "dime") == 0) {
935         return MGparm_parseDIME(thee, sock);
936     } else if (Vstring_strcasecmp(tok, "chgm") == 0) {
937         return MGparm_parseCHGM(thee, sock);
938     } else if (Vstring_strcasecmp(tok, "nlev") == 0) {
939         Vnm_print(2, "Warning: The 'nlev' keyword is now deprecated!\n");
940         return MGparm_parseNLEV(thee, sock);
941     } else if (Vstring_strcasecmp(tok, "etol") == 0) {
942         return MGparm_parseETOL(thee, sock);
943     } else if (Vstring_strcasecmp(tok, "grid") == 0) {
944         return MGparm_parseGRID(thee, sock);
945     } else if (Vstring_strcasecmp(tok, "glen") == 0) {
946         return MGparm_parseGLEN(thee, sock);
947     } else if (Vstring_strcasecmp(tok, "gcent") == 0) {
948         return MGparm_parseGCENT(thee, sock);
949     } else if (Vstring_strcasecmp(tok, "cglen") == 0) {
950         return MGparm_parseCGLEN(thee, sock);
951     } else if (Vstring_strcasecmp(tok, "fglen") == 0) {
952         return MGparm_parseFGLEN(thee, sock);
953     } else if (Vstring_strcasecmp(tok, "cgcent") == 0) {
954         return MGparm_parseCGCENT(thee, sock);
955     } else if (Vstring_strcasecmp(tok, "fgcent") == 0) {
956         return MGparm_parseFGCENT(thee, sock);
957     } else if (Vstring_strcasecmp(tok, "pdime") == 0) {
958         return MGparm_parsePDIME(thee, sock);
959     } else if (Vstring_strcasecmp(tok, "ofrac") == 0) {
960         return MGparm_parseOFRAC(thee, sock);
961     } else if (Vstring_strcasecmp(tok, "async") == 0) {
962         return MGparm_parseASYNC(thee, sock);
963     } else if (Vstring_strcasecmp(tok, "gamma") == 0) {
964         return MGparm_parseGAMMA(thee, sock);
965     } else if (Vstring_strcasecmp(tok, "useaqua") == 0) {
966         return MGparm_parseUSEAQUA(thee, sock);
967     } else {
968         Vnm_print(2, "parseMG:  Unrecognized keyword (%s)!\n", tok);
969         return VRC_WARNING;
970     }
971 
972     return VRC_FAILURE;
973 
974 }
975