ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-3.0/src/UseTheForce/Shapes_FF.cpp
Revision: 2204
Committed: Fri Apr 15 22:04:00 2005 UTC (19 years, 2 months ago) by gezelter
File size: 18362 byte(s)
Log Message:
xemacs has been drafted to perform our indentation services

File Contents

# Content
1 /*
2 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 *
4 * The University of Notre Dame grants you ("Licensee") a
5 * non-exclusive, royalty free, license to use, modify and
6 * redistribute this software in source and binary code form, provided
7 * that the following conditions are met:
8 *
9 * 1. Acknowledgement of the program authors must be made in any
10 * publication of scientific results based in part on use of the
11 * program. An acceptable form of acknowledgement is citation of
12 * the article in which the program was described (Matthew
13 * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14 * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15 * Parallel Simulation Engine for Molecular Dynamics,"
16 * J. Comput. Chem. 26, pp. 252-271 (2005))
17 *
18 * 2. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 3. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * This software is provided "AS IS," without a warranty of any
27 * kind. All express or implied conditions, representations and
28 * warranties, including any implied warranty of merchantability,
29 * fitness for a particular purpose or non-infringement, are hereby
30 * excluded. The University of Notre Dame and its licensors shall not
31 * be liable for any damages suffered by licensee as a result of
32 * using, modifying or distributing the software or its
33 * derivatives. In no event will the University of Notre Dame or its
34 * licensors be liable for any lost revenue, profit or data, or for
35 * direct, indirect, special, consequential, incidental or punitive
36 * damages, however caused and regardless of the theory of liability,
37 * arising out of the use of or inability to use software, even if the
38 * University of Notre Dame has been advised of the possibility of
39 * such damages.
40 */
41
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <map>
46 #include <cmath>
47 #include <iostream>
48
49 #ifdef IS_MPI
50 #include <mpi.h>
51 #endif //is_mpi
52
53 #include "UseTheForce/ForceFields.hpp"
54 #include "primitives/SRI.hpp"
55 #include "utils/simError.h"
56 #include "utils/StringUtils.hpp"
57 #include "io/basic_ifstrstream.hpp"
58 #include "math/RealSphericalHarmonic.hpp"
59 #include "math/SquareMatrix3.hpp"
60 #include "types/ShapeAtomType.hpp"
61 #include "UseTheForce/DarkSide/atype_interface.h"
62 #include "UseTheForce/DarkSide/shapes_interface.h"
63
64 #ifdef IS_MPI
65 #include "UseTheForce/mpiForceField.h"
66 #endif // is_mpi
67
68
69 using namespace oopse;
70
71 Shapes_FF::~Shapes_FF(){
72
73 destroyShapeTypes();
74 #ifdef IS_MPI
75 if( worldRank == 0 ){
76 #endif // is_mpi
77
78 forceFile.close();
79
80 #ifdef IS_MPI
81 }
82 #endif // is_mpi
83 }
84
85
86 void Shapes_FF::calcRcut( void ){
87
88 #ifdef IS_MPI
89 double tempShapesRcut = bigContact;
90 MPI_Allreduce( &tempShapesRcut, &shapesRcut, 1, MPI_DOUBLE, MPI_MAX,
91 MPI_COMM_WORLD);
92 #else
93 shapesRcut = bigContact;
94 #endif //is_mpi
95 entry_plug->setDefaultRcut(shapesRcut);
96 }
97
98
99 void Shapes_FF::initForceField(){
100 initFortran(0);
101 }
102
103
104 void Shapes_FF::readParams( void ){
105
106 char readLine[1024];
107
108 std::string fileName;
109 std::string shapeFileName;
110 std::string tempString;
111
112 char *nameToken;
113 char *delim = " ,;\t\n";
114 int nTokens, i;
115 int nContact = 0;
116 int nRange = 0;
117 int nStrength = 0;
118 int myATID;
119 int isError;
120 std::string nameString;
121 AtomType* at;
122 DirectionalAtomType* dat;
123 ShapeAtomType* st;
124
125 std::map<string, AtomType*>::iterator iter;
126
127 // vectors for shape transfer to fortran
128 std::vector<RealSphericalHarmonic*> tempSHVector;
129 std::vector<int> contactL;
130 std::vector<int> contactM;
131 std::vector<int> contactFunc;
132 std::vector<double> contactCoeff;
133 std::vector<int> rangeL;
134 std::vector<int> rangeM;
135 std::vector<int> rangeFunc;
136 std::vector<double> rangeCoeff;
137 std::vector<int> strengthL;
138 std::vector<int> strengthM;
139 std::vector<int> strengthFunc;
140 std::vector<double> strengthCoeff;
141
142 // generate the force file name
143 fileName = "Shapes.frc";
144
145 // attempt to open the file in the current directory first.
146 forceFile.open( fileName.c_str() );
147
148 if( forceFile == NULL ){
149
150 tempString = ffPath;
151 tempString += "/";
152 tempString += fileName;
153 fileName = tempString;
154
155 forceFile.open( fileName.c_str() );
156
157 if( forceFile == NULL ){
158
159 sprintf( painCave.errMsg,
160 "Error opening the force field parameter file:\n"
161 "\t%s\n"
162 "\tHave you tried setting the FORCE_PARAM_PATH environment "
163 "variable?\n",
164 fileName.c_str() );
165 painCave.severity = OOPSE_ERROR;
166 painCave.isFatal = 1;
167 simError();
168 }
169 }
170
171 // read in the shape types.
172
173 findBegin( forceFile, "ShapeTypes" );
174
175 while( !forceFile.eof() ){
176 forceFile.getline( readLine, sizeof(readLine) );
177
178 // toss comment lines
179 if( readLine[0] != '!' && readLine[0] != '#' ){
180
181 if (isEndLine(readLine)) break;
182
183 nTokens = countTokens(readLine, " ,;\t");
184 if (nTokens != 0) {
185 if (nTokens < 2) {
186 sprintf( painCave.errMsg,
187 "Not enough data on a ShapeTypes line in file: %s\n",
188 fileName.c_str() );
189 painCave.severity = OOPSE_ERROR;
190 painCave.isFatal = 1;
191 simError();
192 }
193
194 nameToken = strtok( readLine, delim );
195 shapeFileName = strtok( NULL, delim );
196
197 // strings are not char arrays!
198 nameString = nameToken;
199
200 // does this AtomType name already exist in the map?
201 iter = atomTypeMap.find(nameString);
202 if (iter == atomTypeMap.end()) {
203 // no, it doesn't, so we may proceed:
204
205 st = new ShapeAtomType();
206
207 st->setName(nameString);
208 myATID = atomTypeMap.size() + 1;
209 st->setIdent(myATID);
210 parseShapeFile(shapeFileName, st);
211 st->complete();
212 atomTypeMap.insert(make_pair(nameString, st));
213
214 } else {
215 // atomType map already contained this std::string (i.e. it was
216 // declared in a previous block, and we just need to add
217 // the shape-specific information for this AtomType:
218
219 st = (ShapeAtomType*)(iter->second);
220 parseShapeFile(shapeFileName, st);
221 }
222 }
223 }
224 }
225
226 #ifdef IS_MPI
227
228 // looks like all the processors have their ShapeType vectors ready...
229 sprintf( checkPointMsg,
230 "Shapes_FF shape objects read successfully." );
231 MPIcheckPoint();
232
233 #endif // is_mpi
234
235 // pack up and send the necessary info to fortran
236 for (iter = atomTypeMap.begin(); iter != atomTypeMap.end(); ++iter){
237
238 at = (AtomType*)(iter->second);
239
240 if (at->isDirectional()) {
241
242 dat = (DirectionalAtomType*)at;
243
244 if (dat->isShape()) {
245
246 st = (ShapeAtomType*)at;
247
248 contactL.clear();
249 contactM.clear();
250 contactFunc.clear();
251 contactCoeff.clear();
252
253 tempSHVector = st->getContactFuncs();
254
255 nContact = tempSHVector.size();
256 for (i=0; i<nContact; i++){
257 contactL.push_back(tempSHVector[i]->getL());
258 contactM.push_back(tempSHVector[i]->getM());
259 contactFunc.push_back(tempSHVector[i]->getFunctionType());
260 contactCoeff.push_back(tempSHVector[i]->getCoefficient());
261 }
262
263 rangeL.clear();
264 rangeM.clear();
265 rangeFunc.clear();
266 rangeCoeff.clear();
267
268 tempSHVector = st->getRangeFuncs();
269
270 nRange = tempSHVector.size();
271 for (i=0; i<nRange; i++){
272 rangeL.push_back(tempSHVector[i]->getL());
273 rangeM.push_back(tempSHVector[i]->getM());
274 rangeFunc.push_back(tempSHVector[i]->getFunctionType());
275 rangeCoeff.push_back(tempSHVector[i]->getCoefficient());
276 }
277
278 strengthL.clear();
279 strengthM.clear();
280 strengthFunc.clear();
281 strengthCoeff.clear();
282
283 tempSHVector = st->getStrengthFuncs();
284
285 nStrength = tempSHVector.size();
286 for (i=0; i<nStrength; i++){
287 strengthL.push_back(tempSHVector[i]->getL());
288 strengthM.push_back(tempSHVector[i]->getM());
289 strengthFunc.push_back(tempSHVector[i]->getFunctionType());
290 strengthCoeff.push_back(tempSHVector[i]->getCoefficient());
291 }
292
293 isError = 0;
294 myATID = at->getIdent();
295
296 makeShape( &nContact, &contactL[0], &contactM[0], &contactFunc[0],
297 &contactCoeff[0],
298 &nRange, &rangeL[0], &rangeM[0], &rangeFunc[0],
299 &rangeCoeff[0],
300 &nStrength, &strengthL[0], &strengthM[0],
301 &strengthFunc[0], &strengthCoeff[0],
302 &myATID,
303 &isError);
304
305 if( isError ){
306 sprintf( painCave.errMsg,
307 "Error initializing the \"%s\" shape in fortran\n",
308 (iter->first).c_str() );
309 painCave.isFatal = 1;
310 simError();
311 }
312 }
313 }
314 }
315
316 isError = 0;
317 completeShapeFF(&isError);
318 if( isError ){
319 sprintf( painCave.errMsg,
320 "Error completing Shape FF in fortran\n");
321 painCave.isFatal = 1;
322 simError();
323 }
324
325 #ifdef IS_MPI
326 sprintf( checkPointMsg,
327 "Shapes_FF atom structures successfully sent to fortran\n" );
328 MPIcheckPoint();
329 #endif // is_mpi
330
331 }
332
333 void Shapes_FF::cleanMe( void ){
334
335 }
336
337 void Shapes_FF::initializeAtoms( int nAtoms, Atom** the_atoms ){
338
339 int i,j,k;
340 std::map<string, AtomType*>::iterator iter;
341
342 // initialize the atoms
343 DirectionalAtom* dAtom;
344 AtomType* at;
345 DirectionalAtomType* dat;
346 ShapeAtomType* sat;
347 double longCutoff;
348 double ji[3];
349 double inertialMat[3][3];
350 Mat3x3d momInt;
351 std::string myTypeString;
352
353 bigContact = 0.0;
354
355 for( i=0; i<nAtoms; i++ ){
356
357 myTypeString = the_atoms[i]->getType().c_str();
358 iter = atomTypeMap.find(myTypeString);
359
360 if (iter == atomTypeMap.end()) {
361 sprintf( painCave.errMsg,
362 "AtomType error, %s not found in force file.\n",
363 the_atoms[i]->getType().c_str() );
364 painCave.isFatal = 1;
365 simError();
366 } else {
367
368 at = (AtomType*)(iter->second);
369
370 the_atoms[i]->setMass( at->getMass() );
371 the_atoms[i]->setIdent( at->getIdent() );
372
373 if ( at->isShape() ) {
374
375 sat = (ShapeAtomType*)at;
376 longCutoff = findCutoffDistance(sat);
377 if (longCutoff > bigContact) bigContact = longCutoff;
378 cout << bigContact << " is the cutoff value\n";
379
380 entry_plug->useShapes = 1;
381 }
382
383 the_atoms[i]->setHasCharge(at->isCharge());
384
385 if( at->isDirectional() ){
386
387 dat = (DirectionalAtomType*)at;
388 dAtom = (DirectionalAtom *) the_atoms[i];
389
390 momInt = dat->getI();
391
392 // zero out the moments of inertia matrix
393 for( j=0; j<3; j++ )
394 for( k=0; k<3; k++ )
395 inertialMat[j][k] = momInt(j,k);
396 dAtom->setI( inertialMat );
397
398 ji[0] = 0.0;
399 ji[1] = 0.0;
400 ji[2] = 0.0;
401 dAtom->setJ( ji );
402
403 if (dat->isDipole()) {
404 dAtom->setHasDipole( dat->isDipole() );
405 entry_plug->n_dipoles++;
406 }
407 }
408 }
409 }
410 }
411
412 void Shapes_FF::initializeBonds( int nBonds, Bond** BondArray,
413 bond_pair* the_bonds ){
414
415 if( nBonds ){
416 sprintf( painCave.errMsg,
417 "Shapes_FF does not support bonds.\n" );
418 painCave.isFatal = 1;
419 simError();
420 }
421 }
422
423 void Shapes_FF::initializeBends( int nBends, Bend** bendArray,
424 bend_set* the_bends ){
425
426 if( nBends ){
427 sprintf( painCave.errMsg,
428 "Shapes_FF does not support bends.\n" );
429 painCave.isFatal = 1;
430 simError();
431 }
432 }
433
434 void Shapes_FF::initializeTorsions( int nTorsions, Torsion** torsionArray,
435 torsion_set* the_torsions ){
436
437 if( nTorsions ){
438 sprintf( painCave.errMsg,
439 "Shapes_FF does not support torsions.\n" );
440 painCave.isFatal = 1;
441 simError();
442 }
443 }
444
445 void Shapes_FF::parseShapeFile(string shapeFileName, ShapeAtomType* st){
446 const int MAXLEN = 1024;
447 char inLine[MAXLEN];
448 char *token;
449 char *delim = " ,;\t\n";
450 int nTokens;
451 Mat3x3d momInert;
452 RealSphericalHarmonic* rsh;
453 std::vector<RealSphericalHarmonic*> functionVector;
454 ifstrstream shapeFile;
455 std::string tempString;
456
457 shapeFile.open( shapeFileName.c_str() );
458
459 if( shapeFile == NULL ){
460
461 tempString = ffPath;
462 tempString += "/";
463 tempString += shapeFileName;
464 shapeFileName = tempString;
465
466 shapeFile.open( shapeFileName.c_str() );
467
468 if( shapeFile == NULL ){
469
470 sprintf( painCave.errMsg,
471 "Error opening the shape file:\n"
472 "\t%s\n"
473 "\tHave you tried setting the FORCE_PARAM_PATH environment "
474 "variable?\n",
475 shapeFileName.c_str() );
476 painCave.severity = OOPSE_ERROR;
477 painCave.isFatal = 1;
478 simError();
479 }
480 }
481
482 // read in the shape types.
483
484 // first grab the values in the ShapeInfo section
485 findBegin( shapeFile, "ShapeInfo");
486
487 shapeFile.getline(inLine, MAXLEN);
488 while( !shapeFile.eof() ) {
489 // toss comment lines
490 if( inLine[0] != '!' && inLine[0] != '#' ){
491 // end marks section completion
492 if (isEndLine(inLine)) break;
493
494 nTokens = countTokens(inLine, delim);
495 if (nTokens != 0) {
496 if (nTokens < 5) {
497 sprintf( painCave.errMsg,
498 "Not enough data on a ShapeInfo line in file: %s\n",
499 shapeFileName.c_str() );
500 painCave.severity = OOPSE_ERROR;
501 painCave.isFatal = 1;
502 simError();
503 } else {
504 token = strtok(inLine, delim);
505 token = strtok(NULL, delim);
506 st->setMass(atof(token));
507 token = strtok(NULL, delim);
508 momInert(0,0) = atof(token);
509 token = strtok(NULL, delim);
510 momInert(1,1) = atof(token);
511 token = strtok(NULL, delim);
512 momInert(2,2) = atof(token);
513 st->setI(momInert);
514 }
515 }
516 }
517 shapeFile.getline(inLine, MAXLEN);
518 }
519
520 // now grab the contact functions
521 findBegin(shapeFile, "ContactFunctions");
522 functionVector.clear();
523
524 shapeFile.getline(inLine, MAXLEN);
525 while( !shapeFile.eof() ) {
526 // toss comment lines
527 if( inLine[0] != '!' && inLine[0] != '#' ){
528 // end marks section completion
529 if (isEndLine(inLine)) break;
530 nTokens = countTokens(inLine, delim);
531 if (nTokens != 0) {
532 if (nTokens < 4) {
533 sprintf( painCave.errMsg,
534 "Not enough data on a ContactFunctions line in file: %s\n",
535 shapeFileName.c_str() );
536 painCave.severity = OOPSE_ERROR;
537 painCave.isFatal = 1;
538 simError();
539 } else {
540 // read in a spherical harmonic function
541 token = strtok(inLine, delim);
542 rsh = new RealSphericalHarmonic();
543 rsh->setL(atoi(token));
544 token = strtok(NULL, delim);
545 rsh->setM(atoi(token));
546 token = strtok(NULL, delim);
547 if (!strcasecmp("sin",token))
548 rsh->makeSinFunction();
549 else
550 rsh->makeCosFunction();
551 token = strtok(NULL, delim);
552 rsh->setCoefficient(atof(token));
553
554 functionVector.push_back(rsh);
555 }
556 }
557 }
558 shapeFile.getline(inLine, MAXLEN);
559 }
560
561 // pass contact functions to ShapeType
562
563 st->setContactFuncs(functionVector);
564
565 // now grab the range functions
566 findBegin(shapeFile, "RangeFunctions");
567 functionVector.clear();
568
569 shapeFile.getline(inLine, MAXLEN);
570 while( !shapeFile.eof() ) {
571 // toss comment lines
572 if( inLine[0] != '!' && inLine[0] != '#' ){
573 // end marks section completion
574 if (isEndLine(inLine)) break;
575
576 nTokens = countTokens(inLine, delim);
577 if (nTokens != 0) {
578 if (nTokens < 4) {
579 sprintf( painCave.errMsg,
580 "Not enough data on a RangeFunctions line in file: %s\n",
581 shapeFileName.c_str() );
582 painCave.severity = OOPSE_ERROR;
583 painCave.isFatal = 1;
584 simError();
585 } else {
586
587 // read in a spherical harmonic function
588 token = strtok(inLine, delim);
589
590 rsh = new RealSphericalHarmonic();
591 rsh->setL(atoi(token));
592 token = strtok(NULL, delim);
593 rsh->setM(atoi(token));
594 token = strtok(NULL, delim);
595 if (!strcasecmp("sin",token))
596 rsh->makeSinFunction();
597 else
598 rsh->makeCosFunction();
599 token = strtok(NULL, delim);
600 rsh->setCoefficient(atof(token));
601
602 functionVector.push_back(rsh);
603 }
604 }
605 }
606 shapeFile.getline(inLine, MAXLEN);
607 }
608
609 // pass range functions to ShapeType
610 st->setRangeFuncs(functionVector);
611
612 // finally grab the strength functions
613 findBegin(shapeFile, "StrengthFunctions");
614 functionVector.clear();
615
616 shapeFile.getline(inLine, MAXLEN);
617 while( !shapeFile.eof() ) {
618 // toss comment lines
619 if( inLine[0] != '!' && inLine[0] != '#' ){
620 // end marks section completion
621 if (isEndLine(inLine)) break;
622
623 nTokens = countTokens(inLine, delim);
624 if (nTokens != 0) {
625 if (nTokens < 4) {
626 sprintf( painCave.errMsg,
627 "Not enough data on a StrengthFunctions line in file: %s\n",
628 shapeFileName.c_str() );
629 painCave.severity = OOPSE_ERROR;
630 painCave.isFatal = 1;
631 simError();
632 } else {
633
634 // read in a spherical harmonic function
635 token = strtok(inLine, delim);
636 rsh = new RealSphericalHarmonic();
637 rsh->setL(atoi(token));
638 token = strtok(NULL, delim);
639 rsh->setM(atoi(token));
640 token = strtok(NULL, delim);
641 if (!strcasecmp("sin",token))
642 rsh->makeSinFunction();
643 else
644 rsh->makeCosFunction();
645 token = strtok(NULL, delim);
646 rsh->setCoefficient(atof(token));
647
648 functionVector.push_back(rsh);
649 }
650 }
651 }
652 shapeFile.getline(inLine, MAXLEN);
653 }
654
655 // pass strength functions to ShapeType
656 st->setStrengthFuncs(functionVector);
657
658 // we're done reading from this file
659 shapeFile.close();
660 }
661
662 double Shapes_FF::findLargestContactDistance(ShapeAtomType* st) {
663 int i, j, nSteps;
664 double theta, thetaStep, thetaMin, costheta;
665 double phi, phiStep;
666 double sigma, bs;
667
668 nSteps = 16;
669
670 thetaStep = M_PI / nSteps;
671 thetaMin = thetaStep / 2.0;
672 phiStep = thetaStep * 2.0;
673 bs = 0.0;
674
675 for (i = 0; i < nSteps; i++) {
676
677 theta = thetaMin + i * thetaStep;
678 costheta = cos(theta);
679
680 for (j = 0; j < nSteps; j++) {
681
682 phi = j*phiStep;
683
684 sigma = st->getContactValueAt(costheta, phi);
685
686 if (sigma > bs) bs = sigma;
687 }
688 }
689
690 return bs;
691 }
692
693
694 double Shapes_FF::findCutoffDistance(ShapeAtomType* st) {
695 int i, j, nSteps;
696 double theta, thetaStep, thetaMin, costheta;
697 double phi, phiStep;
698 double sigma, range;
699 double bigCut, tempCut;
700
701 nSteps = 16;
702
703 thetaStep = M_PI / nSteps;
704 thetaMin = thetaStep / 2.0;
705 phiStep = thetaStep * 2.0;
706 bigCut = 0.0;
707
708 for (i = 0; i < nSteps; i++) {
709
710 theta = thetaMin + i * thetaStep;
711 costheta = cos(theta);
712
713 for (j = 0; j < nSteps; j++) {
714
715 phi = j*phiStep;
716
717 sigma = st->getContactValueAt(costheta, phi);
718 range = st->getRangeValueAt(costheta, phi);
719
720 // cutoff for a shape is taken to be (1.5*rangeVal + contactVal)
721 tempCut = 1.5*range + sigma;
722
723 if (tempCut > bigCut) bigCut = tempCut;
724 }
725 }
726
727 return bigCut;
728 }