1 /**
2 *  @file    nosh.c
3  *  @ingroup NOsh
4  *  @author  Nathan Baker
5  *  @brief   Class NOsh 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 "nosh.h"
58 
59 VEMBED(rcsid="$Id$")
60 
61 
62 VPRIVATE int NOsh_parseREAD(
63                             NOsh *thee,
64                             Vio *sock);
65 
66 VPRIVATE int NOsh_parsePRINT(
67                              NOsh *thee,
68                              Vio *sock);
69 
70 VPRIVATE int NOsh_parseELEC(
71                             NOsh *thee,
72                             Vio *sock
73                             );
74 
75 VPRIVATE int NOsh_parseAPOLAR(
76                             NOsh *thee,
77                             Vio *sock
78                             );
79 
80 VEXTERNC int NOsh_parseFEM(
81                            NOsh *thee,
82                            Vio *sock,
83                            NOsh_calc *elec
84                            );
85 
86 VEXTERNC int NOsh_parseMG(
87                           NOsh *thee,
88                           Vio *sock,
89                           NOsh_calc *elec
90                           );
91 
92 VEXTERNC int NOsh_parseBEM(
93                           NOsh *thee,
94                           Vio *sock,
95                           NOsh_calc *elec
96                           );
97 
98 VEXTERNC int NOsh_parseGEOFLOW(
99                           NOsh *thee,
100                           Vio *sock,
101                           NOsh_calc *elec
102                           );
103 
104 VEXTERNC int NOsh_parsePBAM(
105                            NOsh *thee,
106                            Vio *sock,
107                            NOsh_calc *elec
108                            );
109 
110 VEXTERNC int NOsh_parsePBSAM(
111                              NOsh *thee,
112                              Vio *sock,
113                              NOsh_calc *elec
114                              );
115 
116 VEXTERNC int NOsh_parseAPOL(
117                            NOsh *thee,
118                            Vio *sock,
119                            NOsh_calc *elec
120                            );
121 
122 VPRIVATE int NOsh_setupCalcMG(
123                               NOsh *thee,
124                               NOsh_calc *elec
125                               );
126 
127 
128 VPRIVATE int NOsh_setupCalcMGAUTO(
129                                   NOsh *thee,
130                                   NOsh_calc *elec
131                                   );
132 
133 VPRIVATE int NOsh_setupCalcMGMANUAL(
134                                     NOsh *thee,
135                                     NOsh_calc *elec
136                                     );
137 
138 VPRIVATE int NOsh_setupCalcMGPARA(
139                                   NOsh *thee,
140                                   NOsh_calc *elec
141                                   );
142 
143 VPRIVATE int NOsh_setupCalcFEM(
144                                NOsh *thee,
145                                NOsh_calc *elec
146                                );
147 
148 VPRIVATE int NOsh_setupCalcFEMANUAL(
149                                NOsh *thee,
150                                NOsh_calc *elec
151                                );
152 
153 VPRIVATE int NOsh_setupCalcBEM(
154                               NOsh *thee,
155                               NOsh_calc *elec
156                               );
157 
158 VPRIVATE int NOsh_setupCalcGEOFLOW(
159                               NOsh *thee,
160                               NOsh_calc *elec
161                               );
162 
163 VPRIVATE int NOsh_setupCalcPBAM(
164                                 NOsh *thee,
165                                 NOsh_calc *elec
166                                 );
167 
168 VPRIVATE int NOsh_setupCalcPBSAM(
169                                  NOsh *thee,
170                                  NOsh_calc *elec
171                                  );
172 
173 VPRIVATE int NOsh_setupCalcBEMMANUAL(
174                               NOsh *thee,
175                               NOsh_calc *elec
176                               );
177 
178 VPRIVATE int NOsh_setupCalcGEOFLOWMANUAL(
179                               NOsh *thee,
180                               NOsh_calc *elec
181                               );
182 
183 VPRIVATE int NOsh_setupCalcPBAMAUTO(
184                                     NOsh *thee,
185                                     NOsh_calc *elec
186                                     );
187 
188 VPRIVATE int NOsh_setupCalcPBSAMAUTO(
189                                      NOsh *thee,
190                                      NOsh_calc *elec
191                                      );
192 
193 VPRIVATE int NOsh_setupCalcAPOL(
194                                 NOsh *thee,
195                                 NOsh_calc *elec
196                                 );
197 
198 #if !defined(VINLINE_NOSH)
199 
NOsh_getMolpath(NOsh * thee,int imol)200 VPUBLIC char* NOsh_getMolpath(NOsh *thee, int imol) {
201     VASSERT(thee != VNULL);
202     VASSERT(imol < thee->nmol);
203     return thee->molpath[imol];
204 }
NOsh_getDielXpath(NOsh * thee,int imol)205 VPUBLIC char* NOsh_getDielXpath(NOsh *thee, int imol) {
206     VASSERT(thee != VNULL);
207     VASSERT(imol < thee->nmol);
208     return thee->dielXpath[imol];
209 }
NOsh_getDielYpath(NOsh * thee,int imol)210 VPUBLIC char* NOsh_getDielYpath(NOsh *thee, int imol) {
211     VASSERT(thee != VNULL);
212     VASSERT(imol < thee->nmol);
213     return thee->dielYpath[imol];
214 }
NOsh_getDielZpath(NOsh * thee,int imol)215 VPUBLIC char* NOsh_getDielZpath(NOsh *thee, int imol) {
216     VASSERT(thee != VNULL);
217     VASSERT(imol < thee->nmol);
218     return thee->dielZpath[imol];
219 }
NOsh_getKappapath(NOsh * thee,int imol)220 VPUBLIC char* NOsh_getKappapath(NOsh *thee, int imol) {
221     VASSERT(thee != VNULL);
222     VASSERT(imol < thee->nmol);
223     return thee->kappapath[imol];
224 }
NOsh_getPotpath(NOsh * thee,int imol)225 VPUBLIC char* NOsh_getPotpath(NOsh *thee, int imol) {
226     VASSERT(thee != VNULL);
227     VASSERT(imol < thee->nmol);
228     return thee->potpath[imol];
229 }
NOsh_getChargepath(NOsh * thee,int imol)230 VPUBLIC char* NOsh_getChargepath(NOsh *thee, int imol) {
231     VASSERT(thee != VNULL);
232     VASSERT(imol < thee->nmol);
233     return thee->chargepath[imol];
234 }
NOsh_getCalc(NOsh * thee,int icalc)235 VPUBLIC NOsh_calc* NOsh_getCalc(NOsh *thee, int icalc) {
236     VASSERT(thee != VNULL);
237     VASSERT(icalc < thee->ncalc);
238     return thee->calc[icalc];
239 }
NOsh_getDielfmt(NOsh * thee,int i)240 VPUBLIC int NOsh_getDielfmt(NOsh *thee, int i) {
241     VASSERT(thee != VNULL);
242     VASSERT(i < thee->ndiel);
243     return (thee->dielfmt[i]);
244 }
NOsh_getKappafmt(NOsh * thee,int i)245 VPUBLIC int NOsh_getKappafmt(NOsh *thee, int i) {
246     VASSERT(thee != VNULL);
247     VASSERT(i < thee->nkappa);
248     return (thee->kappafmt[i]);
249 }
NOsh_getPotfmt(NOsh * thee,int i)250 VPUBLIC int NOsh_getPotfmt(NOsh *thee, int i) {
251     VASSERT(thee != VNULL);
252     VASSERT(i < thee->npot);
253     return (thee->potfmt[i]);
254 }
NOsh_getChargefmt(NOsh * thee,int i)255 VPUBLIC int NOsh_getChargefmt(NOsh *thee, int i) {
256     VASSERT(thee != VNULL);
257     VASSERT(i < thee->ncharge);
258     return (thee->chargefmt[i]);
259 }
260 
261 
262 #endif /* if !defined(VINLINE_NOSH) */
263 
NOsh_printWhat(NOsh * thee,int iprint)264 VPUBLIC NOsh_PrintType NOsh_printWhat(NOsh *thee, int iprint) {
265     VASSERT(thee != VNULL);
266     VASSERT(iprint < thee->nprint);
267     return thee->printwhat[iprint];
268 }
269 
NOsh_printNarg(NOsh * thee,int iprint)270 VPUBLIC int NOsh_printNarg(NOsh *thee, int iprint) {
271     VASSERT(thee != VNULL);
272     VASSERT(iprint < thee->nprint);
273     return thee->printnarg[iprint];
274 }
275 
NOsh_elec2calc(NOsh * thee,int icalc)276 VPUBLIC int NOsh_elec2calc(NOsh *thee, int icalc) {
277     VASSERT(thee != VNULL);
278     VASSERT(icalc < thee->ncalc);
279     return thee->elec2calc[icalc];
280 }
281 
NOsh_apol2calc(NOsh * thee,int icalc)282 VPUBLIC int NOsh_apol2calc(NOsh *thee, int icalc) {
283     VASSERT(thee != VNULL);
284     VASSERT(icalc < thee->ncalc);
285     return thee->apol2calc[icalc];
286 }
287 
NOsh_elecname(NOsh * thee,int ielec)288 VPUBLIC char* NOsh_elecname(NOsh *thee, int ielec) {
289     VASSERT(thee != VNULL);
290     VASSERT(ielec < thee->nelec + 1);
291     return thee->elecname[ielec];
292 }
293 
NOsh_printOp(NOsh * thee,int iprint,int iarg)294 VPUBLIC int NOsh_printOp(NOsh *thee, int iprint, int iarg) {
295     VASSERT(thee != VNULL);
296     VASSERT(iprint < thee->nprint);
297     VASSERT(iarg < thee->printnarg[iprint]);
298     return thee->printop[iprint][iarg];
299 }
300 
NOsh_printCalc(NOsh * thee,int iprint,int iarg)301 VPUBLIC int NOsh_printCalc(NOsh *thee, int iprint, int iarg) {
302     VASSERT(thee != VNULL);
303     VASSERT(iprint < thee->nprint);
304     VASSERT(iarg < thee->printnarg[iprint]);
305     return thee->printcalc[iprint][iarg];
306 }
307 
NOsh_ctor(int rank,int size)308 VPUBLIC NOsh* NOsh_ctor(int rank, int size) {
309 
310     /* Set up the structure */
311     NOsh *thee = VNULL;
312     thee = (NOsh*)Vmem_malloc(VNULL, 1, sizeof(NOsh) );
313     VASSERT( thee != VNULL);
314     VASSERT( NOsh_ctor2(thee, rank, size) );
315 
316     return thee;
317 }
318 
NOsh_ctor2(NOsh * thee,int rank,int size)319 VPUBLIC int NOsh_ctor2(NOsh *thee, int rank, int size) {
320 
321     int i;
322 
323     if (thee == VNULL) return 0;
324 
325     thee->proc_rank = rank;
326     thee->proc_size = size;
327 
328     thee->ispara = 0;
329     thee->parsed = 0;
330 
331     thee->nmol = 0;
332     thee->gotparm = 0;
333     thee->ncharge = 0;
334     thee->ndiel = 0;
335     thee->nkappa = 0;
336     thee->npot = 0;
337     thee->nprint = 0;
338 
339     for (i=0; i<NOSH_MAXCALC; i++) {
340         thee->calc[i] = VNULL;
341         thee->elec[i] = VNULL;
342         thee->apol[i] = VNULL;
343     }
344     for (i=0; i<NOSH_MAXMOL; i++) {
345         thee->alist[i] = VNULL;
346     }
347     thee->ncalc = 0;
348     thee->nelec = 0;
349     thee->napol = 0;
350 
351     return 1;
352 }
353 
NOsh_dtor(NOsh ** thee)354 VPUBLIC void NOsh_dtor(NOsh **thee) {
355     if ((*thee) != VNULL) {
356         NOsh_dtor2(*thee);
357         Vmem_free(VNULL, 1, sizeof(NOsh), (void **)thee);
358         (*thee) = VNULL;
359     }
360 }
361 
NOsh_dtor2(NOsh * thee)362 VPUBLIC void NOsh_dtor2(NOsh *thee) {
363 
364     int i;
365 
366     if (thee != VNULL) {
367         for (i=0; i<(thee->ncalc); i++) NOsh_calc_dtor(&(thee->calc[i]));
368         for (i=0; i<(thee->nelec); i++) NOsh_calc_dtor(&(thee->elec[i]));
369         for (i=0; i<(thee->napol); i++) NOsh_calc_dtor(&(thee->apol[i]));
370     }
371 
372 }
373 
NOsh_calc_ctor(NOsh_CalcType calctype)374 VPUBLIC NOsh_calc* NOsh_calc_ctor(
375                                   NOsh_CalcType calctype
376                                   ) {
377     NOsh_calc *thee;
378     thee = (NOsh_calc *)Vmem_malloc(VNULL, 1, sizeof(NOsh_calc));
379     thee->calctype = calctype;
380 
381     thee->mgparm = VNULL;
382     thee->femparm = VNULL;
383     thee->apolparm = VNULL;
384     thee->bemparm = VNULL;
385     thee->geoflowparm = VNULL;
386     thee->pbamparm = VNULL;
387     thee->pbsamparm = VNULL;
388 
389     switch (calctype) {
390         case NCT_MG:
391             thee->mgparm = MGparm_ctor(MCT_NONE);
392             break;
393         case NCT_FEM:
394             thee->femparm = FEMparm_ctor(FCT_NONE);
395             break;
396         case NCT_APOL:
397             thee->apolparm = APOLparm_ctor();
398             break;
399         case NCT_BEM:
400             thee->bemparm = BEMparm_ctor(BCT_MANUAL);
401             break;
402         case NCT_GEOFLOW:
403             thee->geoflowparm = GEOFLOWparm_ctor(GFCT_AUTO);
404             thee->apolparm = APOLparm_ctor();
405             break;
406         case NCT_PBAM:
407             thee->pbamparm = PBAMparm_ctor(PBAMCT_AUTO);
408             break;
409         case NCT_PBSAM:
410             thee->pbamparm = PBAMparm_ctor(PBAMCT_AUTO);
411             thee->pbsamparm = PBSAMparm_ctor(PBSAMCT_AUTO);
412             break;
413         default:
414             Vnm_print(2, "NOsh_calc_ctor:  unknown calculation type (%d)!\n",
415                       calctype);
416             VASSERT(0);
417     }
418     thee->pbeparm = PBEparm_ctor();
419 
420     return thee;
421 }
422 
NOsh_calc_dtor(NOsh_calc ** thee)423 VPUBLIC void NOsh_calc_dtor(
424                             NOsh_calc **thee
425                             ) {
426 
427     NOsh_calc *calc = VNULL;
428     calc = *thee;
429     if (calc == VNULL) return;
430 
431     switch (calc->calctype) {
432         case NCT_MG:
433             MGparm_dtor(&(calc->mgparm));
434             break;
435         case NCT_FEM:
436             FEMparm_dtor(&(calc->femparm));
437             break;
438         case NCT_APOL:
439             APOLparm_dtor(&(calc->apolparm));
440             break;
441         case NCT_BEM:
442             BEMparm_dtor(&(calc->bemparm));
443             break;
444         case NCT_GEOFLOW:
445             GEOFLOWparm_dtor(&(calc->geoflowparm));
446             APOLparm_dtor(&(calc->apolparm));
447             break;
448         case NCT_PBAM:
449             PBAMparm_dtor(&(calc->pbamparm));
450             break;
451         case NCT_PBSAM:
452             PBAMparm_dtor(&(calc->pbamparm));
453             PBSAMparm_dtor(&(calc->pbsamparm));
454             break;
455         default:
456             Vnm_print(2, "NOsh_calc_ctor:  unknown calculation type (%d)!\n",
457                       calc->calctype);
458             VASSERT(0);
459     }
460     PBEparm_dtor(&(calc->pbeparm));
461 
462     Vmem_free(VNULL, 1, sizeof(NOsh_calc), (void **)thee);
463     calc = VNULL;
464 
465 }
466 
NOsh_calc_copy(NOsh_calc * thee,NOsh_calc * source)467 VPUBLIC int NOsh_calc_copy(
468                            NOsh_calc *thee,
469                            NOsh_calc *source
470                            ) {
471 
472     VASSERT(thee != VNULL);
473     VASSERT(source != VNULL);
474     VASSERT(thee->calctype == source->calctype);
475     if (source->mgparm != VNULL)
476         MGparm_copy(thee->mgparm, source->mgparm);
477     if (source->femparm != VNULL)
478         FEMparm_copy(thee->femparm, source->femparm);
479     if (source->bemparm != VNULL)
480         BEMparm_copy(thee->bemparm, source->bemparm);
481     if (source->pbeparm != VNULL)
482         PBEparm_copy(thee->pbeparm, source->pbeparm);
483     if (source->apolparm != VNULL)
484         APOLparm_copy(thee->apolparm, source->apolparm);
485     /*I think here is where the the geoflow changes get lost*/
486     if(source->geoflowparm != VNULL)
487     	GEOFLOWparm_copy(thee->geoflowparm, source->geoflowparm);
488     if(source->pbamparm != VNULL)
489       PBAMparm_copy(thee->pbamparm, source->pbamparm);
490     if(source->pbsamparm != VNULL)
491       PBSAMparm_copy(thee->pbsamparm, source->pbsamparm);
492 
493 
494     return 1;
495 
496 }
497 
NOsh_parseInputFile(NOsh * thee,char * filename)498 VPUBLIC int NOsh_parseInputFile(
499                                 NOsh *thee,
500                                 char *filename
501                                 ) {
502 
503     Vio *sock;
504     int rc;
505 
506     sock = Vio_ctor("FILE", "ASC", VNULL, filename, "r");
507     rc = NOsh_parseInput(thee, sock);
508     Vio_dtor(&sock);
509 
510     return rc;
511 }
512 
NOsh_parseInput(NOsh * thee,Vio * sock)513 VPUBLIC int NOsh_parseInput(
514                             NOsh *thee,
515                             Vio *sock
516                             ) {
517 
518     char *MCwhiteChars = " =,;\t\r\n";
519     char *MCcommChars  = "#%";
520     char tok[VMAX_BUFSIZE];
521 
522     if (thee == VNULL) {
523         Vnm_print(2, "NOsh_parseInput:  Got NULL thee!\n");
524         return 0;
525     }
526 
527     if (sock == VNULL) {
528         Vnm_print(2, "NOsh_parseInput:  Got pointer to NULL socket!\n");
529         Vnm_print(2, "NOsh_parseInput:  The specified input file was not found!\n");
530         return 0;
531     }
532 
533     if (thee->parsed) {
534         Vnm_print(2, "NOsh_parseInput:  Already parsed an input file!\n");
535         return 0;
536     }
537 
538     if (Vio_accept(sock, 0) < 0) {
539         Vnm_print(2, "NOsh_parseInput:  Problem reading from socket!\n");
540         return 0;
541     }
542 
543     /* Set up the whitespace and comment character definitions */
544     Vio_setWhiteChars(sock, MCwhiteChars);
545     Vio_setCommChars(sock, MCcommChars);
546 
547     /* We parse the file until we run out of tokens */
548     Vnm_print(0, "NOsh_parseInput:  Starting file parsing...\n");
549     while (Vio_scanf(sock, "%s", tok) == 1) {
550         /* At the highest level, we look for keywords that indicate functions like:
551 
552         read => Read in a molecule file
553         elec => Do an electrostatics calculation
554         print => Print some results
555         apolar => do a non-polar calculation
556         quit => Quit
557 
558         These cause the code to go to a lower-level parser routine which
559         handles keywords specific to the particular function.  Each
560         lower-level parser routine then returns when it hits the "end"
561         keyword.  Due to this simple layout, no nesting of these "function"
562         sections is allowed.
563         */
564         if (Vstring_strcasecmp(tok, "read") == 0) {
565           //           printf("read\n");
566             Vnm_print(0, "NOsh: Parsing READ section\n");
567             if (!NOsh_parseREAD(thee, sock)) return 0;
568             Vnm_print(0, "NOsh: Done parsing READ section \
569 (nmol=%d, ndiel=%d, nkappa=%d, ncharge=%d, npot=%d)\n", thee->nmol, thee->ndiel,
570                       thee->nkappa, thee->ncharge,thee->npot);
571         } else if (Vstring_strcasecmp(tok, "print") == 0) {
572             Vnm_print(0, "NOsh: Parsing PRINT section\n");
573             if (!NOsh_parsePRINT(thee, sock)) return 0;
574             Vnm_print(0, "NOsh: Done parsing PRINT section\n");
575         } else if (Vstring_strcasecmp(tok, "elec") == 0) {
576             Vnm_print(0, "NOsh: Parsing ELEC section\n");
577             if (!NOsh_parseELEC(thee, sock)) return 0;
578             Vnm_print(0, "NOsh: Done parsing ELEC section (nelec = %d)\n",
579                       thee->nelec);
580         } else if (Vstring_strcasecmp(tok, "apolar") == 0) {
581             Vnm_print(0, "NOsh: Parsing APOLAR section\n");
582             if (!NOsh_parseAPOLAR(thee, sock)) return 0;
583             Vnm_print(0, "NOsh: Done parsing APOLAR section (nelec = %d)\n",
584                       thee->nelec);
585         } else if (Vstring_strcasecmp(tok, "quit") == 0) {
586             Vnm_print(0, "NOsh: Done parsing file (got QUIT)\n");
587             break;
588         } else {
589             Vnm_print(2, "NOsh_parseInput: Ignoring undefined keyword %s!\n", tok);
590         }
591     }
592 
593     thee->parsed = 1;
594     return 1;
595 
596 }
597 
NOsh_parseREAD_MOL(NOsh * thee,Vio * sock)598 VPRIVATE int NOsh_parseREAD_MOL(NOsh *thee, Vio *sock) {
599 
600     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
601     NOsh_MolFormat molfmt;
602 
603     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
604     if (Vstring_strcasecmp(tok, "pqr") == 0) {
605         molfmt = NMF_PQR;
606         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
607         if (tok[0]=='"') {
608             strcpy(strnew, "");
609             while (tok[strlen(tok)-1] != '"') {
610                 strcat(str, tok);
611                 strcat(str, " ");
612                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
613             }
614             strcat(str, tok);
615             strncpy(strnew, str+1, strlen(str)-2);
616             strcpy(tok, strnew);
617         }
618         Vnm_print(0, "NOsh: Storing molecule %d path %s\n",
619                   thee->nmol, tok);
620         thee->molfmt[thee->nmol] = molfmt;
621         strncpy(thee->molpath[thee->nmol], tok, VMAX_ARGLEN);
622         (thee->nmol)++;
623     } else if (Vstring_strcasecmp(tok, "pdb") == 0) {
624         molfmt = NMF_PDB;
625         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
626         if (tok[0]=='"') {
627             strcpy(strnew, "");
628             while (tok[strlen(tok)-1] != '"') {
629                 strcat(str, tok);
630                 strcat(str, " ");
631                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
632             }
633             strcat(str, tok);
634             strncpy(strnew, str+1, strlen(str)-2);
635             strcpy(tok, strnew);
636         }
637         Vnm_print(0, "NOsh: Storing molecule %d path %s\n",
638                   thee->nmol, tok);
639         thee->molfmt[thee->nmol] = molfmt;
640         strncpy(thee->molpath[thee->nmol], tok, VMAX_ARGLEN);
641         (thee->nmol)++;
642     } else if (Vstring_strcasecmp(tok, "xml") == 0) {
643         molfmt = NMF_XML;
644         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
645         if (tok[0]=='"') {
646             strcpy(strnew, "");
647             while (tok[strlen(tok)-1] != '"') {
648                 strcat(str, tok);
649                 strcat(str, " ");
650                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
651             }
652             strcat(str, tok);
653             strncpy(strnew, str+1, strlen(str)-2);
654             strcpy(tok, strnew);
655         }
656         Vnm_print(0, "NOsh: Storing molecule %d path %s\n",
657                   thee->nmol, tok);
658         thee->molfmt[thee->nmol] = molfmt;
659         strncpy(thee->molpath[thee->nmol], tok, VMAX_ARGLEN);
660         (thee->nmol)++;
661     } else {
662         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined mol format \
663 %s!\n", tok);
664     }
665 
666     return 1;
667 
668 
669 VERROR1:
670         Vnm_print(2, "NOsh_parseREAD_MOL:  Ran out of tokens while parsing READ section!\n");
671     return 0;
672 
673 }
674 
NOsh_parseREAD_PARM(NOsh * thee,Vio * sock)675 VPRIVATE int NOsh_parseREAD_PARM(NOsh *thee, Vio *sock) {
676 
677     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
678     NOsh_ParmFormat parmfmt;
679 
680     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
681     if (Vstring_strcasecmp(tok, "flat") == 0) {
682         parmfmt = NPF_FLAT;
683         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
684         if (tok[0]=='"') {
685             strcpy(strnew, "");
686             while (tok[strlen(tok)-1] != '"') {
687                 strcat(str, tok);
688                 strcat(str, " ");
689                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
690             }
691             strcat(str, tok);
692             strncpy(strnew, str+1, strlen(str)-2);
693             strcpy(tok, strnew);
694         }
695         if (thee->gotparm) {
696             Vnm_print(2, "NOsh:  Hey!  You already specified a parameterfile (%s)!\n", thee->parmpath);
697             Vnm_print(2, "NOsh:  I'm going to ignore this one (%s)!\n", tok);
698         } else {
699             thee->parmfmt = parmfmt;
700             thee->gotparm = 1;
701             strncpy(thee->parmpath, tok, VMAX_ARGLEN);
702         }
703     } else if(Vstring_strcasecmp(tok, "xml") == 0) {
704         parmfmt = NPF_XML;
705         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
706         if (tok[0]=='"') {
707             strcpy(strnew, "");
708             while (tok[strlen(tok)-1] != '"') {
709                 strcat(str, tok);
710                 strcat(str, " ");
711                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
712             }
713             strcat(str, tok);
714             strncpy(strnew, str+1, strlen(str)-2);
715             strcpy(tok, strnew);
716         }
717         if (thee->gotparm) {
718             Vnm_print(2, "NOsh:  Hey!  You already specified a parameterfile (%s)!\n", thee->parmpath);
719             Vnm_print(2, "NOsh:  I'm going to ignore this one (%s)!\n", tok);
720         } else {
721             thee->parmfmt = parmfmt;
722             thee->gotparm = 1;
723             strncpy(thee->parmpath, tok, VMAX_ARGLEN);
724         }
725 
726     } else {
727         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined parm format \
728 %s!\n", tok);
729     }
730 
731     return 1;
732 
733 VERROR1:
734         Vnm_print(2, "NOsh_parseREAD_PARM:  Ran out of tokens while parsing READ section!\n");
735     return 0;
736 
737 }
738 
NOsh_parseREAD_DIEL(NOsh * thee,Vio * sock)739 VPRIVATE int NOsh_parseREAD_DIEL(NOsh *thee, Vio *sock) {
740 
741     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
742     Vdata_Format dielfmt;
743 
744     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
745     if (Vstring_strcasecmp(tok, "dx") == 0) {
746         dielfmt = VDF_DX;
747     //added VDF_BIN to take binary files.
748     } else if (Vstring_strcasecmp(tok, "dxbin") == 0){
749     	dielfmt = VDF_DXBIN;
750     }else if (Vstring_strcasecmp(tok, "gz") == 0) {
751         dielfmt = VDF_GZ;
752     } else {
753         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined format \
754                   %s!\n", tok);
755         return VRC_FAILURE;
756     }
757 
758     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
759     if (tok[0]=='"') {
760         strcpy(strnew, "");
761         while (tok[strlen(tok)-1] != '"') {
762             strcat(str, tok);
763             strcat(str, " ");
764             VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
765         }
766         strcat(str, tok);
767         strncpy(strnew, str+1, strlen(str)-2);
768         strcpy(tok, strnew);
769     }
770     Vnm_print(0, "NOsh: Storing x-shifted dielectric map %d path \
771               %s\n", thee->ndiel, tok);
772     strncpy(thee->dielXpath[thee->ndiel], tok, VMAX_ARGLEN);
773     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
774     Vnm_print(0, "NOsh: Storing y-shifted dielectric map %d path \
775               %s\n", thee->ndiel, tok);
776     strncpy(thee->dielYpath[thee->ndiel], tok, VMAX_ARGLEN);
777     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
778     Vnm_print(0, "NOsh: Storing z-shifted dielectric map %d path \
779               %s\n", thee->ndiel, tok);
780     strncpy(thee->dielZpath[thee->ndiel], tok, VMAX_ARGLEN);
781     thee->dielfmt[thee->ndiel] = dielfmt;
782     (thee->ndiel)++;
783 
784     return 1;
785 
786 VERROR1:
787         Vnm_print(2, "NOsh_parseREAD_DIEL:  Ran out of tokens while parsing READ \
788 section!\n");
789     return 0;
790 
791 }
792 
NOsh_parseREAD_KAPPA(NOsh * thee,Vio * sock)793 VPRIVATE int NOsh_parseREAD_KAPPA(NOsh *thee, Vio *sock) {
794 
795     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
796     Vdata_Format kappafmt;
797 
798     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
799     if (Vstring_strcasecmp(tok, "dx") == 0) {
800         kappafmt = VDF_DX;
801     } else if (Vstring_strcasecmp(tok, "gz") == 0) {
802         kappafmt = VDF_GZ;
803     } else if (Vstring_strcasecmp(tok,"dxbin") == 0) {
804     	kappafmt = VDF_DXBIN;
805     } else {
806 
807         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined format \
808                   %s!\n", tok);
809         return VRC_FAILURE;
810     }
811 
812     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
813     if (tok[0]=='"') {
814         strcpy(strnew, "");
815         while (tok[strlen(tok)-1] != '"') {
816             strcat(str, tok);
817             strcat(str, " ");
818             VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
819         }
820         strcat(str, tok);
821         strncpy(strnew, str+1, strlen(str)-2);
822         strcpy(tok, strnew);
823     }
824     Vnm_print(0, "NOsh: Storing kappa map %d path %s\n",
825               thee->nkappa, tok);
826     thee->kappafmt[thee->nkappa] = kappafmt;
827     strncpy(thee->kappapath[thee->nkappa], tok, VMAX_ARGLEN);
828     (thee->nkappa)++;
829 
830     return 1;
831 
832 VERROR1:
833         Vnm_print(2, "NOsh_parseREAD:  Ran out of tokens while parsing READ \
834 section!\n");
835     return 0;
836 
837 }
838 
NOsh_parseREAD_POTENTIAL(NOsh * thee,Vio * sock)839 VPRIVATE int NOsh_parseREAD_POTENTIAL(NOsh *thee, Vio *sock) {
840 
841     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
842     Vdata_Format potfmt;
843 
844     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
845     if (Vstring_strcasecmp(tok, "dx") == 0) {
846         potfmt = VDF_DX;
847     } else if (Vstring_strcasecmp(tok, "gz") == 0) {
848         potfmt = VDF_GZ;
849     } else if(Vstring_strcasecmp(tok, "dxbin") == 0){
850     	potfmt = VDF_DXBIN;
851     } else {
852         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined format \
853                   %s!\n", tok);
854         return VRC_FAILURE;
855    }
856 
857     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
858     if (tok[0]=='"') {
859         strcpy(strnew, "");
860         while (tok[strlen(tok)-1] != '"') {
861             strcat(str, tok);
862             strcat(str, " ");
863             VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
864         }
865         strcat(str, tok);
866         strncpy(strnew, str+1, strlen(str)-2);
867         strcpy(tok, strnew);
868     }
869     Vnm_print(0, "NOsh: Storing potential map %d path %s\n",
870               thee->npot, tok);
871     thee->potfmt[thee->npot] = potfmt;
872     strncpy(thee->potpath[thee->npot], tok, VMAX_ARGLEN);
873     (thee->npot)++;
874 
875     return 1;
876 
877 VERROR1:
878     Vnm_print(2, "NOsh_parseREAD:  Ran out of tokens while parsing READ \
879               section!\n");
880     return 0;
881 
882 }
883 
NOsh_parseREAD_CHARGE(NOsh * thee,Vio * sock)884 VPRIVATE int NOsh_parseREAD_CHARGE(NOsh *thee, Vio *sock) {
885 
886     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
887     Vdata_Format chargefmt;
888 
889     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
890     if (Vstring_strcasecmp(tok, "dx") == 0) {
891         chargefmt = VDF_DX;
892     }
893     else if(Vstring_strcasecmp(tok, "dxbin") == 0){
894     	chargefmt = VDF_DXBIN;
895     }else if (Vstring_strcasecmp(tok, "gz") == 0) {
896         chargefmt = VDF_GZ;
897     } else {
898         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined format \
899                   %s!\n", tok);
900         return VRC_FAILURE;
901     }
902 
903     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
904     if (tok[0]=='"') {
905         strcpy(strnew, "");
906         while (tok[strlen(tok)-1] != '"') {
907             strcat(str, tok);
908             strcat(str, " ");
909             VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
910         }
911         strcat(str, tok);
912         strncpy(strnew, str+1, strlen(str)-2);
913         strcpy(tok, strnew);
914     }
915     Vnm_print(0, "NOsh: Storing charge map %d path %s\n",
916               thee->ncharge, tok);
917     thee->chargefmt[thee->ncharge] = chargefmt;
918     strncpy(thee->chargepath[thee->ncharge], tok, VMAX_ARGLEN);
919     (thee->ncharge)++;
920 
921     return 1;
922 
923 VERROR1:
924         Vnm_print(2, "NOsh_parseREAD:  Ran out of tokens while parsing READ \
925 section!\n");
926     return 0;
927 
928 }
929 
NOsh_parseREAD_MESH(NOsh * thee,Vio * sock)930 VPRIVATE int NOsh_parseREAD_MESH(NOsh *thee, Vio *sock) {
931 
932     char tok[VMAX_BUFSIZE], str[VMAX_BUFSIZE]="", strnew[VMAX_BUFSIZE]="";
933     Vdata_Format meshfmt;
934 
935     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
936     if (Vstring_strcasecmp(tok, "mcsf") == 0) {
937         meshfmt = VDF_MCSF;
938         VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
939         if (tok[0]=='"') {
940             strcpy(strnew, "");
941             while (tok[strlen(tok)-1] != '"') {
942                 strcat(str, tok);
943                 strcat(str, " ");
944                 VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
945             }
946             strcat(str, tok);
947             strncpy(strnew, str+1, strlen(str)-2);
948             strcpy(tok, strnew);
949         }
950         Vnm_print(0, "NOsh: Storing mesh %d path %s\n",
951                   thee->nmesh, tok);
952         thee->meshfmt[thee->nmesh] = meshfmt;
953         strncpy(thee->meshpath[thee->nmesh], tok, VMAX_ARGLEN);
954         (thee->nmesh)++;
955     } else {
956         Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined mesh format \
957                   %s!\n", tok);
958     }
959 
960     return 1;
961 
962 VERROR1:
963     Vnm_print(2, "NOsh_parseREAD:  Ran out of tokens while parsing READ \
964               section!\n");
965     return 0;
966 
967 }
968 
969 
NOsh_parseREAD(NOsh * thee,Vio * sock)970 VPRIVATE int NOsh_parseREAD(NOsh *thee, Vio *sock) {
971 
972     char tok[VMAX_BUFSIZE];
973 
974     if (thee == VNULL) {
975         Vnm_print(2, "NOsh_parseREAD:  Got NULL thee!\n");
976         return 0;
977     }
978 
979     if (sock == VNULL) {
980         Vnm_print(2, "NOsh_parseREAD:  Got pointer to NULL socket!\n");
981         return 0;
982     }
983 
984     if (thee->parsed) {
985         Vnm_print(2, "NOsh_parseREAD:  Already parsed an input file!\n");
986         return 0;
987     }
988 
989     /* Read until we run out of tokens (bad) or hit the "END" keyword (good) */
990     while (Vio_scanf(sock, "%s", tok) == 1) {
991         if (Vstring_strcasecmp(tok, "end") == 0) {
992             Vnm_print(0, "NOsh: Done parsing READ section\n");
993             return 1;
994         } else if (Vstring_strcasecmp(tok, "mol") == 0) {
995             NOsh_parseREAD_MOL(thee, sock);
996         } else if (Vstring_strcasecmp(tok, "parm") == 0) {
997             NOsh_parseREAD_PARM(thee,sock);
998         } else if (Vstring_strcasecmp(tok, "diel") == 0) {
999             NOsh_parseREAD_DIEL(thee,sock);
1000         } else if (Vstring_strcasecmp(tok, "kappa") == 0) {
1001             NOsh_parseREAD_KAPPA(thee,sock);
1002         } else if (Vstring_strcasecmp(tok, "pot") == 0) {
1003             NOsh_parseREAD_POTENTIAL(thee,sock);
1004         } else if (Vstring_strcasecmp(tok, "charge") == 0) {
1005             NOsh_parseREAD_CHARGE(thee,sock);
1006         } else if (Vstring_strcasecmp(tok, "mesh") == 0) {
1007             NOsh_parseREAD_MESH(thee,sock);
1008         } else {
1009             Vnm_print(2, "NOsh_parseREAD:  Ignoring undefined keyword %s!\n",
1010                       tok);
1011         }
1012     }
1013 
1014     /* We ran out of tokens! */
1015     Vnm_print(2, "NOsh_parseREAD:  Ran out of tokens while parsing READ \
1016 section!\n");
1017     return 0;
1018 
1019 }
1020 
NOsh_parsePRINT(NOsh * thee,Vio * sock)1021 VPRIVATE int NOsh_parsePRINT(NOsh *thee, Vio *sock) {
1022 
1023     char tok[VMAX_BUFSIZE];
1024     char name[VMAX_BUFSIZE];
1025     int ti, idx, expect, ielec, iapol;
1026 
1027     if (thee == VNULL) {
1028         Vnm_print(2, "NOsh_parsePRINT:  Got NULL thee!\n");
1029         return 0;
1030     }
1031 
1032     if (sock == VNULL) {
1033         Vnm_print(2, "NOsh_parsePRINT:  Got pointer to NULL socket!\n");
1034         return 0;
1035     }
1036 
1037     if (thee->parsed) {
1038         Vnm_print(2, "NOsh_parsePRINT:  Already parsed an input file!\n");
1039         return 0;
1040     }
1041 
1042     idx = thee->nprint;
1043     if (thee->nprint >= NOSH_MAXPRINT) {
1044         Vnm_print(2, "NOsh_parsePRINT:  Exceeded max number (%d) of PRINT \
1045 sections\n",
1046                   NOSH_MAXPRINT);
1047         return 0;
1048     }
1049 
1050 
1051     /* The first thing we read is the thing we want to print */
1052     VJMPERR1(Vio_scanf(sock, "%s", tok) == 1);
1053     if (Vstring_strcasecmp(tok, "energy") == 0) {
1054         thee->printwhat[idx] = NPT_ENERGY;
1055         thee->printnarg[idx] = 0;
1056     } else if (Vstring_strcasecmp(tok, "force") == 0) {
1057         thee->printwhat[idx] = NPT_FORCE;
1058         thee->printnarg[idx] = 0;
1059     } else if (Vstring_strcasecmp(tok, "elecEnergy") == 0) {
1060         thee->printwhat[idx] = NPT_ELECENERGY;
1061         thee->printnarg[idx] = 0;
1062     } else if (Vstring_strcasecmp(tok, "elecForce") == 0) {
1063         thee->printwhat[idx] = NPT_ELECFORCE;
1064         thee->printnarg[idx] = 0;
1065     } else if (Vstring_strcasecmp(tok, "apolEnergy") == 0) {
1066         thee->printwhat[idx] = NPT_APOLENERGY;
1067         thee->printnarg[idx] = 0;
1068     } else if (Vstring_strcasecmp(tok, "apolForce") == 0) {
1069         thee->printwhat[idx] = NPT_APOLFORCE;
1070         thee->printnarg[idx] = 0;
1071     } else {
1072         Vnm_print(2, "NOsh_parsePRINT:  Undefined keyword %s while parsing \
1073 PRINT section!\n", tok);
1074         return 0;
1075     }
1076 
1077     expect = 0;   /* We first expect a calculation ID (0) then an op (1) */
1078 
1079     /* Read until we run out of tokens (bad) or hit the "END" keyword (good) */
1080     while (Vio_scanf(sock, "%s", tok) == 1) {
1081 
1082         /* The next thing we read is either END or an ARG OP ARG statement */
1083         if (Vstring_strcasecmp(tok, "end") == 0) {
1084             if (expect != 0) {
1085                 (thee->nprint)++;
1086                 (thee->printnarg[idx])++;
1087                 Vnm_print(0, "NOsh: Done parsing PRINT section\n");
1088                 return 1;
1089             } else {
1090                 Vnm_print(2, "NOsh_parsePRINT:  Got premature END to PRINT!\n");
1091                 return 0;
1092             }
1093         } else {
1094 
1095             /* Grab a calculation ID */
1096             if ((sscanf(tok, "%d", &ti) == 1) &&
1097                 (Vstring_isdigit(tok) == 1)) {
1098                 if (expect == 0) {
1099                     thee->printcalc[idx][thee->printnarg[idx]] = ti-1;
1100                     expect = 1;
1101                 } else {
1102                     Vnm_print(2, "NOsh_parsePRINT:  Syntax error in PRINT \
1103 section while reading %s!\n", tok);
1104                     return 0;
1105                 }
1106                 /* Grab addition operation */
1107             } else if (Vstring_strcasecmp(tok, "+") == 0) {
1108                 if (expect == 1) {
1109                     thee->printop[idx][thee->printnarg[idx]] = 0;
1110                     (thee->printnarg[idx])++;
1111                     expect = 0;
1112                     if (thee->printnarg[idx] >= NOSH_MAXPOP) {
1113                         Vnm_print(2, "NOsh_parsePRINT:  Exceeded max number \
1114 (%d) of arguments for PRINT section!\n",
1115                                   NOSH_MAXPOP);
1116                         return 0;
1117                     }
1118                 } else {
1119                     Vnm_print(2, "NOsh_parsePRINT:  Syntax error in PRINT \
1120 section while reading %s!\n", tok);
1121                     return 0;
1122                 }
1123                 /* Grab subtraction operation */
1124             } else if (Vstring_strcasecmp(tok, "-") == 0) {
1125                 if (expect == 1) {
1126                     thee->printop[idx][thee->printnarg[idx]] = 1;
1127                     (thee->printnarg[idx])++;
1128                     expect = 0;
1129                     if (thee->printnarg[idx] >= NOSH_MAXPOP) {
1130                         Vnm_print(2, "NOsh_parseREAD:  Exceeded max number \
1131 (%d) of arguments for PRINT section!\n",
1132                                   NOSH_MAXPOP);
1133                         return 0;
1134                     }
1135                 } else {
1136                     Vnm_print(2, "NOsh_parsePRINT:  Syntax error in PRINT \
1137 section while reading %s!\n", tok);
1138                     return 0;
1139                 }
1140                 /* Grab a calculation name from elec ID */
1141             } else if (sscanf(tok, "%s", name) == 1) {
1142                 if (expect == 0) {
1143                     for (ielec=0; ielec<thee->nelec; ielec++) {
1144                         if (Vstring_strcasecmp(thee->elecname[ielec], name) == 0) {
1145                             thee->printcalc[idx][thee->printnarg[idx]] = ielec;
1146                             expect = 1;
1147                             break;
1148                         }
1149                     }
1150                     for (iapol=0; iapol<thee->napol; iapol++) {
1151                         if (Vstring_strcasecmp(thee->apolname[iapol], name) == 0) {
1152                             thee->printcalc[idx][thee->printnarg[idx]] = iapol;
1153                             expect = 1;
1154                             break;
1155                         }
1156                     }
1157                     if (expect == 0) {
1158                         Vnm_print(2, "No ELEC or APOL statement has been named %s!\n",
1159                                   name);
1160                         return 0;
1161                     }
1162                 } else {
1163                     Vnm_print(2, "NOsh_parsePRINT:  Syntax error in PRINT \
1164 section while reading %s!\n", tok);
1165                     return 0;
1166                 }
1167                 /* Got bad operation */
1168             } else {
1169                 Vnm_print(2, "NOsh_parsePRINT:  Undefined keyword %s while \
1170 parsing PRINT section!\n", tok);
1171                 return 0;
1172             }
1173         } /* end parse token */
1174 
1175     } /* end while */
1176 
1177     VJMPERR1(0);
1178 
1179     /* We ran out of tokens! */
1180 VERROR1:
1181        Vnm_print(2, "NOsh_parsePRINT:  Ran out of tokens while parsing PRINT \
1182 section!\n");
1183        return 0;
1184 
1185 }
1186 
NOsh_parseELEC(NOsh * thee,Vio * sock)1187 VPRIVATE int NOsh_parseELEC(NOsh *thee, Vio *sock) {
1188 
1189     NOsh_calc *calc = VNULL;
1190 
1191     char tok[VMAX_BUFSIZE];
1192 
1193     if (thee == VNULL) {
1194         Vnm_print(2, "NOsh_parseELEC:  Got NULL thee!\n");
1195         return 0;
1196     }
1197 
1198     if (sock == VNULL) {
1199         Vnm_print(2, "NOsh_parseELEC:  Got pointer to NULL socket!\n");
1200         return 0;
1201     }
1202 
1203     if (thee->parsed) {
1204         Vnm_print(2, "NOsh_parseELEC:  Already parsed an input file!\n");
1205         return 0;
1206     }
1207 
1208     /* Get a pointer to the latest ELEC calc object and update the ELEC
1209         statement number */
1210     if (thee->nelec >= NOSH_MAXCALC) {
1211         Vnm_print(2, "NOsh:  Too many electrostatics calculations in this \
1212 run!\n");
1213         Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
1214                   NOSH_MAXCALC);
1215         return 1;
1216     }
1217 
1218     /* The next token HAS to be the method OR "name" */
1219     if (Vio_scanf(sock, "%s", tok) == 1) {
1220         if (Vstring_strcasecmp(tok, "name") == 0) {
1221             Vio_scanf(sock, "%s", tok);
1222             strncpy(thee->elecname[thee->nelec], tok, VMAX_ARGLEN);
1223             if (Vio_scanf(sock, "%s", tok) != 1) {
1224                 Vnm_print(2, "NOsh_parseELEC:  Ran out of tokens while reading \
1225 ELEC section!\n");
1226                 return 0;
1227             }
1228         }
1229         if (Vstring_strcasecmp(tok, "mg-manual") == 0) {
1230             thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_MG);
1231             calc = thee->elec[thee->nelec];
1232             (thee->nelec)++;
1233             calc->mgparm->type = MCT_MANUAL;
1234             return NOsh_parseMG(thee, sock, calc);
1235         } else if (Vstring_strcasecmp(tok, "mg-auto") == 0) {
1236             thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_MG);
1237             calc = thee->elec[thee->nelec];
1238             (thee->nelec)++;
1239             calc->mgparm->type = MCT_AUTO;
1240             return NOsh_parseMG(thee, sock, calc);
1241         } else if (Vstring_strcasecmp(tok, "mg-para") == 0) {
1242             thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_MG);
1243             calc = thee->elec[thee->nelec];
1244             (thee->nelec)++;
1245             calc->mgparm->type = MCT_PARALLEL;
1246             return NOsh_parseMG(thee, sock, calc);
1247         } else if (Vstring_strcasecmp(tok, "mg-dummy") == 0) {
1248             thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_MG);
1249             calc = thee->elec[thee->nelec];
1250             (thee->nelec)++;
1251             calc->mgparm->type = MCT_DUMMY;
1252             return NOsh_parseMG(thee, sock, calc);
1253         } else if (Vstring_strcasecmp(tok, "fe-manual") == 0) {
1254             thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_FEM);
1255             calc = thee->elec[thee->nelec];
1256             (thee->nelec)++;
1257             calc->femparm->type = FCT_MANUAL;
1258             return NOsh_parseFEM(thee, sock, calc);
1259         } else if (Vstring_strcasecmp(tok, "tabi") == 0) {
1260             thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_BEM);
1261             calc = thee->elec[thee->nelec];
1262             (thee->nelec)++;
1263             calc->bemparm->type = BCT_MANUAL;
1264             return NOsh_parseBEM(thee, sock, calc);
1265         } else if (Vstring_strcasecmp(tok, "bem") == 0) {
1266             thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_BEM);
1267             calc = thee->elec[thee->nelec];
1268             (thee->nelec)++;
1269             calc->bemparm->type = BCT_MANUAL;
1270             return NOsh_parseBEM(thee, sock, calc);
1271         } else if (Vstring_strcasecmp(tok, "bem-manual") == 0) {
1272             thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_BEM);
1273             calc = thee->elec[thee->nelec];
1274             (thee->nelec)++;
1275             calc->bemparm->type = BCT_MANUAL;
1276             return NOsh_parseBEM(thee, sock, calc);
1277         } else if (Vstring_strcasecmp(tok, "geoflow-manual") == 0) {
1278         	Vnm_print(2, "Geoflow currently does not support geoflow-manual please use geoflow instead!\n");
1279         	return 0;
1280         } else if(Vstring_strcasecmp(tok, "geoflow-none") == 0) {
1281         	Vnm_print(2, "Geoflow currently does not support geoflow-none please use geoflow instead!\n");
1282         	return 0;
1283         } else if (Vstring_strcasecmp(tok, "geoflow") == 0) {
1284             thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_GEOFLOW);
1285             calc = thee->elec[thee->nelec];
1286             (thee->nelec)++;
1287             calc->geoflowparm->type = GFCT_AUTO;
1288             return NOsh_parseGEOFLOW(thee, sock, calc);
1289         } else if (Vstring_strcasecmp(tok, "pbam") == 0) {
1290             thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_PBAM);
1291             calc = thee->elec[thee->nelec];
1292             (thee->nelec)++;
1293             calc->pbamparm->type = PBAMCT_AUTO;
1294             return NOsh_parsePBAM(thee, sock, calc);
1295         } else if (Vstring_strcasecmp(tok, "pbsam") == 0) {
1296             thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_PBSAM);
1297             calc = thee->elec[thee->nelec];
1298             (thee->nelec)++;
1299             calc->pbsamparm->type = PBSAMCT_AUTO;
1300             return NOsh_parsePBSAM(thee, sock, calc);
1301         } else {
1302             Vnm_print(2, "NOsh_parseELEC: The method (\"mg\",\"fem\", \"bem\", \"geoflow\" \"pbam\", \"pbsam\") or \
1303 \"name\" must be the first keyword in the ELEC section\n");
1304             return 0;
1305         }
1306     }
1307 
1308     Vnm_print(2, "NOsh_parseELEC:  Ran out of tokens while reading ELEC section!\n");
1309     return 0;
1310 
1311 }
1312 
NOsh_parseAPOLAR(NOsh * thee,Vio * sock)1313 VPRIVATE int NOsh_parseAPOLAR(NOsh *thee, Vio *sock) {
1314 
1315     NOsh_calc *calc = VNULL;
1316 
1317     char tok[VMAX_BUFSIZE];
1318 
1319     if (thee == VNULL) {
1320         Vnm_print(2, "NOsh_parseAPOLAR:  Got NULL thee!\n");
1321         return 0;
1322     }
1323 
1324     if (sock == VNULL) {
1325         Vnm_print(2, "NOsh_parseAPOLAR:  Got pointer to NULL socket!\n");
1326         return 0;
1327     }
1328 
1329     if (thee->parsed) {
1330         Vnm_print(2, "NOsh_parseAPOLAR:  Already parsed an input file!\n");
1331         return 0;
1332     }
1333 
1334     /* Get a pointer to the latest ELEC calc object and update the ELEC
1335         statement number */
1336     if (thee->napol >= NOSH_MAXCALC) {
1337         Vnm_print(2, "NOsh:  Too many non-polar calculations in this \
1338 run!\n");
1339         Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
1340                   NOSH_MAXCALC);
1341         return 1;
1342     }
1343 
1344     /* The next token HAS to be the method OR "name" */
1345     if (Vio_scanf(sock, "%s", tok) == 1) {
1346         if (Vstring_strcasecmp(tok, "name") == 0) {
1347             Vio_scanf(sock, "%s", tok);
1348             strncpy(thee->apolname[thee->napol], tok, VMAX_ARGLEN);
1349 
1350             /* Parse the non-polar parameters */
1351             thee->apol[thee->napol] = NOsh_calc_ctor(NCT_APOL);
1352             calc = thee->apol[thee->napol];
1353             (thee->napol)++;
1354             return NOsh_parseAPOL(thee, sock, calc);
1355 //        } else if (Vstring_strcasecmp(tok, "geoflow-manual") == 0) {
1356 //            thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_GEOFLOW);
1357 //            calc = thee->elec[thee->nelec];
1358 //            (thee->nelec)++;
1359 //            calc->geoflowparm->type = GFCT_MANUAL;
1360 //            return NOsh_parseGEOFLOW(thee, sock, calc);
1361 //        } else if (Vstring_strcasecmp(tok, "geoflow-auto") == 0) {
1362 //            thee->elec[thee->nelec] = NOsh_calc_ctor(NCT_GEOFLOW);
1363 //            calc = thee->elec[thee->nelec];
1364 //            (thee->nelec)++;
1365 //            calc->geoflowparm->type = GFCT_AUTO;
1366 //            return NOsh_parseGEOFLOW(thee, sock, calc);
1367         }
1368     }
1369 
1370     return 1;
1371 
1372 }
1373 
NOsh_setupElecCalc(NOsh * thee,Valist * alist[NOSH_MAXMOL])1374 VPUBLIC int NOsh_setupElecCalc(
1375                            NOsh *thee,
1376                            Valist *alist[NOSH_MAXMOL]
1377                            ) {
1378     int ielec, imol, i;
1379     NOsh_calc *elec = VNULL;
1380     MGparm *mgparm = VNULL;
1381     Valist *mymol = VNULL;
1382 
1383     VASSERT(thee != VNULL);
1384     for (imol=0; imol<thee->nmol; imol++) {
1385         thee->alist[imol] = alist[imol];
1386     }
1387 
1388 
1389     for (ielec=0; ielec<(thee->nelec); ielec++) {
1390         /* Unload the calculation object containing the ELEC information */
1391         elec = thee->elec[ielec];
1392 
1393         if (((thee->ndiel != 0) || (thee->nkappa != 0) ||
1394              (thee->ncharge != 0) || (thee->npot != 0)) &&
1395                 (elec->pbeparm->calcforce != PCF_NO)) {
1396             Vnm_print(2, "NOsh_setupElecCalc:  Calculation of forces disabled because surface \
1397 map is used!\n");
1398             elec->pbeparm->calcforce = PCF_NO;
1399         }
1400 
1401         /* Setup the calculation */
1402         switch (elec->calctype) {
1403             case NCT_MG:
1404                 /* Center on the molecules, if requested */
1405                 mgparm = elec->mgparm;
1406                 VASSERT(mgparm != VNULL);
1407                 if (elec->mgparm->cmeth == MCM_MOLECULE) {
1408                     VASSERT(mgparm->centmol >= 0);
1409                     VASSERT(mgparm->centmol < thee->nmol);
1410                     mymol = thee->alist[mgparm->centmol];
1411                     VASSERT(mymol != VNULL);
1412                     for (i=0; i<3; i++) {
1413                         mgparm->center[i] = mymol->center[i];
1414                     }
1415                 }
1416                 if (elec->mgparm->fcmeth == MCM_MOLECULE) {
1417                     VASSERT(mgparm->fcentmol >= 0);
1418                     VASSERT(mgparm->fcentmol < thee->nmol);
1419                     mymol = thee->alist[mgparm->fcentmol];
1420                     VASSERT(mymol != VNULL);
1421                     for (i=0; i<3; i++) {
1422                         mgparm->fcenter[i] = mymol->center[i];
1423                     }
1424                 }
1425                 if (elec->mgparm->ccmeth == MCM_MOLECULE) {
1426                     VASSERT(mgparm->ccentmol >= 0);
1427                     VASSERT(mgparm->ccentmol < thee->nmol);
1428                     mymol = thee->alist[mgparm->ccentmol];
1429                     VASSERT(mymol != VNULL);
1430                     for (i=0; i<3; i++) {
1431                         mgparm->ccenter[i] = mymol->center[i];
1432                     }
1433                 }
1434                 NOsh_setupCalcMG(thee, elec);
1435                 break;
1436             case NCT_FEM:
1437                 NOsh_setupCalcFEM(thee, elec);
1438                 break;
1439             case NCT_PBAM:
1440                 NOsh_setupCalcPBAM(thee, elec);
1441                 break;
1442             case NCT_PBSAM:
1443                 NOsh_setupCalcPBSAM(thee, elec);
1444                 break;
1445             case NCT_BEM:
1446                 NOsh_setupCalcBEM(thee, elec);
1447                 break;
1448             case NCT_GEOFLOW:
1449                 NOsh_setupCalcGEOFLOW(thee, elec);
1450                 break;
1451             default:
1452                 Vnm_print(2, "NOsh_setupCalc:  Invalid calculation type (%d)!\n",
1453                           elec->calctype);
1454                 return 0;
1455         }
1456 
1457         /* At this point, the most recently-created NOsh_calc object should be the
1458             one we use for results for this ELEC statement.  Assign it. */
1459         /* Associate ELEC statement with the calculation */
1460         thee->elec2calc[ielec] = thee->ncalc-1;
1461         Vnm_print(0, "NOsh_setupCalc:  Mapping ELEC statement %d (%d) to \
1462 calculation %d (%d)\n", ielec, ielec+1, thee->elec2calc[ielec],
1463                   thee->elec2calc[ielec]+1);
1464     }
1465 
1466     return 1;
1467 }
1468 
NOsh_setupApolCalc(NOsh * thee,Valist * alist[NOSH_MAXMOL])1469 VPUBLIC int NOsh_setupApolCalc(
1470                                NOsh *thee,
1471                                Valist *alist[NOSH_MAXMOL]
1472                                ) {
1473     int iapol, imol;
1474     int doCalc = ACD_NO;
1475     NOsh_calc *calc = VNULL;
1476 
1477     VASSERT(thee != VNULL);
1478     for (imol=0; imol<thee->nmol; imol++) {
1479         thee->alist[imol] = alist[imol];
1480     }
1481 
1482     for (iapol=0; iapol<(thee->napol); iapol++) {
1483         /* Unload the calculation object containing the APOL information */
1484         calc = thee->apol[iapol];
1485 
1486         /* Setup the calculation */
1487         switch (calc->calctype) {
1488             case NCT_APOL:
1489                 NOsh_setupCalcAPOL(thee, calc);
1490                 doCalc = ACD_YES;
1491                 break;
1492             default:
1493                 Vnm_print(2, "NOsh_setupCalc:  Invalid calculation type (%d)!\n", calc->calctype);
1494                 return ACD_ERROR;
1495         }
1496         /* At this point, the most recently-created NOsh_calc object should be the
1497             one we use for results for this APOL statement.  Assign it. */
1498         /* Associate APOL statement with the calculation */
1499         thee->apol2calc[iapol] = thee->ncalc-1;
1500         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);
1501     }
1502 
1503     if(doCalc == ACD_YES){
1504         return ACD_YES;
1505     }else{
1506         return ACD_NO;
1507     }
1508 }
1509 
NOsh_parseMG(NOsh * thee,Vio * sock,NOsh_calc * elec)1510 VPUBLIC int NOsh_parseMG(
1511                          NOsh *thee,
1512                          Vio *sock,
1513                          NOsh_calc *elec
1514                          ) {
1515 
1516     char tok[VMAX_BUFSIZE];
1517     MGparm *mgparm = VNULL;
1518     PBEparm *pbeparm = VNULL;
1519     int rc;
1520 
1521     /* Check the arguments */
1522     if (thee == VNULL) {
1523         Vnm_print(2, "NOsh:  Got NULL thee!\n");
1524         return 0;
1525     }
1526     if (sock == VNULL) {
1527         Vnm_print(2, "NOsh:  Got pointer to NULL socket!\n");
1528         return 0;
1529     }
1530     if (elec == VNULL) {
1531         Vnm_print(2, "NOsh:  Got pointer to NULL elec object!\n");
1532         return 0;
1533     }
1534     mgparm = elec->mgparm;
1535     if (mgparm == VNULL) {
1536         Vnm_print(2, "NOsh:  Got pointer to NULL mgparm object!\n");
1537         return 0;
1538     }
1539     pbeparm = elec->pbeparm;
1540     if (pbeparm == VNULL) {
1541         Vnm_print(2, "NOsh:  Got pointer to NULL pbeparm object!\n");
1542         return 0;
1543     }
1544 
1545     Vnm_print(0, "NOsh_parseMG: Parsing parameters for MG calculation\n");
1546 
1547     /* Parallel stuff */
1548     if (mgparm->type == MCT_PARALLEL) {
1549         mgparm->proc_rank = thee->proc_rank;
1550         mgparm->proc_size = thee->proc_size;
1551         mgparm->setrank = 1;
1552         mgparm->setsize = 1;
1553     }
1554 
1555 
1556     /* Start snarfing tokens from the input stream */
1557     rc = 1;
1558     while (Vio_scanf(sock, "%s", tok) == 1) {
1559 
1560         Vnm_print(0, "NOsh_parseMG:  Parsing %s...\n", tok);
1561 
1562         /* See if it's an END token */
1563         if (Vstring_strcasecmp(tok, "end") == 0) {
1564             mgparm->parsed = 1;
1565             pbeparm->parsed = 1;
1566             rc = 1;
1567             break;
1568         }
1569 
1570         /* Pass the token through a series of parsers */
1571         rc = PBEparm_parseToken(pbeparm, tok, sock);
1572         if (rc == -1) {
1573             Vnm_print(0, "NOsh_parseMG:  parsePBE error!\n");
1574             break;
1575         } else if (rc == 0) {
1576             /* Pass the token to the generic MG parser */
1577             rc = MGparm_parseToken(mgparm, tok, sock);
1578             if (rc == -1) {
1579                 Vnm_print(0, "NOsh_parseMG:  parseMG error!\n");
1580                 break;
1581             } else if (rc == 0) {
1582                 /* We ran out of parsers! */
1583                 Vnm_print(2, "NOsh:  Unrecognized keyword: %s\n", tok);
1584                 break;
1585             }
1586         }
1587     }
1588 
1589     /* Handle various errors arising in the token-snarfing loop -- these all
1590         just result in simple returns right now */
1591     if (rc == -1) return 0;
1592     if (rc == 0) return 0;
1593 
1594     /* Check the status of the parameter objects */
1595     if ((MGparm_check(mgparm) == VRC_FAILURE) || (!PBEparm_check(pbeparm))) {
1596         Vnm_print(2, "NOsh:  MG parameters not set correctly!\n");
1597         return 0;
1598     }
1599 
1600     return 1;
1601 }
1602 
NOsh_setupCalcMG(NOsh * thee,NOsh_calc * calc)1603 VPRIVATE int NOsh_setupCalcMG(
1604                               NOsh *thee,
1605                               NOsh_calc *calc
1606                               ) {
1607 
1608     MGparm *mgparm = VNULL;
1609 
1610     VASSERT(thee != VNULL);
1611     VASSERT(calc != VNULL);
1612     mgparm = calc->mgparm;
1613     VASSERT(mgparm != VNULL);
1614 
1615 
1616     /* Now we're ready to whatever sorts of post-processing operations that are
1617         necessary for the various types of calculations */
1618     switch (mgparm->type) {
1619         case MCT_MANUAL:
1620             return NOsh_setupCalcMGMANUAL(thee, calc);
1621         case MCT_DUMMY:
1622             return NOsh_setupCalcMGMANUAL(thee, calc);
1623         case MCT_AUTO:
1624             return NOsh_setupCalcMGAUTO(thee, calc);
1625         case MCT_PARALLEL:
1626             return NOsh_setupCalcMGPARA(thee, calc);
1627         default:
1628             Vnm_print(2, "NOsh_setupCalcMG:  undefined MG calculation type (%d)!\n",
1629                       mgparm->type);
1630             return 0;
1631     }
1632 
1633     /* Shouldn't get here */
1634     return 0;
1635 }
1636 
1637 
NOsh_setupCalcBEM(NOsh * thee,NOsh_calc * calc)1638 VPRIVATE int NOsh_setupCalcBEM(
1639                               NOsh *thee,
1640                               NOsh_calc *calc
1641                               ) {
1642 
1643     BEMparm *bemparm = VNULL;
1644 
1645     VASSERT(thee != VNULL);
1646     VASSERT(calc != VNULL);
1647     bemparm = calc->bemparm;
1648     VASSERT(bemparm != VNULL);
1649 
1650 
1651     /* Now we're ready to whatever sorts of post-processing operations that are
1652         necessary for the various types of calculations */
1653     switch (bemparm->type) {
1654         case BCT_MANUAL:
1655             return NOsh_setupCalcBEMMANUAL(thee, calc);
1656         default:
1657             Vnm_print(2, "NOsh_setupCalcBEM:  undefined BEM calculation type (%d)!\n",
1658                       bemparm->type);
1659             return 0;
1660     }
1661 
1662     /* Shouldn't get here */
1663     return 0;
1664 }
1665 
NOsh_setupCalcGEOFLOW(NOsh * thee,NOsh_calc * calc)1666 VPRIVATE int NOsh_setupCalcGEOFLOW(NOsh *thee, NOsh_calc *calc) {
1667 
1668     GEOFLOWparm *parm = VNULL;
1669 
1670     VASSERT(thee != VNULL);
1671     VASSERT(calc != VNULL);
1672     parm = calc->geoflowparm;
1673     VASSERT(parm != VNULL);
1674 
1675 
1676     /* Now we're ready to whatever sorts of post-processing operations that are
1677         necessary for the various types of calculations */
1678     if(/*parm->type == GFCT_MANUAL ||*/ parm->type == GFCT_AUTO){
1679         return NOsh_setupCalcGEOFLOWMANUAL(thee, calc);
1680     }else{
1681         Vnm_print(2, "NOsh_setupCalcGEOFLOW:  undefined GEOFLOW calculation type (%d)!\n", parm->type);
1682         return 0;
1683     }
1684 }
1685 
NOsh_setupCalcPBAM(NOsh * thee,NOsh_calc * calc)1686 VPRIVATE int NOsh_setupCalcPBAM(NOsh *thee, NOsh_calc *calc){
1687 
1688   PBAMparm *parm = VNULL;
1689 
1690   VASSERT(thee!=VNULL);
1691   VASSERT(calc!=VNULL);
1692   parm = calc->pbamparm;
1693   VASSERT(parm!=VNULL);
1694 
1695   if(parm->type == PBAMCT_AUTO){
1696     return NOsh_setupCalcPBAMAUTO(thee, calc);
1697   } else {
1698     Vnm_print(2, "NOsh_setupCalcPBAM: undefined PBAM calculation type (%d)!\n", parm->type);
1699     return 0;
1700   }
1701 }
1702 
1703 
NOsh_setupCalcPBSAM(NOsh * thee,NOsh_calc * calc)1704 VPRIVATE int NOsh_setupCalcPBSAM(NOsh *thee, NOsh_calc *calc){
1705 
1706   PBSAMparm *parm = VNULL;
1707 
1708   VASSERT(thee!=VNULL);
1709   VASSERT(calc!=VNULL);
1710   parm = calc->pbsamparm;
1711   VASSERT(parm!=VNULL);
1712 
1713   if(parm->type == PBSAMCT_AUTO){
1714     return NOsh_setupCalcPBSAMAUTO(thee, calc);
1715   } else {
1716     Vnm_print(2, "NOsh_setupCalcPBSAM: undefined PBSAM calculation type (%d)!\n", parm->type);
1717     return 0;
1718   }
1719 }
1720 
1721 
NOsh_setupCalcFEM(NOsh * thee,NOsh_calc * calc)1722 VPRIVATE int NOsh_setupCalcFEM(
1723                                NOsh *thee,
1724                                NOsh_calc *calc
1725                                ) {
1726 
1727     VASSERT(thee != VNULL);
1728     VASSERT(calc != VNULL);
1729     VASSERT(calc->femparm != VNULL);
1730 
1731     /* Now we're ready to whatever sorts of post-processing operations that are
1732         * necessary for the various types of calculations */
1733     switch (calc->femparm->type) {
1734         case FCT_MANUAL:
1735             return NOsh_setupCalcFEMANUAL(thee, calc);
1736         default:
1737             Vnm_print(2, "NOsh_parseFEM:  unknown calculation type (%d)!\n",
1738                       calc->femparm->type);
1739             return 0;
1740     }
1741 
1742     /* Shouldn't get here */
1743     return 0;
1744 }
1745 
1746 
NOsh_setupCalcMGMANUAL(NOsh * thee,NOsh_calc * elec)1747 VPRIVATE int NOsh_setupCalcMGMANUAL(
1748                                    NOsh *thee,
1749                                    NOsh_calc *elec
1750                                    ) {
1751 
1752     MGparm *mgparm = VNULL;
1753     PBEparm *pbeparm = VNULL;
1754     NOsh_calc *calc = VNULL;
1755 
1756     if (thee == VNULL) {
1757         Vnm_print(2, "NOsh_setupCalcMGMANUAL:  Got NULL thee!\n");
1758         return 0;
1759     }
1760     if (elec == VNULL) {
1761         Vnm_print(2, "NOsh_setupCalcMGMANUAL:  Got NULL calc!\n");
1762         return 0;
1763     }
1764     mgparm = elec->mgparm;
1765     if (mgparm == VNULL) {
1766         Vnm_print(2, "NOsh_setupCalcMGMANUAL:  Got NULL mgparm -- was this calculation \
1767 set up?\n");
1768         return 0;
1769     }
1770     pbeparm = elec->pbeparm;
1771     if (pbeparm == VNULL) {
1772         Vnm_print(2, "NOsh_setupCalcMGMANUAL:  Got NULL pbeparm -- was this calculation \
1773 set up?\n");
1774         return 0;
1775     }
1776 
1777     /* Set up missing MG parameters */
1778     if (mgparm->setgrid == 0) {
1779         VASSERT(mgparm->setglen);
1780         mgparm->grid[0] = mgparm->glen[0]/((double)(mgparm->dime[0]-1));
1781         mgparm->grid[1] = mgparm->glen[1]/((double)(mgparm->dime[1]-1));
1782         mgparm->grid[2] = mgparm->glen[2]/((double)(mgparm->dime[2]-1));
1783     }
1784     if (mgparm->setglen == 0) {
1785         VASSERT(mgparm->setgrid);
1786         mgparm->glen[0] = mgparm->grid[0]*((double)(mgparm->dime[0]-1));
1787         mgparm->glen[1] = mgparm->grid[1]*((double)(mgparm->dime[1]-1));
1788         mgparm->glen[2] = mgparm->grid[2]*((double)(mgparm->dime[2]-1));
1789     }
1790 
1791     /* Check to see if he have any room left for this type of calculation, if
1792         so: set the calculation type, update the number of calculations of this type,
1793         and parse the rest of the section */
1794     if (thee->ncalc >= NOSH_MAXCALC) {
1795         Vnm_print(2, "NOsh:  Too many calculations in this run!\n");
1796         Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
1797                   NOSH_MAXCALC);
1798         return 0;
1799     }
1800 
1801     /* Get the next calculation object and increment the number of calculations */
1802     thee->calc[thee->ncalc] = NOsh_calc_ctor(NCT_MG);
1803     calc = thee->calc[thee->ncalc];
1804     (thee->ncalc)++;
1805 
1806 
1807 
1808     /* Copy over contents of ELEC */
1809     NOsh_calc_copy(calc, elec);
1810 
1811 
1812     return 1;
1813 }
1814 
NOsh_setupCalcMGAUTO(NOsh * thee,NOsh_calc * elec)1815 VPUBLIC int NOsh_setupCalcMGAUTO(
1816                                  NOsh *thee,
1817                                  NOsh_calc *elec
1818                                  ) {
1819 
1820     NOsh_calc *calcf = VNULL;
1821     NOsh_calc *calcc = VNULL;
1822     double fgrid[3], cgrid[3];
1823     double d[3], minf[3], maxf[3], minc[3], maxc[3];
1824     double redfrac, redrat[3], td;
1825     int ifocus, nfocus, tnfocus[3];
1826     int j;
1827     int icalc;
1828     int dofix;
1829 
1830     /* A comment about the coding style in this function.  I use lots and lots
1831         and lots of pointer deferencing.  I could (and probably should) save
1832         these in temporary variables.  However, since there are so many MGparm,
1833         etc. and NOsh_calc, etc. objects running around in this function, the
1834         current scheme is easiest to debug. */
1835 
1836 
1837     if (thee == VNULL) {
1838         Vnm_print(2, "NOsh_setupCalcMGAUTO:  Got NULL thee!\n");
1839         return 0;
1840     }
1841     if (elec == VNULL) {
1842         Vnm_print(2, "NOsh_setupCalcMGAUTO:  Got NULL elec!\n");
1843         return 0;
1844     }
1845     if (elec->mgparm == VNULL) {
1846         Vnm_print(2, "NOsh_setupCalcMGAUTO:  Got NULL mgparm!\n");
1847         return 0;
1848     }
1849     if (elec->pbeparm == VNULL) {
1850         Vnm_print(2, "NOsh_setupCalcMGAUTO:  Got NULL pbeparm!\n");
1851         return 0;
1852     }
1853 
1854     Vnm_print(0, "NOsh_setupCalcMGAUTO(%s, %d):  coarse grid center = %g %g %g\n",
1855               __FILE__, __LINE__,
1856               elec->mgparm->ccenter[0],
1857               elec->mgparm->ccenter[1],
1858               elec->mgparm->ccenter[2]);
1859     Vnm_print(0, "NOsh_setupCalcMGAUTO(%s, %d):  fine grid center = %g %g %g\n",
1860               __FILE__, __LINE__,
1861               elec->mgparm->fcenter[0],
1862               elec->mgparm->fcenter[1],
1863               elec->mgparm->fcenter[2]);
1864 
1865     /* Calculate the grid spacing on the coarse and fine levels */
1866     for (j=0; j<3; j++) {
1867         cgrid[j] = (elec->mgparm->cglen[j])/((double)(elec->mgparm->dime[j]-1));
1868         fgrid[j] = (elec->mgparm->fglen[j])/((double)(elec->mgparm->dime[j]-1));
1869         d[j] = elec->mgparm->fcenter[j] - elec->mgparm->ccenter[j];
1870     }
1871     Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  Coarse grid spacing = %g, %g, %g\n",
1872               __FILE__, __LINE__, cgrid[0], cgrid[1], cgrid[2]);
1873     Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  Fine grid spacing = %g, %g, %g\n",
1874               __FILE__, __LINE__, fgrid[0], fgrid[1], fgrid[2]);
1875     Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  Displacement between fine and \
1876 coarse grids = %g, %g, %g\n", __FILE__, __LINE__, d[0], d[1], d[2]);
1877 
1878     /* Now calculate the number of focusing levels, never reducing the grid
1879         spacing by more than redfrac at each level */
1880     for (j=0; j<3; j++) {
1881         if (fgrid[j]/cgrid[j] < VREDFRAC) {
1882             redfrac = fgrid[j]/cgrid[j];
1883             td = log(redfrac)/log(VREDFRAC);
1884             tnfocus[j] = (int)ceil(td) + 1;
1885         } else tnfocus[j] = 2;
1886     }
1887     nfocus = VMAX2(VMAX2(tnfocus[0], tnfocus[1]), tnfocus[2]);
1888 
1889     /* Now set redrat to the actual value by which the grid spacing is reduced
1890         at each level of focusing */
1891     for (j=0; j<3; j++) {
1892         redrat[j] = VPOW((fgrid[j]/cgrid[j]), 1.0/((double)nfocus-1.0));
1893     }
1894     Vnm_print(0, "NOsh:  %d levels of focusing with %g, %g, %g reductions\n",
1895               nfocus, redrat[0], redrat[1], redrat[2]);
1896 
1897     /* Now that we know how many focusing levels to use, we're ready to set up
1898         the parameter objects */
1899     if (nfocus > (NOSH_MAXCALC-(thee->ncalc))) {
1900         Vnm_print(2, "NOsh:  Require more calculations than max (%d)!\n",
1901                   NOSH_MAXCALC);
1902         return 0;
1903     }
1904 
1905     for (ifocus=0; ifocus<nfocus; ifocus++) {
1906 
1907         /* Generate the new calc object */
1908         icalc = thee->ncalc;
1909         thee->calc[icalc] = NOsh_calc_ctor(NCT_MG);
1910         (thee->ncalc)++;
1911 
1912         /* This is the _current_ NOsh_calc object */
1913         calcf = thee->calc[icalc];
1914         /* This is the _previous_ Nosh_calc object */
1915         if (ifocus != 0) {
1916             calcc = thee->calc[icalc-1];
1917         } else {
1918             calcc = VNULL;
1919         }
1920 
1921         /* Copy over most of the parameters from the ELEC object */
1922         NOsh_calc_copy(calcf, elec);
1923 
1924         /* Set up the grid lengths and spacings */
1925         if (ifocus == 0) {
1926             for (j=0; j<3; j++) {
1927                 calcf->mgparm->grid[j] = cgrid[j];
1928                 calcf->mgparm->glen[j] = elec->mgparm->cglen[j];
1929             }
1930         } else {
1931             for (j=0; j<3; j++) {
1932                 calcf->mgparm->grid[j] = redrat[j]*(calcc->mgparm->grid[j]);
1933                 calcf->mgparm->glen[j] = redrat[j]*(calcc->mgparm->glen[j]);
1934             }
1935         }
1936         calcf->mgparm->setgrid = 1;
1937         calcf->mgparm->setglen = 1;
1938 
1939         /* Get centers and centering method from coarse and fine meshes */
1940         if (ifocus == 0) {
1941             calcf->mgparm->cmeth = elec->mgparm->ccmeth;
1942             calcf->mgparm->centmol = elec->mgparm->ccentmol;
1943             for (j=0; j<3; j++) {
1944                 calcf->mgparm->center[j] = elec->mgparm->ccenter[j];
1945             }
1946         } else if (ifocus == (nfocus-1)) {
1947             calcf->mgparm->cmeth = elec->mgparm->fcmeth;
1948             calcf->mgparm->centmol = elec->mgparm->fcentmol;
1949             for (j=0; j<3; j++) {
1950                 calcf->mgparm->center[j] = elec->mgparm->fcenter[j];
1951             }
1952         } else {
1953             calcf->mgparm->cmeth = MCM_FOCUS;
1954             /* TEMPORARILY move the current grid center
1955             to the fine grid center.  In general, this will move portions of
1956             the current mesh off the immediately-coarser mesh.  We'll fix that
1957             in the next step. */
1958             for (j=0; j<3; j++) {
1959                 calcf->mgparm->center[j] = elec->mgparm->fcenter[j];
1960             }
1961         }
1962 
1963 
1964         /* As mentioned above, it is highly likely that the previous "jump"
1965             to the fine grid center put portions of the current mesh off the
1966             previous (coarser) mesh.  Fix this by displacing the current mesh
1967             back onto the previous coarser mesh.  */
1968         if (ifocus != 0) {
1969             Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  starting mesh \
1970 repositioning.\n", __FILE__, __LINE__);
1971             Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  coarse mesh center = \
1972 %g %g %g\n", __FILE__, __LINE__,
1973                       calcc->mgparm->center[0],
1974                       calcc->mgparm->center[1],
1975                       calcc->mgparm->center[2]);
1976             Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  coarse mesh upper corner = \
1977 %g %g %g\n", __FILE__, __LINE__,
1978                       calcc->mgparm->center[0]+0.5*(calcc->mgparm->glen[0]),
1979                       calcc->mgparm->center[1]+0.5*(calcc->mgparm->glen[1]),
1980                       calcc->mgparm->center[2]+0.5*(calcc->mgparm->glen[2]));
1981             Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  coarse mesh lower corner = \
1982 %g %g %g\n", __FILE__, __LINE__,
1983                       calcc->mgparm->center[0]-0.5*(calcc->mgparm->glen[0]),
1984                       calcc->mgparm->center[1]-0.5*(calcc->mgparm->glen[1]),
1985                       calcc->mgparm->center[2]-0.5*(calcc->mgparm->glen[2]));
1986             Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  initial fine mesh upper corner = \
1987 %g %g %g\n", __FILE__, __LINE__,
1988                       calcf->mgparm->center[0]+0.5*(calcf->mgparm->glen[0]),
1989                       calcf->mgparm->center[1]+0.5*(calcf->mgparm->glen[1]),
1990                       calcf->mgparm->center[2]+0.5*(calcf->mgparm->glen[2]));
1991             Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  initial fine mesh lower corner = \
1992 %g %g %g\n", __FILE__, __LINE__,
1993                       calcf->mgparm->center[0]-0.5*(calcf->mgparm->glen[0]),
1994                       calcf->mgparm->center[1]-0.5*(calcf->mgparm->glen[1]),
1995                       calcf->mgparm->center[2]-0.5*(calcf->mgparm->glen[2]));
1996             for (j=0; j<3; j++) {
1997                 /* Check if we've fallen off of the lower end of the mesh */
1998                 dofix = 0;
1999                 minf[j] = calcf->mgparm->center[j]
2000                     - 0.5*(calcf->mgparm->glen[j]);
2001                 minc[j] = calcc->mgparm->center[j]
2002                     - 0.5*(calcc->mgparm->glen[j]);
2003                 d[j] = minc[j] - minf[j];
2004                 if (d[j] >= VSMALL) {
2005                     if (ifocus == (nfocus-1)) {
2006                         Vnm_print(2, "NOsh_setupCalcMGAUTO:  Error!  Finest \
2007 mesh has fallen off the coarser meshes!\n");
2008                         Vnm_print(2, "NOsh_setupCalcMGAUTO:  difference in min %d-\
2009 direction = %g\n", j, d[j]);
2010                         Vnm_print(2, "NOsh_setupCalcMGAUTO:  min fine = %g %g %g\n",
2011                                   minf[0], minf[1], minf[2]);
2012                         Vnm_print(2, "NOsh_setupCalcMGAUTO:  min coarse = %g %g %g\n",
2013                                   minc[0], minc[1], minc[2]);
2014                         VASSERT(0);
2015                     } else {
2016                         Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  ifocus = %d, \
2017 fixing mesh min violation (%g in %d-direction).\n", __FILE__, __LINE__, ifocus,
2018                                   d[j], j);
2019                         calcf->mgparm->center[j] += d[j];
2020                         dofix = 1;
2021                     }
2022                 }
2023                 /* Check if we've fallen off of the upper end of the mesh */
2024                 maxf[j] = calcf->mgparm->center[j] \
2025                     + 0.5*(calcf->mgparm->glen[j]);
2026                 maxc[j] = calcc->mgparm->center[j] \
2027                     + 0.5*(calcc->mgparm->glen[j]);
2028                 d[j] = maxf[j] - maxc[j];
2029                 if (d[j] >= VSMALL) {
2030                     if (ifocus == (nfocus-1)) {
2031                         Vnm_print(2, "NOsh_setupCalcMGAUTO:  Error!  Finest \
2032 mesh has fallen off the coarser meshes!\n");
2033                         Vnm_print(2, "NOsh_setupCalcMGAUTO:  difference in %d-\
2034 direction = %g\n", j, d[j]);
2035                         VASSERT(0);
2036                     } else {
2037                         /* If we already fixed the lower boundary and we now need
2038                         to fix the upper boundary, we have a serious problem. */
2039                         if (dofix) {
2040                             Vnm_print(2, "NOsh_setupCalcMGAUTO:  Error!  Both \
2041 ends of the finer mesh do not fit in the bigger mesh!\n");
2042                             VASSERT(0);
2043                         }
2044                         Vnm_print(0, "NOsh_setupCalcMGAUTO(%s, %d):  ifocus = %d, \
2045 fixing mesh max violation (%g in %d-direction).\n", __FILE__, __LINE__, ifocus,
2046                                   d[j], j);
2047                         calcf->mgparm->center[j] -= d[j];
2048                         dofix = 1;
2049                     }
2050                 }
2051             }
2052             Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  final fine mesh upper corner = \
2053 %g %g %g\n", __FILE__, __LINE__,
2054                       calcf->mgparm->center[0]+0.5*(calcf->mgparm->glen[0]),
2055                       calcf->mgparm->center[1]+0.5*(calcf->mgparm->glen[1]),
2056                       calcf->mgparm->center[2]+0.5*(calcf->mgparm->glen[2]));
2057             Vnm_print(0, "NOsh_setupCalcMGAUTO (%s, %d):  final fine mesh lower corner = \
2058 %g %g %g\n", __FILE__, __LINE__,
2059                       calcf->mgparm->center[0]-0.5*(calcf->mgparm->glen[0]),
2060                       calcf->mgparm->center[1]-0.5*(calcf->mgparm->glen[1]),
2061                       calcf->mgparm->center[2]-0.5*(calcf->mgparm->glen[2]));
2062         }
2063 
2064         /* Finer levels have focusing boundary conditions */
2065         if (ifocus != 0) calcf->pbeparm->bcfl = BCFL_FOCUS;
2066 
2067         /* Only the finest level handles I/O and needs to worry about disjoint
2068             partitioning */
2069         if (ifocus != (nfocus-1)) calcf->pbeparm->numwrite = 0;
2070 
2071         /* Reset boundary flags for everything except parallel focusing */
2072         if (calcf->mgparm->type != MCT_PARALLEL)  {
2073             Vnm_print(0, "NOsh_setupMGAUTO:  Resetting boundary flags\n");
2074             for (j=0; j<6; j++) calcf->mgparm->partDisjOwnSide[j] = 0;
2075             for (j=0; j<3; j++) {
2076                 calcf->mgparm->partDisjCenter[j] = 0;
2077                 calcf->mgparm->partDisjLength[j] = calcf->mgparm->glen[j];
2078             }
2079         }
2080 
2081 
2082         calcf->mgparm->parsed = 1;
2083     }
2084 
2085 
2086     return 1;
2087 }
2088 
2089 /* Author:   Nathan Baker and Todd Dolinsky */
NOsh_setupCalcMGPARA(NOsh * thee,NOsh_calc * elec)2090 VPUBLIC int NOsh_setupCalcMGPARA(
2091                                  NOsh *thee,
2092                                  NOsh_calc *elec
2093                                  ) {
2094 
2095     /* NEW (25-Jul-2006):  This code should produce modify the ELEC statement
2096     and pass it on to MGAUTO for further processing. */
2097 
2098     MGparm *mgparm = VNULL;
2099     double ofrac;
2100     double hx, hy, hzed;
2101     double xofrac, yofrac, zofrac;
2102     int rank, size, npx, npy, npz, nproc, ip, jp, kp;
2103     int xeffGlob, yeffGlob, zeffGlob, xDisj, yDisj, zDisj;
2104     int xigminDisj, xigmaxDisj, yigminDisj, yigmaxDisj, zigminDisj, zigmaxDisj;
2105     int xigminOlap, xigmaxOlap, yigminOlap, yigmaxOlap, zigminOlap, zigmaxOlap;
2106     int xOlapReg, yOlapReg, zOlapReg;
2107     double xlenDisj, ylenDisj, zlenDisj;
2108     double xcentDisj, ycentDisj, zcentDisj;
2109     double xcentOlap, ycentOlap, zcentOlap;
2110     double xlenOlap, ylenOlap, zlenOlap;
2111     double xminOlap, xmaxOlap, yminOlap, ymaxOlap, zminOlap, zmaxOlap;
2112     double xminDisj, xmaxDisj, yminDisj, ymaxDisj, zminDisj, zmaxDisj;
2113     double xcent, ycent, zcent;
2114 
2115     /* Grab some useful variables */
2116     VASSERT(thee != VNULL);
2117     VASSERT(elec != VNULL);
2118     mgparm = elec->mgparm;
2119     VASSERT(mgparm != VNULL);
2120 
2121     /* Grab some useful variables */
2122     ofrac = mgparm->ofrac;
2123     npx = mgparm->pdime[0];
2124     npy = mgparm->pdime[1];
2125     npz = mgparm->pdime[2];
2126     nproc = npx*npy*npz;
2127 
2128     /* If this is not an asynchronous calculation, then we need to make sure we
2129         have all the necessary MPI information */
2130     if (mgparm->setasync == 0) {
2131 
2132 #ifndef HAVE_MPI_H
2133 
2134         Vnm_tprint(2, "NOsh_setupCalcMGPARA:  Oops!  You're trying to perform \
2135 an 'mg-para' (parallel) calculation\n");
2136         Vnm_tprint(2, "NOsh_setupCalcMGPARA:  with a version of APBS that wasn't \
2137 compiled with MPI!\n");
2138         Vnm_tprint(2, "NOsh_setupCalcMGPARA:  Perhaps you meant to use the \
2139 'async' flag?\n");
2140         Vnm_tprint(2, "NOsh_setupCalcMGPARA:  Bailing out!\n");
2141 
2142         return 0;
2143 
2144 #endif
2145 
2146         rank = thee->proc_rank;
2147         size = thee->proc_size;
2148         Vnm_print(0, "NOsh_setupCalcMGPARA:  Hello from processor %d of %d\n", rank,
2149                   size);
2150 
2151         /* Check to see if we have too many processors.  If so, then simply set
2152             this processor to duplicating the work of processor 0. */
2153         if (rank > (nproc-1)) {
2154             Vnm_print(2, "NOsh_setupMGPARA:  There are more processors available than\
2155 the %d you requested.\n", nproc);
2156             Vnm_print(2, "NOsh_setupMGPARA:  Eliminating processor %d\n", rank);
2157             thee->bogus = 1;
2158             rank = 0;
2159         }
2160 
2161         /* Check to see if we have too few processors.  If so, this is a fatal
2162             error. */
2163         if (size < nproc) {
2164             Vnm_print(2, "NOsh_setupMGPARA:  There are too few processors (%d) to \
2165 satisfy requirements (%d)\n", size, nproc);
2166             return 0;
2167         }
2168 
2169         Vnm_print(0, "NOsh_setupMGPARA:  Hello (again) from processor %d of %d\n",
2170                   rank, size);
2171 
2172     } else { /* Setting up for an asynchronous calculation. */
2173 
2174         rank = mgparm->async;
2175 
2176         thee->ispara = 1;
2177         thee->proc_rank = rank;
2178 
2179         /* Check to see if the async id is greater than the number of
2180         * processors.  If so, this is a fatal error. */
2181         if (rank > (nproc-1)) {
2182             Vnm_print(2, "NOsh_setupMGPARA:  The processor id you requested (%d) \
2183 is not within the range of processors available (0-%d)\n", rank, (nproc-1));
2184             return 0;
2185         }
2186     }
2187 
2188     /* Calculate the processor's coordinates in the processor grid */
2189     kp = (int)floor(rank/(npx*npy));
2190     jp = (int)floor((rank-kp*npx*npy)/npx);
2191     ip = rank - kp*npx*npy - jp*npx;
2192     Vnm_print(0, "NOsh_setupMGPARA:  Hello world from PE (%d, %d, %d)\n",
2193               ip, jp, kp);
2194 
2195     /* Calculate effective overlap fractions for uneven processor distributions */
2196     if (npx == 1) xofrac = 0.0;
2197     else xofrac = ofrac;
2198     if (npy == 1) yofrac = 0.0;
2199     else yofrac = ofrac;
2200     if (npz == 1) zofrac = 0.0;
2201     else zofrac = ofrac;
2202 
2203     /* Calculate the global grid size and spacing */
2204     xDisj = (int)VFLOOR(mgparm->dime[0]/(1 + 2*xofrac) + 0.5);
2205     xeffGlob = npx*xDisj;
2206     hx = mgparm->fglen[0]/(double)(xeffGlob-1);
2207     yDisj = (int)VFLOOR(mgparm->dime[1]/(1 + 2*yofrac) + 0.5);
2208     yeffGlob = npy*yDisj;
2209     hy = mgparm->fglen[1]/(double)(yeffGlob-1);
2210     zDisj = (int)VFLOOR(mgparm->dime[2]/(1 + 2*zofrac) + 0.5);
2211     zeffGlob = npz*zDisj;
2212     hzed = mgparm->fglen[2]/(double)(zeffGlob-1);
2213     Vnm_print(0, "NOsh_setupMGPARA:  Global Grid size = (%d, %d, %d)\n",
2214               xeffGlob, yeffGlob, zeffGlob);
2215     Vnm_print(0, "NOsh_setupMGPARA:  Global Grid Spacing = (%.3f, %.3f, %.3f)\n",
2216               hx, hy, hzed);
2217     Vnm_print(0, "NOsh_setupMGPARA:  Processor Grid Size = (%d, %d, %d)\n",
2218               xDisj, yDisj, zDisj);
2219 
2220     /* Calculate the maximum and minimum processor grid points */
2221     xigminDisj = ip*xDisj;
2222     xigmaxDisj = xigminDisj + xDisj - 1;
2223     yigminDisj = jp*yDisj;
2224     yigmaxDisj = yigminDisj + yDisj - 1;
2225     zigminDisj = kp*zDisj;
2226     zigmaxDisj = zigminDisj + zDisj - 1;
2227     Vnm_print(0, "NOsh_setupMGPARA:  Min Grid Points for this proc. (%d, %d, %d)\n",
2228               xigminDisj, yigminDisj, zigminDisj);
2229     Vnm_print(0, "NOsh_setupMGPARA:  Max Grid Points for this proc. (%d, %d, %d)\n",
2230               xigmaxDisj, yigmaxDisj, zigmaxDisj);
2231 
2232 
2233     /* Calculate the disjoint partition length and center displacement */
2234     xminDisj = VMAX2(hx*(xigminDisj-0.5), 0.0);
2235     xmaxDisj = VMIN2(hx*(xigmaxDisj+0.5), mgparm->fglen[0]);
2236     xlenDisj = xmaxDisj - xminDisj;
2237     yminDisj = VMAX2(hy*(yigminDisj-0.5), 0.0);
2238     ymaxDisj = VMIN2(hy*(yigmaxDisj+0.5), mgparm->fglen[1]);
2239     ylenDisj = ymaxDisj - yminDisj;
2240     zminDisj = VMAX2(hzed*(zigminDisj-0.5), 0.0);
2241     zmaxDisj = VMIN2(hzed*(zigmaxDisj+0.5), mgparm->fglen[2]);
2242     zlenDisj = zmaxDisj - zminDisj;
2243 
2244     xcent = 0.5*mgparm->fglen[0];
2245     ycent = 0.5*mgparm->fglen[1];
2246     zcent = 0.5*mgparm->fglen[2];
2247 
2248     xcentDisj = xminDisj + 0.5*xlenDisj - xcent;
2249     ycentDisj = yminDisj + 0.5*ylenDisj - ycent;
2250     zcentDisj = zminDisj + 0.5*zlenDisj - zcent;
2251     if (VABS(xcentDisj) < VSMALL) xcentDisj = 0.0;
2252     if (VABS(ycentDisj) < VSMALL) ycentDisj = 0.0;
2253     if (VABS(zcentDisj) < VSMALL) zcentDisj = 0.0;
2254 
2255     Vnm_print(0, "NOsh_setupMGPARA:  Disj part length = (%g, %g, %g)\n",
2256               xlenDisj, ylenDisj, zlenDisj);
2257     Vnm_print(0, "NOsh_setupMGPARA:  Disj part center displacement = (%g, %g, %g)\n",
2258               xcentDisj, ycentDisj, zcentDisj);
2259 
2260     /* Calculate the overlapping partition length and center displacement */
2261     xOlapReg = 0;
2262     yOlapReg = 0;
2263     zOlapReg = 0;
2264     if (npx != 1) xOlapReg = (int)VFLOOR(xofrac*mgparm->fglen[0]/npx/hx + 0.5) + 1;
2265     if (npy != 1) yOlapReg = (int)VFLOOR(yofrac*mgparm->fglen[1]/npy/hy + 0.5) + 1;
2266     if (npz != 1) zOlapReg = (int)VFLOOR(zofrac*mgparm->fglen[2]/npz/hzed + 0.5) + 1;
2267 
2268     Vnm_print(0, "NOsh_setupMGPARA:  No. of Grid Points in Overlap (%d, %d, %d)\n",
2269               xOlapReg, yOlapReg, zOlapReg);
2270 
2271     if (ip == 0) xigminOlap = 0;
2272     else if (ip == (npx - 1)) xigminOlap = xeffGlob - mgparm->dime[0];
2273     else xigminOlap = xigminDisj - xOlapReg;
2274     xigmaxOlap = xigminOlap + mgparm->dime[0] - 1;
2275 
2276     if (jp == 0) yigminOlap = 0;
2277     else if (jp == (npy - 1)) yigminOlap = yeffGlob - mgparm->dime[1];
2278     else yigminOlap = yigminDisj - yOlapReg;
2279     yigmaxOlap = yigminOlap + mgparm->dime[1] - 1;
2280 
2281     if (kp == 0) zigminOlap = 0;
2282     else if (kp == (npz - 1)) zigminOlap = zeffGlob - mgparm->dime[2];
2283     else zigminOlap = zigminDisj - zOlapReg;
2284     zigmaxOlap = zigminOlap + mgparm->dime[2] - 1;
2285 
2286     Vnm_print(0, "NOsh_setupMGPARA:  Min Grid Points with Overlap (%d, %d, %d)\n",
2287               xigminOlap, yigminOlap, zigminOlap);
2288     Vnm_print(0, "NOsh_setupMGPARA:  Max Grid Points with Overlap (%d, %d, %d)\n",
2289               xigmaxOlap, yigmaxOlap, zigmaxOlap);
2290 
2291     xminOlap = hx * xigminOlap;
2292     xmaxOlap = hx * xigmaxOlap;
2293     yminOlap = hy * yigminOlap;
2294     ymaxOlap = hy * yigmaxOlap;
2295     zminOlap = hzed * zigminOlap;
2296     zmaxOlap = hzed * zigmaxOlap;
2297 
2298     xlenOlap = xmaxOlap - xminOlap;
2299     ylenOlap = ymaxOlap - yminOlap;
2300     zlenOlap = zmaxOlap - zminOlap;
2301 
2302     xcentOlap = (xminOlap + 0.5*xlenOlap) - xcent;
2303     ycentOlap = (yminOlap + 0.5*ylenOlap) - ycent;
2304     zcentOlap = (zminOlap + 0.5*zlenOlap) - zcent;
2305     if (VABS(xcentOlap) < VSMALL) xcentOlap = 0.0;
2306     if (VABS(ycentOlap) < VSMALL) ycentOlap = 0.0;
2307     if (VABS(zcentOlap) < VSMALL) zcentOlap = 0.0;
2308 
2309     Vnm_print(0, "NOsh_setupMGPARA:  Olap part length = (%g, %g, %g)\n",
2310               xlenOlap, ylenOlap, zlenOlap);
2311     Vnm_print(0, "NOsh_setupMGPARA:  Olap part center displacement = (%g, %g, %g)\n",
2312               xcentOlap, ycentOlap, zcentOlap);
2313 
2314 
2315     /* Calculate the boundary flags:
2316         Flags are set to 1 when another processor is present along the boundary
2317         Flags are otherwise set to 0. */
2318 
2319     if (ip == 0) mgparm->partDisjOwnSide[VAPBS_LEFT] = 0;
2320     else mgparm->partDisjOwnSide[VAPBS_LEFT] = 1;
2321     if (ip == (npx-1)) mgparm->partDisjOwnSide[VAPBS_RIGHT] = 0;
2322     else mgparm->partDisjOwnSide[VAPBS_RIGHT] = 1;
2323     if (jp == 0) mgparm->partDisjOwnSide[VAPBS_BACK] = 0;
2324     else mgparm->partDisjOwnSide[VAPBS_BACK] = 1;
2325     if (jp == (npy-1)) mgparm->partDisjOwnSide[VAPBS_FRONT] = 0;
2326     else mgparm->partDisjOwnSide[VAPBS_FRONT] = 1;
2327     if (kp == 0) mgparm->partDisjOwnSide[VAPBS_DOWN] = 0;
2328     else mgparm->partDisjOwnSide[VAPBS_DOWN] = 1;
2329     if (kp == (npz-1)) mgparm->partDisjOwnSide[VAPBS_UP] = 0;
2330     else mgparm->partDisjOwnSide[VAPBS_UP] = 1;
2331 
2332     Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[LEFT] = %d\n",
2333               mgparm->partDisjOwnSide[VAPBS_LEFT]);
2334     Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[RIGHT] = %d\n",
2335               mgparm->partDisjOwnSide[VAPBS_RIGHT]);
2336     Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[FRONT] = %d\n",
2337               mgparm->partDisjOwnSide[VAPBS_FRONT]);
2338     Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[BACK] = %d\n",
2339               mgparm->partDisjOwnSide[VAPBS_BACK]);
2340     Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[UP] = %d\n",
2341               mgparm->partDisjOwnSide[VAPBS_UP]);
2342     Vnm_print(0, "NOsh_setupMGPARA:  partDisjOwnSide[DOWN] = %d\n",
2343               mgparm->partDisjOwnSide[VAPBS_DOWN]);
2344 
2345     /* Set the mesh parameters */
2346     mgparm->fglen[0] = xlenOlap;
2347     mgparm->fglen[1] = ylenOlap;
2348     mgparm->fglen[2] = zlenOlap;
2349     mgparm->partDisjLength[0] = xlenDisj;
2350     mgparm->partDisjLength[1] = ylenDisj;
2351     mgparm->partDisjLength[2] = zlenDisj;
2352     mgparm->partDisjCenter[0] = mgparm->fcenter[0] + xcentDisj;
2353     mgparm->partDisjCenter[1] = mgparm->fcenter[1] + ycentDisj;
2354     mgparm->partDisjCenter[2] = mgparm->fcenter[2] + zcentDisj;
2355     mgparm->fcenter[0] += xcentOlap;
2356     mgparm->fcenter[1] += ycentOlap;
2357     mgparm->fcenter[2] += zcentOlap;
2358 
2359     Vnm_print(0, "NOsh_setupCalcMGPARA (%s, %d):  Set up *relative* partition \
2360 centers...\n", __FILE__, __LINE__);
2361     Vnm_print(0, "NOsh_setupCalcMGPARA (%s, %d):  Absolute centers will be set \
2362 in  NOsh_setupMGAUTO\n", __FILE__, __LINE__);
2363     Vnm_print(0, "NOsh_setupCalcMGPARA (%s, %d):  partDisjCenter = %g %g %g\n",
2364               __FILE__, __LINE__,
2365               mgparm->partDisjCenter[0],
2366               mgparm->partDisjCenter[1],
2367               mgparm->partDisjCenter[2]);
2368     Vnm_print(0, "NOsh_setupCalcMGPARA (%s, %d):  ccenter = %g %g %g\n",
2369               __FILE__, __LINE__,
2370               mgparm->ccenter[0],
2371               mgparm->ccenter[1],
2372               mgparm->ccenter[2]);
2373     Vnm_print(0, "NOsh_setupCalcMGPARA (%s, %d):  fcenter = %g %g %g\n",
2374               __FILE__, __LINE__,
2375               mgparm->fcenter[0],
2376               mgparm->fcenter[1],
2377               mgparm->fcenter[2]);
2378 
2379 
2380     /* Setup the automatic focusing calculations associated with this processor */
2381     return NOsh_setupCalcMGAUTO(thee, elec);
2382 
2383 }
2384 
NOsh_parseFEM(NOsh * thee,Vio * sock,NOsh_calc * elec)2385 VPUBLIC int NOsh_parseFEM(
2386                           NOsh *thee,
2387                           Vio *sock,
2388                           NOsh_calc *elec
2389                           ) {
2390 
2391     char tok[VMAX_BUFSIZE];
2392     FEMparm *feparm = VNULL;
2393     PBEparm *pbeparm = VNULL;
2394     int rc;
2395     Vrc_Codes vrc;
2396 
2397     /* Check the arguments */
2398     if (thee == VNULL) {
2399         Vnm_print(2, "NOsh_parseFEM:  Got NULL thee!\n");
2400         return 0;
2401     }
2402     if (sock == VNULL) {
2403         Vnm_print(2, "NOsh_parseFEM:  Got pointer to NULL socket!\n");
2404         return 0;
2405     }
2406     if (elec == VNULL) {
2407         Vnm_print(2, "NOsh_parseFEM:  Got pointer to NULL elec object!\n");
2408         return 0;
2409     }
2410     feparm = elec->femparm;
2411     if (feparm == VNULL) {
2412         Vnm_print(2, "NOsh_parseFEM:  Got pointer to NULL feparm object!\n");
2413         return 0;
2414     }
2415     pbeparm = elec->pbeparm;
2416     if (feparm == VNULL) {
2417         Vnm_print(2, "NOsh_parseFEM:  Got pointer to NULL pbeparm object!\n");
2418         return 0;
2419     }
2420 
2421     Vnm_print(0, "NOsh_parseFEM: Parsing parameters for FEM calculation\n");
2422 
2423     /* Start snarfing tokens from the input stream */
2424     rc = 1;
2425     while (Vio_scanf(sock, "%s", tok) == 1) {
2426 
2427         Vnm_print(0, "NOsh_parseFEM:  Parsing %s...\n", tok);
2428 
2429         /* See if it's an END token */
2430         if (Vstring_strcasecmp(tok, "end") == 0) {
2431             feparm->parsed = 1;
2432             pbeparm->parsed = 1;
2433             rc = 1;
2434             break;
2435         }
2436 
2437         /* Pass the token through a series of parsers */
2438         rc = PBEparm_parseToken(pbeparm, tok, sock);
2439         if (rc == -1) {
2440             Vnm_print(0, "NOsh_parseFEM:  parsePBE error!\n");
2441             break;
2442         } else if (rc == 0) {
2443             /* Pass the token to the generic MG parser */
2444             vrc = FEMparm_parseToken(feparm, tok, sock);
2445             if (vrc == VRC_FAILURE) {
2446                 Vnm_print(0, "NOsh_parseFEM:  parseMG error!\n");
2447                 break;
2448             } else if (vrc == VRC_WARNING) {
2449                 /* We ran out of parsers! */
2450                 Vnm_print(2, "NOsh:  Unrecognized keyword: %s\n", tok);
2451                 break;
2452             }
2453         }
2454     }
2455 
2456     /* Handle various errors arising in the token-snarfing loop -- these all
2457         * just result in simple returns right now */
2458     if (rc == -1) return 0;
2459     if (rc == 0) return 0;
2460 
2461     /* Check the status of the parameter objects */
2462     if ((!FEMparm_check(feparm)) || (!PBEparm_check(pbeparm))) {
2463         Vnm_print(2, "NOsh:  FEM parameters not set correctly!\n");
2464         return 0;
2465     }
2466 
2467     return 1;
2468 
2469 }
2470 
NOsh_setupCalcFEMANUAL(NOsh * thee,NOsh_calc * elec)2471 VPRIVATE int NOsh_setupCalcFEMANUAL(
2472                                    NOsh *thee,
2473                                    NOsh_calc *elec
2474                                    ) {
2475 
2476     FEMparm *feparm = VNULL;
2477     PBEparm *pbeparm = VNULL;
2478     NOsh_calc *calc = VNULL;
2479 
2480     VASSERT(thee != VNULL);
2481     VASSERT(elec != VNULL);
2482     feparm = elec->femparm;
2483     VASSERT(feparm != VNULL);
2484     pbeparm = elec->pbeparm;
2485     VASSERT(pbeparm);
2486 
2487     /* Check to see if he have any room left for this type of
2488      * calculation, if so: set the calculation type, update the number
2489      * of calculations of this type, and parse the rest of the section
2490      */
2491     if (thee->ncalc >= NOSH_MAXCALC) {
2492         Vnm_print(2, "NOsh:  Too many calculations in this run!\n");
2493         Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
2494                   NOSH_MAXCALC);
2495         return 0;
2496     }
2497     thee->calc[thee->ncalc] = NOsh_calc_ctor(NCT_FEM);
2498     calc = thee->calc[thee->ncalc];
2499     (thee->ncalc)++;
2500 
2501     /* Copy over contents of ELEC */
2502     NOsh_calc_copy(calc, elec);
2503 
2504 
2505     return 1;
2506 }
2507 
NOsh_parseAPOL(NOsh * thee,Vio * sock,NOsh_calc * elec)2508 VPUBLIC int NOsh_parseAPOL(
2509                           NOsh *thee,
2510                           Vio *sock,
2511                           NOsh_calc *elec
2512                           ) {
2513 
2514     char tok[VMAX_BUFSIZE];
2515     APOLparm *apolparm = VNULL;
2516     int rc;
2517 
2518     /* Check the arguments */
2519     if (thee == VNULL) {
2520         Vnm_print(2, "NOsh_parseAPOL:  Got NULL thee!\n");
2521         return 0;
2522     }
2523     if (sock == VNULL) {
2524         Vnm_print(2, "NOsh_parseAPOL:  Got pointer to NULL socket!\n");
2525         return 0;
2526     }
2527     if (elec == VNULL) {
2528         Vnm_print(2, "NOsh_parseAPOL:  Got pointer to NULL elec object!\n");
2529         return 0;
2530     }
2531     apolparm = elec->apolparm;
2532     if (apolparm == VNULL) {
2533         Vnm_print(2, "NOsh_parseAPOL:  Got pointer to NULL apolparm object!\n");
2534         return 0;
2535     }
2536 
2537     Vnm_print(0, "NOsh_parseAPOL: Parsing parameters for APOL calculation\n");
2538 
2539     /* Start snarfing tokens from the input stream */
2540     rc = 1;
2541     while (Vio_scanf(sock, "%s", tok) == 1) {
2542 
2543         Vnm_print(0, "NOsh_parseAPOL:  Parsing %s...\n", tok);
2544         /* See if it's an END token */
2545         if (Vstring_strcasecmp(tok, "end") == 0) {
2546             apolparm->parsed = 1;
2547             rc = 1;
2548             break;
2549         }
2550 
2551         /* Pass the token through a series of parsers */
2552         /* Pass the token to the generic non-polar parser */
2553         rc = APOLparm_parseToken(apolparm, tok, sock);
2554         if (rc == -1) {
2555             Vnm_print(0, "NOsh_parseFEM:  parseMG error!\n");
2556             break;
2557         } else if (rc == 0) {
2558             /* We ran out of parsers! */
2559             Vnm_print(2, "NOsh:  Unrecognized keyword: %s\n", tok);
2560             break;
2561         }
2562 
2563     }
2564 
2565     /* Handle various errors arising in the token-snarfing loop -- these all
2566         * just result in simple returns right now */
2567     if (rc == -1) return 0;
2568     if (rc == 0) return 0;
2569 
2570     /* Check the status of the parameter objects */
2571     if (!APOLparm_check(apolparm)) {
2572         Vnm_print(2, "NOsh:  APOL parameters not set correctly!\n");
2573         return 0;
2574     }
2575 
2576     return 1;
2577 
2578 }
2579 
2580 
NOsh_setupCalcAPOL(NOsh * thee,NOsh_calc * apol)2581 VPRIVATE int NOsh_setupCalcAPOL(
2582                                 NOsh *thee,
2583                                 NOsh_calc *apol
2584                                 ) {
2585 
2586     NOsh_calc *calc = VNULL;
2587 
2588     VASSERT(thee != VNULL);
2589     VASSERT(apol != VNULL);
2590 
2591     /* Check to see if he have any room left for this type of
2592         * calculation, if so: set the calculation type, update the number
2593         * of calculations of this type, and parse the rest of the section
2594         */
2595     if (thee->ncalc >= NOSH_MAXCALC) {
2596         Vnm_print(2, "NOsh:  Too many calculations in this run!\n");
2597         Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
2598                   NOSH_MAXCALC);
2599         return 0;
2600     }
2601     thee->calc[thee->ncalc] = NOsh_calc_ctor(NCT_APOL);
2602     calc = thee->calc[thee->ncalc];
2603     (thee->ncalc)++;
2604 
2605     /* Copy over contents of APOL */
2606     NOsh_calc_copy(calc, apol);
2607 
2608     return 1;
2609 }
2610 
2611 
NOsh_setupCalcBEMMANUAL(NOsh * thee,NOsh_calc * elec)2612 VPRIVATE int NOsh_setupCalcBEMMANUAL(
2613                                    NOsh *thee,
2614                                    NOsh_calc *elec
2615                                    ) {
2616 
2617     BEMparm *bemparm = VNULL;
2618     PBEparm *pbeparm = VNULL;
2619     NOsh_calc *calc = VNULL;
2620 
2621     if (thee == VNULL) {
2622         Vnm_print(2, "NOsh_setupCalcBEMMANUAL:  Got NULL thee!\n");
2623         return 0;
2624     }
2625     if (elec == VNULL) {
2626         Vnm_print(2, "NOsh_setupCalcBEMMANUAL:  Got NULL calc!\n");
2627         return 0;
2628     }
2629     bemparm = elec->bemparm;
2630     if (bemparm == VNULL) {
2631         Vnm_print(2, "NOsh_setupCalcBEMMANUAL:  Got NULL bemparm -- was this calculation \
2632 set up?\n");
2633         return 0;
2634     }
2635     pbeparm = elec->pbeparm;
2636     if (pbeparm == VNULL) {
2637         Vnm_print(2, "NOsh_setupCalcBEMMANUAL:  Got NULL pbeparm -- was this calculation \
2638 set up?\n");
2639         return 0;
2640     }
2641 
2642     /* Set up missing BEM parameters */
2643     if (bemparm->settree_order == 0) {
2644         bemparm->tree_order=1;
2645     }
2646 
2647     if (bemparm->settree_n0 == 0) {
2648         bemparm->tree_n0=500;
2649     }
2650 
2651     if (bemparm->setmac == 0) {
2652         bemparm->mac=0.8;
2653     }
2654 
2655     /* Check to see if he have any room left for this type of calculation, if
2656         so: set the calculation type, update the number of calculations of this type,
2657         and parse the rest of the section */
2658     if (thee->ncalc >= NOSH_MAXCALC) {
2659         Vnm_print(2, "NOsh:  Too many calculations in this run!\n");
2660         Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
2661                   NOSH_MAXCALC);
2662         return 0;
2663     }
2664 
2665     /* Get the next calculation object and increment the number of calculations */
2666     thee->calc[thee->ncalc] = NOsh_calc_ctor(NCT_BEM);
2667     calc = thee->calc[thee->ncalc];
2668     (thee->ncalc)++;
2669 
2670     /* Copy over contents of ELEC */
2671     NOsh_calc_copy(calc, elec);
2672 
2673 
2674     return 1;
2675 }
2676 
NOsh_setupCalcGEOFLOWMANUAL(NOsh * thee,NOsh_calc * elec)2677 VPRIVATE int NOsh_setupCalcGEOFLOWMANUAL(
2678                                    NOsh *thee,
2679                                    NOsh_calc *elec
2680                                    ) {
2681 
2682     GEOFLOWparm *parm = VNULL;
2683     APOLparm *apolparm = VNULL;
2684     PBEparm *pbeparm = VNULL;
2685     NOsh_calc *calc = VNULL;
2686 
2687     if (thee == VNULL) {
2688         Vnm_print(2, "NOsh_setupCalcGEOFLOWMANUAL:  Got NULL thee!\n");
2689         return 0;
2690     }
2691     if (elec == VNULL) {
2692         Vnm_print(2, "NOsh_setupCalcGEOFLOWMANUAL:  Got NULL calc!\n");
2693         return 0;
2694     }
2695     parm = elec->geoflowparm;
2696     if (parm == VNULL) {
2697         Vnm_print(2, "NOsh_setupCalcGEOFLOWMANUAL:  Got NULL geoflowparm -- was this calculation \
2698 set up?\n");
2699         return 0;
2700     }
2701     apolparm = elec->apolparm;
2702     if (parm == VNULL) {
2703         Vnm_print(2, "NOsh_setupCalcGEOFLOWMANUAL:  Got NULL apolparm -- was this calculation \
2704 set up?\n");
2705         return 0;
2706     }
2707     pbeparm = elec->pbeparm;
2708     if (pbeparm == VNULL) {
2709         Vnm_print(2, "NOsh_setupCalcGEOFLOWMANUAL:  Got NULL pbeparm -- was this calculation \
2710 set up?\n");
2711         return 0;
2712     }
2713 
2714     /* Check to see if he have any room left for this type of calculation, if
2715         so: set the calculation type, update the number of calculations of this type,
2716         and parse the rest of the section */
2717     if (thee->ncalc >= NOSH_MAXCALC) {
2718         Vnm_print(2, "NOsh:  Too many calculations in this run!\n");
2719         Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
2720                   NOSH_MAXCALC);
2721         return 0;
2722     }
2723 
2724     /* Get the next calculation object and increment the number of calculations */
2725     thee->calc[thee->ncalc] = NOsh_calc_ctor(NCT_GEOFLOW);
2726     calc = thee->calc[thee->ncalc];
2727     (thee->ncalc)++;
2728 
2729     /* Copy over contents of ELEC */
2730     NOsh_calc_copy(calc, elec);
2731 
2732     return 1;
2733 }
2734 
NOsh_setupCalcPBAMAUTO(NOsh * thee,NOsh_calc * elec)2735 VPRIVATE int NOsh_setupCalcPBAMAUTO(
2736                                    NOsh *thee,
2737                                    NOsh_calc *elec
2738                                    ) {
2739 
2740     PBAMparm *parm = VNULL;
2741     PBEparm *pbeparm = VNULL;
2742     NOsh_calc *calc = VNULL;
2743 
2744     if (thee == VNULL) {
2745         Vnm_print(2, "NOsh_setupCalcPBAMAUTO:  Got NULL thee!\n");
2746         return 0;
2747     }
2748     if (elec == VNULL) {
2749         Vnm_print(2, "NOsh_setupCalcPBAMAUTO:  Got NULL calc!\n");
2750         return 0;
2751     }
2752     parm = elec->pbamparm;
2753     if (parm == VNULL) {
2754         Vnm_print(2, "NOsh_setupCalcPBAMAUTO:  Got NULL pbamparm -- was this calculation \
2755 set up?\n");
2756         return 0;
2757     }
2758     pbeparm = elec->pbeparm;
2759     if (pbeparm == VNULL) {
2760         Vnm_print(2, "NOsh_setupCalcPBAMAUTO:  Got NULL pbeparm -- was this calculation \
2761 set up?\n");
2762         return 0;
2763     }
2764 
2765     /* Check to see if he have any room left for this type of calculation, if
2766         so: set the calculation type, update the number of calculations of this type,
2767         and parse the rest of the section */
2768     if (thee->ncalc >= NOSH_MAXCALC) {
2769         Vnm_print(2, "NOsh:  Too many calculations in this run!\n");
2770         Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
2771                   NOSH_MAXCALC);
2772         return 0;
2773     }
2774 
2775     /* Get the next calculation object and increment the number of calculations */
2776     thee->calc[thee->ncalc] = NOsh_calc_ctor(NCT_PBAM);
2777     calc = thee->calc[thee->ncalc];
2778     (thee->ncalc)++;
2779 
2780     /* Copy over contents of ELEC */
2781     NOsh_calc_copy(calc, elec);
2782 
2783     return 1;
2784 }
2785 
NOsh_setupCalcPBSAMAUTO(NOsh * thee,NOsh_calc * elec)2786 VPRIVATE int NOsh_setupCalcPBSAMAUTO(
2787                                    NOsh *thee,
2788                                    NOsh_calc *elec
2789                                    ) {
2790 
2791     PBAMparm *parm = VNULL;
2792     PBSAMparm *samparm = VNULL;
2793     PBEparm *pbeparm = VNULL;
2794     NOsh_calc *calc = VNULL;
2795 
2796     if (thee == VNULL) {
2797         Vnm_print(2, "NOsh_setupCalcPBSAMAUTO:  Got NULL thee!\n");
2798         return 0;
2799     }
2800     if (elec == VNULL) {
2801         Vnm_print(2, "NOsh_setupCalcPBSAMAUTO:  Got NULL calc!\n");
2802         return 0;
2803     }
2804     parm = elec->pbamparm;
2805     if (parm == VNULL) {
2806         Vnm_print(2, "NOsh_setupCalcPBSAMAUTO:  Got NULL pbamparm -- was this calculation \
2807 set up?\n");
2808         return 0;
2809     }
2810     samparm = elec->pbsamparm;
2811     if (samparm == VNULL) {
2812         Vnm_print(2, "NOsh_setupCalcPBSAMAUTO:  Got NULL pbsamparm -- was this calculation \
2813 set up?\n");
2814         return 0;
2815     }
2816     pbeparm = elec->pbeparm;
2817     if (pbeparm == VNULL) {
2818         Vnm_print(2, "NOsh_setupCalcPBAMAUTO:  Got NULL pbeparm -- was this calculation \
2819 set up?\n");
2820         return 0;
2821     }
2822 
2823     /* Check to see if he have any room left for this type of calculation, if
2824         so: set the calculation type, update the number of calculations of this type,
2825         and parse the rest of the section */
2826     if (thee->ncalc >= NOSH_MAXCALC) {
2827         Vnm_print(2, "NOsh:  Too many calculations in this run!\n");
2828         Vnm_print(2, "NOsh:  Current max is %d; ignoring this calculation\n",
2829                   NOSH_MAXCALC);
2830         return 0;
2831     }
2832 
2833     /* Get the next calculation object and increment the number of calculations */
2834     thee->calc[thee->ncalc] = NOsh_calc_ctor(NCT_PBSAM);
2835     calc = thee->calc[thee->ncalc];
2836     (thee->ncalc)++;
2837 
2838     /* Copy over contents of ELEC */
2839     NOsh_calc_copy(calc, elec);
2840 
2841     return 1;
2842 }
2843 
2844 
NOsh_parseBEM(NOsh * thee,Vio * sock,NOsh_calc * elec)2845 VPUBLIC int NOsh_parseBEM(
2846                          NOsh *thee,
2847                          Vio *sock,
2848                          NOsh_calc *elec
2849                          ) {
2850 
2851     char tok[VMAX_BUFSIZE];
2852     BEMparm *bemparm = VNULL;
2853     PBEparm *pbeparm = VNULL;
2854     int rc;
2855 
2856     /* Check the arguments */
2857     if (thee == VNULL) {
2858         Vnm_print(2, "NOsh:  Got NULL thee!\n");
2859         return 0;
2860     }
2861     if (sock == VNULL) {
2862         Vnm_print(2, "NOsh:  Got pointer to NULL socket!\n");
2863         return 0;
2864     }
2865     if (elec == VNULL) {
2866         Vnm_print(2, "NOsh:  Got pointer to NULL elec object!\n");
2867         return 0;
2868     }
2869     bemparm = elec->bemparm;
2870     if (bemparm == VNULL) {
2871         Vnm_print(2, "NOsh:  Got pointer to NULL bemparm object!\n");
2872         return 0;
2873     }
2874     pbeparm = elec->pbeparm;
2875     if (pbeparm == VNULL) {
2876         Vnm_print(2, "NOsh:  Got pointer to NULL pbeparm object!\n");
2877         return 0;
2878     }
2879 
2880     Vnm_print(0, "NOsh_parseBEM: Parsing parameters for BEM calculation\n");
2881 
2882 
2883     /* Start snarfing tokens from the input stream */
2884     rc = 1;
2885     while (Vio_scanf(sock, "%s", tok) == 1) {
2886 
2887         Vnm_print(0, "NOsh_parseBEM:  Parsing %s...\n", tok);
2888 
2889         /* See if it's an END token */
2890         if (Vstring_strcasecmp(tok, "end") == 0) {
2891             bemparm->parsed = 1;
2892             pbeparm->parsed = 1;
2893             rc = 1;
2894             break;
2895         }
2896 
2897         /* Pass the token through a series of parsers */
2898         rc = PBEparm_parseToken(pbeparm, tok, sock);
2899         if (rc == -1) {
2900             Vnm_print(0, "NOsh_parseBEM:  parsePBE error!\n");
2901             break;
2902         } else if (rc == 0) {
2903             /* Pass the token to the generic BEM parser */
2904             rc = BEMparm_parseToken(bemparm, tok, sock);
2905             if (rc == -1) {
2906                 Vnm_print(0, "NOsh_parseBEM:  parseBEM error!\n");
2907                 break;
2908             } else if (rc == 0) {
2909                 /* We ran out of parsers! */
2910                 Vnm_print(2, "NOsh:  Unrecognized keyword: %s\n", tok);
2911                 break;
2912             }
2913         }
2914     }
2915 
2916     pbeparm->setsrfm=1;     // unneeded srfm
2917     pbeparm->setpbetype=1;  // unneeded pbe type
2918     pbeparm->setbcfl=1;     // unneeded bcfl
2919 
2920     /* Handle various errors arising in the token-snarfing loop -- these all
2921         just result in simple returns right now */
2922     if (rc == -1) return 0;
2923     if (rc == 0) return 0;
2924 
2925     /* Check the status of the parameter objects */
2926     if ((BEMparm_check(bemparm) == VRC_FAILURE) || (!PBEparm_check(pbeparm))) {
2927         Vnm_print(2, "NOsh:  BEM parameters not set correctly!\n");
2928         return 0;
2929     }
2930 
2931     return 1;
2932 }
2933 
NOsh_parseGEOFLOW(NOsh * thee,Vio * sock,NOsh_calc * elec)2934 VPUBLIC int NOsh_parseGEOFLOW(
2935                          NOsh *thee,
2936                          Vio *sock,
2937                          NOsh_calc *elec
2938                          ) {
2939 
2940     char tok[VMAX_BUFSIZE];
2941     GEOFLOWparm *parm = VNULL;
2942     APOLparm *apolparm = VNULL;
2943     PBEparm *pbeparm = VNULL;
2944     int rc;
2945 
2946     /* Check the arguments */
2947     if (thee == VNULL) {
2948         Vnm_print(2, "NOsh:  Got NULL thee!\n");
2949         return 0;
2950     }
2951     if (sock == VNULL) {
2952         Vnm_print(2, "NOsh:  Got pointer to NULL socket!\n");
2953         return 0;
2954     }
2955     if (elec == VNULL) {
2956         Vnm_print(2, "NOsh:  Got pointer to NULL elec object!\n");
2957         return 0;
2958     }
2959     parm = elec->geoflowparm;
2960     if (parm == VNULL) {
2961         Vnm_print(2, "NOsh:  Got pointer to NULL geoflowparm object!\n");
2962         return 0;
2963     }
2964     apolparm = elec->apolparm;
2965     if (parm == VNULL) {
2966         Vnm_print(2, "NOsh:  Got pointer to NULL apolparm object!\n");
2967         return 0;
2968     }
2969     pbeparm = elec->pbeparm;
2970     if (pbeparm == VNULL) {
2971         Vnm_print(2, "NOsh:  Got pointer to NULL pbeparm object!\n");
2972         return 0;
2973     }
2974 
2975     Vnm_print(0, "NOsh_parseGEOFLOW: Parsing parameters for GEOFLOW calculation\n");
2976 
2977 
2978     /* Start snarfing tokens from the input stream */
2979     rc = 1;
2980     while (Vio_scanf(sock, "%s", tok) == 1) {
2981 
2982         Vnm_print(0, "NOsh_parseGEOFLOW:  Parsing %s...\n", tok);
2983 
2984         /* See if it's an END token */
2985         if (Vstring_strcasecmp(tok, "end") == 0) {
2986             parm->parsed = 1;
2987             pbeparm->parsed = 1;
2988             apolparm->parsed = 1;
2989             rc = 1;
2990             break;
2991         }
2992 
2993         if (Vstring_strcasecmp(tok, "ion") == 0) {
2994             Vnm_print(2, "parseGEOFLOW: WARNING! ion not implemented for geometric flow!\n");
2995         }
2996 
2997         /* Pass the token through a series of parsers */
2998         rc = PBEparm_parseToken(pbeparm, tok, sock);
2999         if (rc == -1) {
3000             Vnm_print(0, "NOsh_parseGEOFLOW:  parsePBE error!\n");
3001             break;
3002         } else if (rc == 0) {
3003             /* Pass the token to the generic GEOFLOW parser */
3004             rc = APOLparm_parseToken(apolparm, tok, sock);
3005             if (rc == -1) {
3006                 Vnm_print(0, "NOsh_parseAPOL:  parseAPOL error!\n");
3007                 break;
3008             } else if (rc == 0) {
3009                 rc = GEOFLOWparm_parseToken(parm, tok, sock);
3010                 if (rc == -1) {
3011                     Vnm_print(0, "NOsh_parseGEOFLOW:  parseGEOFLOW error!\n");
3012                     break;
3013                 } else if (rc == 0) {
3014                     /* We ran out of parsers! */
3015                     Vnm_print(2, "NOsh:  Unrecognized keyword: %s\n", tok);
3016                     break;
3017                 }
3018             }
3019         }
3020     }
3021 
3022     pbeparm->setsrfm=1;
3023     pbeparm->srad=0.0;
3024     pbeparm->setsrad=1;
3025     pbeparm->settemp=1;
3026 
3027     /* Handle various errors arising in the token-snarfing loop -- these all
3028         just result in simple returns right now */
3029     if (rc == -1) return 0;
3030     if (rc == 0) return 0;
3031 
3032     /* Check the status of the parameter objects */
3033     if ((GEOFLOWparm_check(parm) == VRC_FAILURE) || (!PBEparm_check(pbeparm))) {
3034         Vnm_print(2, "NOsh:  GEOFLOW parameters not set correctly!\n");
3035         return 0;
3036     }
3037     /*currently the only bc handle by geoflow is mdh so we check here if mdh was read*/
3038 	if(pbeparm->bcfl != BCFL_MDH){
3039 		Vnm_print(2, "NOsh_parseGEOFLOW: Geoflow currently only supports mdh boundary conditions!\n");
3040 		Vnm_print(2, "NOsh_parseGEOFLOW: please change bcfl keyword.\n");
3041 		return 0;
3042 	}
3043 
3044     return 1;
3045 }
3046 
3047 
NOsh_parsePBAM(NOsh * thee,Vio * sock,NOsh_calc * elec)3048 VPUBLIC int NOsh_parsePBAM(
3049                           NOsh *thee,
3050                           Vio *sock,
3051                           NOsh_calc *elec
3052                           ) {
3053 
3054     char tok[VMAX_BUFSIZE];
3055     PBAMparm *parm = VNULL;
3056     PBEparm *pbeparm = VNULL;
3057     int rc;
3058 
3059     /* Check the arguments */
3060     if (thee == VNULL) {
3061         Vnm_print(2, "NOsh:  Got NULL thee!\n");
3062         return 0;
3063     }
3064     if (sock == VNULL) {
3065         Vnm_print(2, "NOsh:  Got pointer to NULL socket!\n");
3066         return 0;
3067     }
3068     if (elec == VNULL) {
3069         Vnm_print(2, "NOsh:  Got pointer to NULL elec object!\n");
3070         return 0;
3071     }
3072     parm = elec->pbamparm;
3073     if (parm == VNULL) {
3074         Vnm_print(2, "NOsh:  Got pointer to NULL pbam object!\n");
3075         return 0;
3076     }
3077     pbeparm = elec->pbeparm;
3078     if (pbeparm == VNULL) {
3079         Vnm_print(2, "NOsh:  Got pointer to NULL pbeparm object!\n");
3080         return 0;
3081     }
3082     Vnm_print(0, "NOsh_parsePBAM: Parsing parameters for PBAM calculation\n");
3083 
3084     /* Start snarfing tokens from the input stream */
3085     rc = 1;
3086     while (Vio_scanf(sock, "%s", tok) == 1) {
3087 
3088         Vnm_print(0, "NOsh_parsePBAM:  Parsing %s...\n", tok);
3089 
3090         /* See if it's an END token */
3091         if (Vstring_strcasecmp(tok, "end") == 0) {
3092             parm->parsed = 1;
3093             pbeparm->parsed = 1;
3094             rc = 1;
3095             break;
3096         }
3097 
3098         if (Vstring_strcasecmp(tok, "ion") == 0) {
3099             Vnm_print(2, "parsePBAM: WARNING! PBAM only uses the conc parameter of ion!\n");
3100         }
3101 
3102         /* Pass the token through a series of parsers */
3103         rc = PBEparm_parseToken(pbeparm, tok, sock);
3104         if (rc == -1) {
3105             Vnm_print(0, "NOsh_parsePBAM:  parsePBE error!\n");
3106             break;
3107         } else if (rc == 0) {
3108              rc = PBAMparm_parseToken(parm, tok, sock);
3109              if (rc == -1) {
3110                  Vnm_print(0, "NOsh_parsePBAM:  parsePBAM error!\n");
3111                  break;
3112              } else if (rc == 0) {
3113                  /* We ran out of parsers! */
3114                  Vnm_print(2, "NOsh:  Unrecognized keyword: %s\n", tok);
3115                  break;
3116             }
3117         }
3118     }
3119 
3120     pbeparm->setsrfm=1;
3121     pbeparm->setsrad=1;
3122     pbeparm->settemp=1; // do need temp, but have default, incase
3123     pbeparm->setmolid=1; // for unneeded mol flag
3124     pbeparm->setpbetype=1; // unneeded pbe type
3125     pbeparm->setbcfl=1;  // unneeded bcfl
3126     pbeparm->setsdens=1;
3127 
3128     //This is a hacky fix at best for issue 501. This is so we don't need to change PBAM's
3129     //external code.
3130     if(pbeparm->setnion){
3131     	parm->salt = pbeparm->ionc[pbeparm->nion-1];
3132     	parm->setsalt = 1;
3133     }
3134 
3135     /* Handle various errors arising in the token-snarfing loop -- these all
3136         just result in simple returns right now */
3137     if (rc == -1) return 0;
3138     if (rc == 0) return 0;
3139 
3140     /* Check the status of the parameter objects */
3141     if ((PBAMparm_check(parm) == VRC_FAILURE) || (!PBEparm_check(pbeparm))) {
3142         Vnm_print(2, "NOsh:  PBAM parameters not set correctly!\n");
3143         return 0;
3144     }
3145     return 1;
3146 }
3147 
NOsh_parsePBSAM(NOsh * thee,Vio * sock,NOsh_calc * elec)3148 VPUBLIC int NOsh_parsePBSAM(
3149                             NOsh *thee,
3150                             Vio *sock,
3151                             NOsh_calc *elec
3152                             ) {
3153 
3154     char tok[VMAX_BUFSIZE];
3155     PBAMparm *parm = VNULL;
3156     PBSAMparm *samparm = VNULL;
3157     PBEparm *pbeparm = VNULL;
3158     int rc;
3159 
3160     /* Check the arguments */
3161     if (thee == VNULL) {
3162         Vnm_print(2, "NOsh:  Got NULL thee!\n");
3163         return 0;
3164     }
3165     if (sock == VNULL) {
3166         Vnm_print(2, "NOsh:  Got pointer to NULL socket!\n");
3167         return 0;
3168     }
3169     if (elec == VNULL) {
3170         Vnm_print(2, "NOsh:  Got pointer to NULL elec object!\n");
3171         return 0;
3172     }
3173     parm = elec->pbamparm;
3174     if (parm == VNULL) {
3175         Vnm_print(2, "NOsh:  Got pointer to NULL pbam object!\n");
3176         return 0;
3177     }
3178     samparm = elec->pbsamparm;
3179     if (samparm == VNULL) {
3180         Vnm_print(2, "NOsh:  Got pointer to NULL pbsam object!\n");
3181         return 0;
3182     }
3183     pbeparm = elec->pbeparm;
3184     if (pbeparm == VNULL) {
3185         Vnm_print(2, "NOsh:  Got pointer to NULL pbeparm object!\n");
3186         return 0;
3187     }
3188     Vnm_print(0, "NOsh_parsePBSAM: Parsing parameters for PBSAM calculation\n");
3189 
3190     /* Start snarfing tokens from the input stream */
3191     rc = 1;
3192     while (Vio_scanf(sock, "%s", tok) == 1) {
3193 
3194         Vnm_print(0, "NOsh_parsePBSAM:  Parsing %s...\n", tok);
3195 
3196         /* See if it's an END token */
3197         if (Vstring_strcasecmp(tok, "end") == 0) {
3198             parm->parsed = 1;
3199             samparm->parsed = 1;
3200             pbeparm->parsed = 1;
3201             rc = 1;
3202             break;
3203         }
3204 
3205         if (Vstring_strcasecmp(tok, "ion") == 0) {
3206             Vnm_print(2, "parsePBSAM: WARNING! PBAM only uses the conc parameter of ion!\n");
3207         }
3208 
3209         /* Pass the token through a series of parsers */
3210         rc = PBEparm_parseToken(pbeparm, tok, sock);
3211         if (rc == -1) {
3212             Vnm_print(0, "NOsh_parsePBSAM:  parsePBE error!\n");
3213             break;
3214         } else if (rc == 0) {
3215              rc = PBAMparm_parseToken(parm, tok, sock);
3216              if (rc == -1) {
3217                  Vnm_print(0, "NOsh_parsePBSAM:  parsePBAM error!\n");
3218                  break;
3219              } else if ( rc == 0 ) {
3220                   rc = PBSAMparm_parseToken(samparm, tok, sock);
3221                   if (rc == -1) {
3222                       Vnm_print(0, "NOsh_parsePBSAM:  parsePBSAM error!\n");
3223                       break;
3224                   } else if (rc == 0) {
3225                       /* We ran out of parsers! */
3226                       Vnm_print(2, "NOsh:  Unrecognized keyword: %s\n", tok);
3227                       break;
3228                   }
3229              }
3230         }
3231     }
3232 
3233     pbeparm->setsrfm=1;
3234     pbeparm->setsrad=1;
3235     pbeparm->settemp=1; // do need temp, but have default, incase
3236     pbeparm->setmolid=1; // for unneeded mol flag
3237     pbeparm->setpbetype=1; // unneeded pbe type
3238     pbeparm->setbcfl=1;  // unneeded bcfl
3239     pbeparm->setsdens=1;
3240 
3241     //This is a hacky fix at best for issue 501. This is so we don't need to change PBAM's
3242     //external code.
3243 	if(pbeparm->setnion){
3244 		parm->salt = pbeparm->ionc[pbeparm->nion-1];
3245 		parm->setsalt = 1;
3246 	}
3247 
3248     /* Handle various errors arising in the token-snarfing loop -- these all
3249         just result in simple returns right now */
3250     if (rc == -1) return 0;
3251     if (rc == 0) return 0;
3252 
3253     /* Check the status of the parameter objects */
3254     if ((PBSAMparm_check(samparm)==VRC_FAILURE) ||
3255          (PBAMparm_check(parm) == VRC_FAILURE) ||
3256          (!PBEparm_check(pbeparm))) {
3257         Vnm_print(2, "NOsh:  PBSAM parameters not set correctly!\n");
3258         return 0;
3259     }
3260     return 1;
3261 }
3262