ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/UseTheForce/WATER.cpp
Revision: 1617
Committed: Wed Oct 20 20:46:20 2004 UTC (19 years, 8 months ago) by chuckv
File size: 27175 byte(s)
Log Message:
Fortran/C++ interface de-obfuscation project (It is a very long story)

File Contents

# User Rev Content
1 gezelter 1490 #include <stdlib.h>
2     #include <stdio.h>
3     #include <string.h>
4    
5     #include <iostream>
6     using namespace std;
7    
8     #ifdef IS_MPI
9     #include <mpi.h>
10     #endif //is_mpi
11    
12 tim 1492 #include "UseTheForce/ForceFields.hpp"
13     #include "primitives/SRI.hpp"
14     #include "utils/simError.h"
15 gezelter 1490
16    
17 chuckv 1617 #include "UseTheForce/DarkSide/atype_interface.h"
18     #include "UseTheForce/DarkSide/sticky_interface.h"
19    
20 gezelter 1490 #ifdef IS_MPI
21 tim 1492 #include "UseTheForce/mpiForceField.h"
22 gezelter 1490 #endif // is_mpi
23    
24    
25    
26     namespace WATER_NS{
27    
28     // Declare the structures that will be passed by the parser and MPI
29    
30     typedef struct{
31     char name[15];
32     double mass;
33     double epslon;
34     double sigma;
35     double charge;
36     int isDirectional;
37     int isLJ;
38     int isCharge;
39     int ident;
40     int last; // 0 -> default
41     // 1 -> in MPI: tells nodes to stop listening
42     } atomStruct;
43    
44     typedef struct{
45     char name[15];
46     double Ixx;
47     double Iyy;
48     double Izz;
49     double dipole;
50     double w0;
51     double v0;
52     double v0p;
53     double rl;
54     double ru;
55     double rlp;
56     double rup;
57     int isDipole;
58     int isSticky;
59     int last; // 0 -> default
60     // 1 -> in MPI: tells nodes to stop listening
61     } directionalStruct;
62    
63     int parseAtom( char *lineBuffer, int lineNum, atomStruct &info );
64     int parseDirectional( char *lineBuffer, int lineNum, directionalStruct &info );
65    
66    
67     #ifdef IS_MPI
68    
69     MPI_Datatype mpiAtomStructType;
70     MPI_Datatype mpiDirectionalStructType;
71    
72     #endif
73    
74     class LinkedAtomType {
75     public:
76     LinkedAtomType(){
77     next = NULL;
78     name[0] = '\0';
79     }
80     ~LinkedAtomType(){ if( next != NULL ) delete next; }
81    
82     LinkedAtomType* find(char* key){
83     if( !strcmp(name, key) ) return this;
84     if( next != NULL ) return next->find(key);
85     return NULL;
86     }
87    
88    
89     void add( atomStruct &info ){
90    
91     // check for duplicates
92    
93     if( !strcmp( info.name, name ) ){
94     sprintf( painCave.errMsg,
95     "Duplicate WATER atom type \"%s\" found in "
96     "the WATER param file./n",
97     name );
98     painCave.isFatal = 1;
99     simError();
100     }
101    
102     if( next != NULL ) next->add(info);
103     else{
104     next = new LinkedAtomType();
105     strcpy(next->name, info.name);
106     next->isDirectional = info.isDirectional;
107     next->isLJ = info.isLJ;
108     next->isCharge = info.isCharge;
109     next->mass = info.mass;
110     next->epslon = info.epslon;
111     next->sigma = info.sigma;
112     next->charge = info.charge;
113     next->ident = info.ident;
114     }
115     }
116    
117     #ifdef IS_MPI
118    
119     void duplicate( atomStruct &info ){
120     strcpy(info.name, name);
121     info.isDirectional = isDirectional;
122     info.isLJ = isLJ;
123     info.isCharge = isCharge;
124     info.mass = mass;
125     info.epslon = epslon;
126     info.sigma = sigma;
127     info.charge = charge;
128     info.ident = ident;
129     info.last = 0;
130     }
131    
132     #endif
133    
134     char name[15];
135     int isDirectional;
136     int isLJ;
137     int isCharge;
138     double mass;
139     double epslon;
140     double sigma;
141     double charge;
142     int ident;
143     LinkedAtomType* next;
144     };
145    
146     class LinkedDirectionalType {
147     public:
148     LinkedDirectionalType(){
149     next = NULL;
150     name[0] = '\0';
151     }
152     ~LinkedDirectionalType(){ if( next != NULL ) delete next; }
153    
154     LinkedDirectionalType* find(char* key){
155     if( !strcmp(name, key) ) return this;
156     if( next != NULL ) return next->find(key);
157     return NULL;
158     }
159    
160    
161     void add( directionalStruct &info ){
162    
163     // check for duplicates
164    
165     if( !strcmp( info.name, name ) ){
166     sprintf( painCave.errMsg,
167     "Duplicate WATER directional type \"%s\" found in "
168     "the WATER param file./n",
169     name );
170     painCave.isFatal = 1;
171     simError();
172     }
173    
174     if( next != NULL ) next->add(info);
175     else{
176     next = new LinkedDirectionalType();
177     strcpy(next->name, info.name);
178     next->isDipole = info.isDipole;
179     next->isSticky = info.isSticky;
180     next->Ixx = info.Ixx;
181     next->Iyy = info.Iyy;
182     next->Izz = info.Izz;
183     next->dipole = info.dipole;
184     next->w0 = info.w0;
185     next->v0 = info.v0;
186     next->v0p = info.v0p;
187     next->rl = info.rl;
188     next->ru = info.ru;
189     next->rlp = info.rlp;
190     next->rup = info.rup;
191     }
192     }
193    
194     #ifdef IS_MPI
195    
196     void duplicate( directionalStruct &info ){
197     strcpy(info.name, name);
198     info.isDipole = isDipole;
199     info.isSticky = isSticky;
200     info.Ixx = Ixx;
201     info.Iyy = Iyy;
202     info.Izz = Izz;
203     info.dipole = dipole;
204     info.w0 = w0;
205     info.v0 = v0;
206     info.v0p = v0p;
207     info.rl = rl;
208     info.ru = ru;
209     info.rlp = rlp;
210     info.rup = rup;
211     info.last = 0;
212     }
213    
214     #endif
215    
216     char name[15];
217     int isDipole;
218     int isSticky;
219     double Ixx;
220     double Iyy;
221     double Izz;
222     double dipole;
223     double w0;
224     double v0;
225     double v0p;
226     double rl;
227     double ru;
228     double rlp;
229     double rup;
230     LinkedDirectionalType* next;
231     };
232    
233     LinkedAtomType* headAtomType;
234     LinkedAtomType* currentAtomType;
235     LinkedDirectionalType* headDirectionalType;
236     LinkedDirectionalType* currentDirectionalType;
237     } // namespace
238    
239     using namespace WATER_NS;
240    
241     //****************************************************************
242     // begins the actual forcefield stuff.
243     //****************************************************************
244    
245    
246     WATER::WATER(){
247    
248     char fileName[200];
249     char* ffPath_env = "FORCE_PARAM_PATH";
250     char* ffPath;
251     char temp[200];
252    
253     headAtomType = NULL;
254     currentAtomType = NULL;
255     headDirectionalType = NULL;
256     currentDirectionalType = NULL;
257    
258     #ifdef IS_MPI
259     int i;
260    
261     // **********************************************************************
262     // Init the atomStruct mpi type
263    
264     atomStruct atomProto; // mpiPrototype
265     int atomBC[3] = {15,4,5}; // block counts
266     MPI_Aint atomDspls[3]; // displacements
267     MPI_Datatype atomMbrTypes[3]; // member mpi types
268    
269     MPI_Address(&atomProto.name, &atomDspls[0]);
270     MPI_Address(&atomProto.mass, &atomDspls[1]);
271     MPI_Address(&atomProto.isDirectional, &atomDspls[2]);
272    
273     atomMbrTypes[0] = MPI_CHAR;
274     atomMbrTypes[1] = MPI_DOUBLE;
275     atomMbrTypes[2] = MPI_INT;
276    
277     for (i=2; i >= 0; i--) atomDspls[i] -= atomDspls[0];
278    
279     MPI_Type_struct(3, atomBC, atomDspls, atomMbrTypes, &mpiAtomStructType);
280     MPI_Type_commit(&mpiAtomStructType);
281    
282     // ***********************************************************************
283    
284     // **********************************************************************
285     // Init the directionalStruct mpi type
286    
287     directionalStruct directionalProto; // mpiPrototype
288     int directionalBC[3] = {15,11,3}; // block counts
289     MPI_Aint directionalDspls[3]; // displacements
290     MPI_Datatype directionalMbrTypes[3]; // member mpi types
291    
292     MPI_Address(&directionalProto.name, &directionalDspls[0]);
293     MPI_Address(&directionalProto.Ixx, &directionalDspls[1]);
294     MPI_Address(&directionalProto.isDipole, &directionalDspls[2]);
295    
296     directionalMbrTypes[0] = MPI_CHAR;
297     directionalMbrTypes[1] = MPI_DOUBLE;
298     directionalMbrTypes[2] = MPI_INT;
299    
300     for (i=2; i >= 0; i--) directionalDspls[i] -= directionalDspls[0];
301    
302     MPI_Type_struct(3, directionalBC, directionalDspls, directionalMbrTypes,
303     &mpiDirectionalStructType);
304     MPI_Type_commit(&mpiDirectionalStructType);
305    
306     // ***********************************************************************
307    
308     if( worldRank == 0 ){
309     #endif
310    
311     // generate the force file name
312    
313     strcpy( fileName, "WATER.frc" );
314     // fprintf( stderr,"Trying to open %s\n", fileName );
315    
316     // attempt to open the file in the current directory first.
317    
318     frcFile = fopen( fileName, "r" );
319    
320     if( frcFile == NULL ){
321    
322     // next see if the force path enviorment variable is set
323    
324     ffPath = getenv( ffPath_env );
325     if( ffPath == NULL ) {
326     STR_DEFINE(ffPath, FRC_PATH );
327     }
328    
329    
330     strcpy( temp, ffPath );
331     strcat( temp, "/" );
332     strcat( temp, fileName );
333     strcpy( fileName, temp );
334    
335     frcFile = fopen( fileName, "r" );
336    
337     if( frcFile == NULL ){
338    
339     sprintf( painCave.errMsg,
340     "Error opening the force field parameter file:\n"
341     "\t%s\n"
342     "\tHave you tried setting the FORCE_PARAM_PATH environment "
343     "variable?\n",
344     fileName );
345     painCave.severity = OOPSE_ERROR;
346     painCave.isFatal = 1;
347     simError();
348     }
349     }
350    
351     #ifdef IS_MPI
352     }
353    
354     sprintf( checkPointMsg, "WATER file opened sucessfully." );
355     MPIcheckPoint();
356    
357     #endif // is_mpi
358     }
359    
360    
361     WATER::~WATER(){
362    
363     if( headAtomType != NULL ) delete headAtomType;
364     if( headDirectionalType != NULL ) delete headDirectionalType;
365    
366     #ifdef IS_MPI
367     if( worldRank == 0 ){
368     #endif // is_mpi
369    
370     fclose( frcFile );
371    
372     #ifdef IS_MPI
373     }
374     #endif // is_mpi
375     }
376    
377     void WATER::cleanMe( void ){
378    
379     #ifdef IS_MPI
380    
381     // keep the linked list in the mpi version
382    
383     #else // is_mpi
384    
385     // delete the linked list in the single processor version
386    
387     if( headAtomType != NULL ) delete headAtomType;
388     if( headDirectionalType != NULL ) delete headDirectionalType;
389    
390     #endif // is_mpi
391     }
392    
393    
394     void WATER::initForceField( int ljMixRule ){
395    
396     initFortran( ljMixRule, entry_plug->useReactionField );
397     }
398    
399    
400     void WATER::readParams( void ){
401    
402     int identNum;
403     int tempDirect0, tempDirect1;
404    
405     atomStruct atomInfo;
406     directionalStruct directionalInfo;
407     fpos_t *atomPos;
408    
409     atomInfo.last = 1; // initialize last to have the last set.
410     directionalInfo.last = 1; // if things go well, last will be set to 0
411    
412     atomPos = new fpos_t;
413     bigSigma = 0.0;
414    
415     #ifdef IS_MPI
416     if( worldRank == 0 ){
417     #endif
418    
419     // read in the atom types.
420    
421     headAtomType = new LinkedAtomType;
422     headDirectionalType = new LinkedDirectionalType;
423    
424     fastForward( "AtomTypes", "initializeAtoms" );
425    
426     // we are now at the AtomTypes section.
427    
428     eof_test = fgets( readLine, sizeof(readLine), frcFile );
429     lineNum++;
430    
431    
432     // read a line, and start parsing out the atom types
433    
434     if( eof_test == NULL ){
435     sprintf( painCave.errMsg,
436     "Error in reading Atoms from force file at line %d.\n",
437     lineNum );
438     painCave.isFatal = 1;
439     simError();
440     }
441    
442     identNum = 1;
443     // stop reading at end of file, or at next section
444     while( readLine[0] != '#' && eof_test != NULL ){
445    
446     // toss comment lines
447     if( readLine[0] != '!' ){
448    
449     // the parser returns 0 if the line was blank
450     if( parseAtom( readLine, lineNum, atomInfo ) ){
451     atomInfo.ident = identNum;
452     headAtomType->add( atomInfo );
453     if ( atomInfo.isDirectional ) {
454    
455     // if the atom is directional, skip to the directional section
456     // and parse directional info.
457     fgetpos( frcFile, atomPos );
458     sectionSearch( "DirectionalTypes", atomInfo.name,
459     "initializeDirectional" );
460     parseDirectional( readLine, lineNum, directionalInfo );
461     headDirectionalType->add( directionalInfo );
462    
463     // return to the AtomTypes section
464     fsetpos( frcFile, atomPos );
465     }
466     identNum++;
467     }
468     }
469     eof_test = fgets( readLine, sizeof(readLine), frcFile );
470     lineNum++;
471     }
472    
473     #ifdef IS_MPI
474    
475     // send out the linked list to all the other processes
476    
477     sprintf( checkPointMsg,
478     "WATER atom and directional structures read successfully." );
479     MPIcheckPoint();
480     currentAtomType = headAtomType->next; //skip the first element place holder
481     currentDirectionalType = headDirectionalType->next; // same w/ directional
482    
483     while( currentAtomType != NULL ){
484     currentAtomType->duplicate( atomInfo );
485    
486     sendFrcStruct( &atomInfo, mpiAtomStructType );
487    
488     sprintf( checkPointMsg,
489     "successfully sent WATER force type: \"%s\"\n",
490     atomInfo.name );
491    
492     if ( atomInfo.isDirectional ){
493     // send out the directional linked list to all the other processes
494    
495     currentDirectionalType->duplicate( directionalInfo );
496     sendFrcStruct( &directionalInfo, mpiDirectionalStructType );
497    
498     sprintf( checkPointMsg,
499     "successfully sent WATER directional type: \"%s\"\n",
500     directionalInfo.name );
501     }
502    
503     MPIcheckPoint();
504     tempDirect0 = atomInfo.isDirectional;
505     currentAtomType = currentAtomType->next;
506     if( tempDirect0 )
507     currentDirectionalType = currentDirectionalType->next;
508     }
509    
510     atomInfo.last = 1;
511     sendFrcStruct( &atomInfo, mpiAtomStructType );
512     directionalInfo.last = 1;
513     if ( atomInfo.isDirectional )
514     sendFrcStruct( &directionalInfo, mpiDirectionalStructType );
515     }
516    
517     else{
518     // listen for node 0 to send out the force params
519    
520     MPIcheckPoint();
521    
522     headAtomType = new LinkedAtomType;
523     headDirectionalType = new LinkedDirectionalType;
524     receiveFrcStruct( &atomInfo, mpiAtomStructType );
525    
526     if ( atomInfo.isDirectional )
527     receiveFrcStruct( &directionalInfo, mpiDirectionalStructType );
528    
529     while( !atomInfo.last ){
530    
531     headAtomType->add( atomInfo );
532    
533     MPIcheckPoint();
534    
535     receiveFrcStruct( &atomInfo, mpiAtomStructType );
536    
537     if( atomInfo.isDirectional ){
538     headDirectionalType->add( directionalInfo );
539    
540     receiveFrcStruct( &directionalInfo, mpiDirectionalStructType );
541     }
542     }
543     }
544    
545     #endif // is_mpi
546    
547     // call new A_types in fortran
548    
549     int isError;
550    
551     // dummy variables
552     int isGB = 0;
553     int isEAM = 0;
554     int notDipole = 0;
555     int notSSD = 0;
556     double noDipMoment = 0.0;
557    
558    
559     currentAtomType = headAtomType->next;
560     currentDirectionalType = headDirectionalType->next;
561    
562     while( currentAtomType != NULL ){
563    
564     if( currentAtomType->isLJ ) entry_plug->useLJ = 1;
565     if( currentAtomType->isCharge ) entry_plug->useCharges = 1;
566     if( currentAtomType->isDirectional ){
567     // only directional atoms can have dipoles or be sticky
568     if ( currentDirectionalType->isDipole ) entry_plug->useDipoles = 1;
569     if ( currentDirectionalType->isSticky ) {
570     entry_plug->useSticky = 1;
571     set_sticky_params( &(currentDirectionalType->w0),
572     &(currentDirectionalType->v0),
573     &(currentDirectionalType->v0p),
574     &(currentDirectionalType->rl),
575     &(currentDirectionalType->ru),
576     &(currentDirectionalType->rlp),
577     &(currentDirectionalType->rup));
578     }
579     if( currentAtomType->name[0] != '\0' ){
580     isError = 0;
581     makeAtype( &(currentAtomType->ident),
582     &(currentAtomType->isLJ),
583     &(currentDirectionalType->isSticky),
584     &(currentDirectionalType->isDipole),
585     &isGB,
586     &isEAM,
587     &(currentAtomType->isCharge),
588     &(currentAtomType->epslon),
589     &(currentAtomType->sigma),
590     &(currentAtomType->charge),
591     &(currentDirectionalType->dipole),
592     &isError );
593     if( isError ){
594     sprintf( painCave.errMsg,
595     "Error initializing the \"%s\" atom type in fortran\n",
596     currentAtomType->name );
597     painCave.isFatal = 1;
598     simError();
599     }
600     }
601     currentDirectionalType->next;
602     }
603    
604     else {
605     // use all dummy variables if this is not a directional atom
606     if( currentAtomType->name[0] != '\0' ){
607     isError = 0;
608     makeAtype( &(currentAtomType->ident),
609     &(currentAtomType->isLJ),
610     &notSSD,
611     &notDipole,
612     &isGB,
613     &isEAM,
614     &(currentAtomType->isCharge),
615     &(currentAtomType->epslon),
616     &(currentAtomType->sigma),
617     &(currentAtomType->charge),
618     &noDipMoment,
619     &isError );
620     if( isError ){
621     sprintf( painCave.errMsg,
622     "Error initializing the \"%s\" atom type in fortran\n",
623     currentAtomType->name );
624     painCave.isFatal = 1;
625     simError();
626     }
627     }
628     }
629     currentAtomType = currentAtomType->next;
630     }
631    
632     #ifdef IS_MPI
633     sprintf( checkPointMsg,
634     "WATER atom and directional structures successfully"
635     "sent to fortran\n" );
636     MPIcheckPoint();
637     #endif // is_mpi
638    
639     }
640    
641    
642     void WATER::initializeAtoms( int nAtoms, Atom** the_atoms ){
643    
644     int i,j,k;
645    
646     // initialize the atoms
647     DirectionalAtom* dAtom;
648     double ji[3];
649     double inertialMat[3][3];
650    
651     for( i=0; i<nAtoms; i++ ){
652     currentAtomType = headAtomType->find( the_atoms[i]->getType() );
653     if( currentAtomType == NULL ){
654     sprintf( painCave.errMsg,
655     "AtomType error, %s not found in force file.\n",
656     the_atoms[i]->getType() );
657     painCave.isFatal = 1;
658     simError();
659     }
660     the_atoms[i]->setMass( currentAtomType->mass );
661     the_atoms[i]->setIdent( currentAtomType->ident );
662    
663     if( bigSigma < currentAtomType->sigma ) bigSigma = currentAtomType->sigma;
664    
665     the_atoms[i]->setHasCharge(currentAtomType->isCharge);
666    
667     if( currentAtomType->isDirectional ){
668     currentDirectionalType =
669     headDirectionalType->find( the_atoms[i]->getType() );
670     if( currentDirectionalType == NULL ){
671     sprintf( painCave.errMsg,
672     "DirectionalType error, %s not found in force file.\n",
673     the_atoms[i]->getType() );
674     painCave.isFatal = 1;
675     simError();
676     }
677    
678     // zero out the moments of inertia matrix
679     for( j=0; j<3; j++ )
680     for( k=0; k<3; k++ )
681     inertialMat[j][k] = 0.0;
682    
683     // load the force file moments of inertia
684     inertialMat[0][0] = currentDirectionalType->Ixx;
685     inertialMat[1][1] = currentDirectionalType->Iyy;
686     inertialMat[2][2] = currentDirectionalType->Izz;
687    
688     dAtom = (DirectionalAtom *) the_atoms[i];
689     dAtom->setHasDipole( currentDirectionalType->isDipole );
690    
691     ji[0] = 0.0;
692     ji[1] = 0.0;
693     ji[2] = 0.0;
694     dAtom->setJ( ji );
695     dAtom->setI( inertialMat );
696    
697     entry_plug->n_dipoles++;
698     }
699     }
700     }
701    
702     void WATER::initializeBonds( int nBonds, Bond** BondArray,
703     bond_pair* the_bonds ){
704    
705     if( nBonds ){
706     sprintf( painCave.errMsg,
707     "WATER does not support bonds.\n" );
708     painCave.isFatal = 1;
709     simError();
710     }
711     }
712    
713     void WATER::initializeBends( int nBends, Bend** bendArray,
714     bend_set* the_bends ){
715    
716     if( nBends ){
717     sprintf( painCave.errMsg,
718     "WATER does not support bends.\n" );
719     painCave.isFatal = 1;
720     simError();
721     }
722     }
723    
724     void WATER::initializeTorsions( int nTorsions, Torsion** torsionArray,
725     torsion_set* the_torsions ){
726    
727     if( nTorsions ){
728     sprintf( painCave.errMsg,
729     "WATER does not support torsions.\n" );
730     painCave.isFatal = 1;
731     simError();
732     }
733     }
734    
735     void WATER::fastForward( char* stopText, char* searchOwner ){
736    
737     int foundText = 0;
738     char* the_token;
739    
740     rewind( frcFile );
741     lineNum = 0;
742    
743     eof_test = fgets( readLine, sizeof(readLine), frcFile );
744     lineNum++;
745     if( eof_test == NULL ){
746     sprintf( painCave.errMsg, "Error fast forwarding force file for %s: "
747     " file is empty.\n",
748     searchOwner );
749     painCave.isFatal = 1;
750     simError();
751     }
752    
753    
754     while( !foundText ){
755     while( eof_test != NULL && readLine[0] != '#' ){
756     eof_test = fgets( readLine, sizeof(readLine), frcFile );
757     lineNum++;
758     }
759     if( eof_test == NULL ){
760     sprintf( painCave.errMsg,
761     "Error fast forwarding force file for %s at "
762     "line %d: file ended unexpectedly.\n",
763     searchOwner,
764     lineNum );
765     painCave.isFatal = 1;
766     simError();
767     }
768    
769     the_token = strtok( readLine, " ,;\t#\n" );
770     foundText = !strcmp( stopText, the_token );
771    
772     if( !foundText ){
773     eof_test = fgets( readLine, sizeof(readLine), frcFile );
774     lineNum++;
775    
776     if( eof_test == NULL ){
777     sprintf( painCave.errMsg,
778     "Error fast forwarding force file for %s at "
779     "line %d: file ended unexpectedly.\n",
780     searchOwner,
781     lineNum );
782     painCave.isFatal = 1;
783     simError();
784     }
785     }
786     }
787     }
788    
789     void WATER::sectionSearch( char* secHead, char* stopText, char* searchOwner ){
790    
791     int foundSection = 0;
792     int foundText = 0;
793     char* the_token;
794     fpos_t *tempPos;
795    
796     rewind( frcFile );
797     lineNum = 0;
798     tempPos = new fpos_t;
799    
800     eof_test = fgets( readLine, sizeof(readLine), frcFile );
801     lineNum++;
802     if( eof_test == NULL ){
803     sprintf( painCave.errMsg, "Error fast forwarding force file for %s: "
804     " file is empty.\n",
805     searchOwner );
806     painCave.isFatal = 1;
807     simError();
808     }
809    
810     while( !foundSection ){
811     while( eof_test != NULL && readLine[0] != '#' ){
812     eof_test = fgets( readLine, sizeof(readLine), frcFile );
813     lineNum++;
814     }
815     if( eof_test == NULL ){
816     sprintf( painCave.errMsg,
817     "Error fast forwarding force file for %s at "
818     "line %d: file ended unexpectedly.\n",
819     searchOwner,
820     lineNum );
821     painCave.isFatal = 1;
822     simError();
823     }
824     the_token = strtok( readLine, " ,;\t#\n" );
825     foundSection = !strcmp( secHead, the_token );
826    
827     if( !foundSection ){
828     eof_test = fgets( readLine, sizeof(readLine), frcFile );
829     lineNum++;
830    
831     if( eof_test == NULL ){
832     sprintf( painCave.errMsg,
833     "Error section searching force file for %s at "
834     "line %d: file ended unexpectedly.\n",
835     searchOwner,
836     lineNum );
837     painCave.isFatal = 1;
838     simError();
839     }
840     }
841     }
842    
843     while( !foundText ){
844    
845     fgetpos( frcFile, tempPos );
846     eof_test = fgets( readLine, sizeof(readLine), frcFile );
847     lineNum++;
848    
849     if( eof_test == NULL ){
850     sprintf( painCave.errMsg,
851     "Error fast forwarding force file for %s at "
852     "line %d: file ended unexpectedly.\n",
853     searchOwner,
854     lineNum );
855     painCave.isFatal = 1;
856     simError();
857     }
858    
859     the_token = strtok( readLine, " ,;\t#\n" );
860     if( the_token != NULL ){
861     foundText = !strcmp( stopText, the_token );
862     }
863     }
864     fsetpos( frcFile, tempPos );
865     eof_test = fgets( readLine, sizeof(readLine), frcFile );
866     lineNum++;
867     }
868    
869    
870     int WATER_NS::parseAtom( char *lineBuffer, int lineNum, atomStruct &info ){
871    
872     char* the_token;
873    
874     the_token = strtok( lineBuffer, " \n\t,;" );
875     if( the_token != NULL ){
876    
877     strcpy( info.name, the_token );
878    
879     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
880     sprintf( painCave.errMsg,
881     "Error parseing AtomTypes: line %d\n", lineNum );
882     painCave.isFatal = 1;
883     simError();
884     }
885    
886     info.isDirectional = atoi( the_token );
887    
888     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
889     sprintf( painCave.errMsg,
890     "Error parseing AtomTypes: line %d\n", lineNum );
891     painCave.isFatal = 1;
892     simError();
893     }
894    
895     info.isLJ = atoi( the_token );
896    
897     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
898     sprintf( painCave.errMsg,
899     "Error parseing AtomTypes: line %d\n", lineNum );
900     painCave.isFatal = 1;
901     simError();
902     }
903    
904     info.isCharge = atoi( the_token );
905    
906     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
907     sprintf( painCave.errMsg,
908     "Error parseing AtomTypes: line %d\n", lineNum );
909     painCave.isFatal = 1;
910     simError();
911     }
912    
913     info.mass = atof( the_token );
914    
915     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
916     sprintf( painCave.errMsg,
917     "Error parseing AtomTypes: line %d\n", lineNum );
918     painCave.isFatal = 1;
919     simError();
920     }
921    
922     info.epslon = atof( the_token );
923    
924     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
925     sprintf( painCave.errMsg,
926     "Error parseing AtomTypes: line %d\n", lineNum );
927     painCave.isFatal = 1;
928     simError();
929     }
930    
931     info.sigma = atof( the_token );
932    
933     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
934     sprintf( painCave.errMsg,
935     "Error parseing AtomTypes: line %d\n", lineNum );
936     painCave.isFatal = 1;
937     simError();
938     }
939    
940     info.charge = atof( the_token );
941    
942     return 1;
943     }
944     else return 0;
945     }
946    
947     int WATER_NS::parseDirectional( char *lineBuffer, int lineNum, directionalStruct &info ){
948    
949     char* the_token;
950    
951     the_token = strtok( lineBuffer, " \n\t,;" );
952     if( the_token != NULL ){
953    
954     strcpy( info.name, the_token );
955    
956     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
957     sprintf( painCave.errMsg,
958     "Error parseing DirectionalTypes: line %d\n", lineNum );
959     painCave.isFatal = 1;
960     simError();
961     }
962    
963     info.isDipole = atoi( the_token );
964    
965     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
966     sprintf( painCave.errMsg,
967     "Error parseing DirectionalTypes: line %d\n", lineNum );
968     painCave.isFatal = 1;
969     simError();
970     }
971    
972     info.isSticky = atoi( the_token );
973    
974     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
975     sprintf( painCave.errMsg,
976     "Error parseing DirectionalTypes: line %d\n", lineNum );
977     painCave.isFatal = 1;
978     simError();
979     }
980    
981     info.Ixx = atof( the_token );
982    
983     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
984     sprintf( painCave.errMsg,
985     "Error parseing DirectionalTypes: line %d\n", lineNum );
986     painCave.isFatal = 1;
987     simError();
988     }
989    
990     info.Iyy = atof( the_token );
991    
992     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
993     sprintf( painCave.errMsg,
994     "Error parseing DirectionalTypes: line %d\n", lineNum );
995     painCave.isFatal = 1;
996     simError();
997     }
998    
999     info.Izz = atof( the_token );
1000    
1001     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
1002     sprintf( painCave.errMsg,
1003     "Error parseing DirectionalTypes: line %d\n", lineNum );
1004     painCave.isFatal = 1;
1005     simError();
1006     }
1007    
1008    
1009     info.dipole = atof( the_token );
1010    
1011     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
1012     sprintf( painCave.errMsg,
1013     "Error parseing DirectionalTypes: line %d\n", lineNum );
1014     painCave.isFatal = 1;
1015     simError();
1016     }
1017    
1018     info.w0 = atof( the_token );
1019    
1020     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
1021     sprintf( painCave.errMsg,
1022     "Error parseing DirectionalTypes: line %d\n", lineNum );
1023     painCave.isFatal = 1;
1024     simError();
1025     }
1026    
1027     info.v0 = atof( the_token );
1028    
1029     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
1030     sprintf( painCave.errMsg,
1031     "Error parseing DirectionalTypes: line %d\n", lineNum );
1032     painCave.isFatal = 1;
1033     simError();
1034     }
1035    
1036     info.v0p = atof( the_token );
1037    
1038     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
1039     sprintf( painCave.errMsg,
1040     "Error parseing DirectionalTypes: line %d\n", lineNum );
1041     painCave.isFatal = 1;
1042     simError();
1043     }
1044    
1045     info.rl = atof( the_token );
1046    
1047     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
1048     sprintf( painCave.errMsg,
1049     "Error parseing DirectionalTypes: line %d\n", lineNum );
1050     painCave.isFatal = 1;
1051     simError();
1052     }
1053    
1054     info.ru = atof( the_token );
1055    
1056     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
1057     sprintf( painCave.errMsg,
1058     "Error parseing DirectionalTypes: line %d\n", lineNum );
1059     painCave.isFatal = 1;
1060     simError();
1061     }
1062    
1063     info.rlp = atof( the_token );
1064    
1065     if( ( the_token = strtok( NULL, " \n\t,;" ) ) == NULL ){
1066     sprintf( painCave.errMsg,
1067     "Error parseing DirectionalTypes: line %d\n", lineNum );
1068     painCave.isFatal = 1;
1069     simError();
1070     }
1071    
1072     info.rup = atof( the_token );
1073    
1074     return 1;
1075     }
1076     else return 0;
1077     }
1078     double WATER::getAtomTypeMass (char* atomType) {
1079    
1080     currentAtomType = headAtomType->find( atomType );
1081     if( currentAtomType == NULL ){
1082     sprintf( painCave.errMsg,
1083     "AtomType error, %s not found in force file.\n",
1084     atomType );
1085     painCave.isFatal = 1;
1086     simError();
1087     }
1088    
1089     return currentAtomType->mass;
1090     }