ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-2.0/src/restraints/Restraints.cpp
Revision: 1826
Committed: Thu Dec 2 05:04:20 2004 UTC (19 years, 7 months ago) by tim
File size: 14229 byte(s)
Log Message:
adding qulified name prefix std

File Contents

# Content
1 // Thermodynamic integration is not multiprocessor friendly right now
2
3
4
5 #include <iostream>
6
7 #include <stdlib.h>
8
9 #include <cstdio>
10
11 #include <fstream>
12
13 #include <iomanip>
14
15 #include <string>
16
17 #include <cstring>
18
19 #include <math.h>
20
21
22
23 using namespace std;
24
25
26
27 #include "restraints/Restraints.hpp"
28
29 #include "brains/SimInfo.hpp"
30
31 #include "utils/simError.h"
32
33
34
35 #define PI 3.14159265359
36
37 #define TWO_PI 6.28318530718
38
39
40
41 Restraints::Restraints(double lambdaVal, double lambdaExp){
42
43 lambdaValue = lambdaVal;
44
45 lambdaK = lambdaExp;
46
47 std::vector<double> resConsts;
48
49 const char *jolt = " \t\n;,";
50
51
52
53 #ifdef IS_MPI
54
55 if(worldRank == 0 ){
56
57 #endif // is_mpi
58
59
60
61 strcpy(springName, "HarmSpringConsts.txt");
62
63
64
65 ifstream springs(springName);
66
67
68
69 if (!springs) {
70
71 sprintf(painCave.errMsg,
72
73 "Unable to open HarmSpringConsts.txt for reading, so the\n"
74
75 "\tdefault spring constants will be loaded. If you want\n"
76
77 "\tto specify spring constants, include a three line\n"
78
79 "\tHarmSpringConsts.txt file in the execution directory.\n");
80
81 painCave.severity = OOPSE_WARNING;
82
83 painCave.isFatal = 0;
84
85 simError();
86
87
88
89 // load default spring constants
90
91 kDist = 6; // spring constant in units of kcal/(mol*ang^2)
92
93 kTheta = 7.5; // in units of kcal/mol
94
95 kOmega = 13.5; // in units of kcal/mol
96
97 } else {
98
99
100
101 springs.getline(inLine,999,'\n');
102
103 // the file is blank!
104
105 if (springs.eof()){
106
107 sprintf(painCave.errMsg,
108
109 "HarmSpringConsts.txt file is not valid.\n"
110
111 "\tThe file should contain four rows, the last three containing\n"
112
113 "\ta label and the spring constant value. They should be listed\n"
114
115 "\tin the following order: kDist (positional restrant), kTheta\n"
116
117 "\t(rot. restraint: deflection of z-axis), and kOmega (rot.\n"
118
119 "\trestraint: rotation about the z-axis).\n");
120
121 painCave.severity = OOPSE_ERROR;
122
123 painCave.isFatal = 1;
124
125 simError();
126
127 }
128
129 // read in spring constants and check to make sure it is a valid file
130
131 springs.getline(inLine,999,'\n');
132
133 while (!springs.eof()){
134
135 if (NULL != inLine){
136
137 token = strtok(inLine,jolt);
138
139 token = strtok(NULL,jolt);
140
141 if (NULL != token){
142
143 strcpy(inValue,token);
144
145 resConsts.push_back(atof(inValue));
146
147 }
148
149 }
150
151 springs.getline(inLine,999,'\n');
152
153 }
154
155 if (resConsts.size() == 3){
156
157 kDist = resConsts[0];
158
159 kTheta = resConsts[1];
160
161 kOmega = resConsts[2];
162
163 }
164
165 else {
166
167 sprintf(painCave.errMsg,
168
169 "HarmSpringConsts.txt file is not valid.\n"
170
171 "\tThe file should contain four rows, the last three containing\n"
172
173 "\ta label and the spring constant value. They should be listed\n"
174
175 "\tin the following order: kDist (positional restrant), kTheta\n"
176
177 "\t(rot. restraint: deflection of z-axis), and kOmega (rot.\n"
178
179 "\trestraint: rotation about the z-axis).\n");
180
181 painCave.severity = OOPSE_ERROR;
182
183 painCave.isFatal = 1;
184
185 simError();
186
187 }
188
189 }
190
191 #ifdef IS_MPI
192
193 }
194
195
196
197 MPI_Bcast(&kDist, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
198
199 MPI_Bcast(&kTheta, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
200
201 MPI_Bcast(&kOmega, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
202
203
204
205 sprintf( checkPointMsg,
206
207 "Sucessfully opened and read spring file.\n");
208
209 MPIcheckPoint();
210
211
212
213 #endif // is_mpi
214
215
216
217 sprintf(painCave.errMsg,
218
219 "The spring constants for thermodynamic integration are:\n"
220
221 "\tkDist = %lf\n"
222
223 "\tkTheta = %lf\n"
224
225 "\tkOmega = %lf\n", kDist, kTheta, kOmega);
226
227 painCave.severity = OOPSE_INFO;
228
229 painCave.isFatal = 0;
230
231 simError();
232
233 }
234
235
236
237 Restraints::~Restraints(){
238
239 }
240
241
242
243 void Restraints::Calc_rVal(double position[3], int currentMol){
244
245 delRx = position[0] - cofmPosX[currentMol];
246
247 delRy = position[1] - cofmPosY[currentMol];
248
249 delRz = position[2] - cofmPosZ[currentMol];
250
251
252
253 return;
254
255 }
256
257
258
259 void Restraints::Calc_body_thetaVal(double matrix[3][3], int currentMol){
260
261 ub0x = matrix[0][0]*uX0[currentMol] + matrix[0][1]*uY0[currentMol]
262
263 + matrix[0][2]*uZ0[currentMol];
264
265 ub0y = matrix[1][0]*uX0[currentMol] + matrix[1][1]*uY0[currentMol]
266
267 + matrix[1][2]*uZ0[currentMol];
268
269 ub0z = matrix[2][0]*uX0[currentMol] + matrix[2][1]*uY0[currentMol]
270
271 + matrix[2][2]*uZ0[currentMol];
272
273
274
275 normalize = sqrt(ub0x*ub0x + ub0y*ub0y + ub0z*ub0z);
276
277 ub0x = ub0x/normalize;
278
279 ub0y = ub0y/normalize;
280
281 ub0z = ub0z/normalize;
282
283
284
285 // Theta is the dot product of the reference and new z-axes
286
287 theta = acos(ub0z);
288
289
290
291 return;
292
293 }
294
295
296
297 void Restraints::Calc_body_omegaVal(double matrix[3][3], double zAngle){
298
299 double zRotator[3][3];
300
301 double tempOmega;
302
303 double wholeTwoPis;
304
305 // Use the omega accumulated from the rotation propagation
306
307 omega = zAngle;
308
309
310
311 // translate the omega into a range between -PI and PI
312
313 if (omega < -PI){
314
315 tempOmega = omega / -TWO_PI;
316
317 wholeTwoPis = floor(tempOmega);
318
319 tempOmega = omega + TWO_PI*wholeTwoPis;
320
321 if (tempOmega < -PI)
322
323 omega = tempOmega + TWO_PI;
324
325 else
326
327 omega = tempOmega;
328
329 }
330
331 if (omega > PI){
332
333 tempOmega = omega / TWO_PI;
334
335 wholeTwoPis = floor(tempOmega);
336
337 tempOmega = omega - TWO_PI*wholeTwoPis;
338
339 if (tempOmega > PI)
340
341 omega = tempOmega - TWO_PI;
342
343 else
344
345 omega = tempOmega;
346
347 }
348
349
350
351 vb0x = sin(omega);
352
353 vb0y = cos(omega);
354
355 vb0z = 0.0;
356
357
358
359 normalize = sqrt(vb0x*vb0x + vb0y*vb0y + vb0z*vb0z);
360
361 vb0x = vb0x/normalize;
362
363 vb0y = vb0y/normalize;
364
365 vb0z = vb0z/normalize;
366
367
368
369 return;
370
371 }
372
373
374
375 double Restraints::Calc_Restraint_Forces(vector<StuntDouble*> vecParticles){
376
377 double pos[3];
378
379 double A[3][3];
380
381 double tolerance;
382
383 double tempPotent;
384
385 double factor;
386
387 double spaceTrq[3];
388
389 double omegaPass;
390
391
392
393 tolerance = 5.72957795131e-7;
394
395
396
397 harmPotent = 0.0; // zero out the global harmonic potential variable
398
399
400
401 factor = 1 - pow(lambdaValue, lambdaK);
402
403
404
405 for (i=0; i<vecParticles.size(); i++){
406
407 if (vecParticles[i]->isDirectional()){
408
409 pos = vecParticles[i]->getPos();
410
411 vecParticles[i]->getA(A);
412
413 Calc_rVal( pos, i );
414
415 Calc_body_thetaVal( A, i );
416
417 omegaPass = vecParticles[i]->getZangle();
418
419 Calc_body_omegaVal( A, omegaPass );
420
421
422
423 // first we calculate the derivatives
424
425 dVdrx = -kDist*delRx;
426
427 dVdry = -kDist*delRy;
428
429 dVdrz = -kDist*delRz;
430
431
432
433 // uTx... and vTx... are the body-fixed z and y unit vectors
434
435 uTx = 0.0;
436
437 uTy = 0.0;
438
439 uTz = 1.0;
440
441 vTx = 0.0;
442
443 vTy = 1.0;
444
445 vTz = 0.0;
446
447
448
449 dVdux = 0;
450
451 dVduy = 0;
452
453 dVduz = 0;
454
455 dVdvx = 0;
456
457 dVdvy = 0;
458
459 dVdvz = 0;
460
461
462
463 if (fabs(theta) > tolerance) {
464
465 dVdux = -(kTheta*theta/sin(theta))*ub0x;
466
467 dVduy = -(kTheta*theta/sin(theta))*ub0y;
468
469 dVduz = -(kTheta*theta/sin(theta))*ub0z;
470
471 }
472
473
474
475 if (fabs(omega) > tolerance) {
476
477 dVdvx = -(kOmega*omega/sin(omega))*vb0x;
478
479 dVdvy = -(kOmega*omega/sin(omega))*vb0y;
480
481 dVdvz = -(kOmega*omega/sin(omega))*vb0z;
482
483 }
484
485
486
487 // next we calculate the restraint forces and torques
488
489 restraintFrc[0] = dVdrx;
490
491 restraintFrc[1] = dVdry;
492
493 restraintFrc[2] = dVdrz;
494
495 tempPotent = 0.5*kDist*(delRx*delRx + delRy*delRy + delRz*delRz);
496
497
498
499 restraintTrq[0] = 0.0;
500
501 restraintTrq[1] = 0.0;
502
503 restraintTrq[2] = 0.0;
504
505
506
507 if (fabs(omega) > tolerance) {
508
509 restraintTrq[0] += 0.0;
510
511 restraintTrq[1] += 0.0;
512
513 restraintTrq[2] += vTy*dVdvx;
514
515 tempPotent += 0.5*(kOmega*omega*omega);
516
517 }
518
519 if (fabs(theta) > tolerance) {
520
521 restraintTrq[0] += (uTz*dVduy);
522
523 restraintTrq[1] += -(uTz*dVdux);
524
525 restraintTrq[2] += 0.0;
526
527 tempPotent += 0.5*(kTheta*theta*theta);
528
529 }
530
531
532
533 for (j = 0; j < 3; j++) {
534
535 restraintFrc[j] *= factor;
536
537 restraintTrq[j] *= factor;
538
539 }
540
541
542
543 harmPotent += tempPotent;
544
545
546
547 // now we need to convert from body-fixed torques to space-fixed torques
548
549 spaceTrq[0] = A[0][0]*restraintTrq[0] + A[1][0]*restraintTrq[1]
550
551 + A[2][0]*restraintTrq[2];
552
553 spaceTrq[1] = A[0][1]*restraintTrq[0] + A[1][1]*restraintTrq[1]
554
555 + A[2][1]*restraintTrq[2];
556
557 spaceTrq[2] = A[0][2]*restraintTrq[0] + A[1][2]*restraintTrq[1]
558
559 + A[2][2]*restraintTrq[2];
560
561
562
563 // now it's time to pass these temporary forces and torques
564
565 // to the total forces and torques
566
567 vecParticles[i]->addFrc(restraintFrc);
568
569 vecParticles[i]->addTrq(spaceTrq);
570
571 }
572
573 }
574
575
576
577 // and we can return the appropriately scaled potential energy
578
579 tempPotent = harmPotent * factor;
580
581 return tempPotent;
582
583 }
584
585
586
587 void Restraints::Store_Init_Info(vector<StuntDouble*> vecParticles){
588
589 int idealSize;
590
591 double pos[3];
592
593 double A[3][3];
594
595 double RfromQ[3][3];
596
597 double quat0, quat1, quat2, quat3;
598
599 double dot;
600
601 std::vector<double> tempZangs;
602
603 const char *delimit = " \t\n;,";
604
605
606
607 //open the idealCrystal.in file and zAngle.ang file
608
609 strcpy(fileName, "idealCrystal.in");
610
611 strcpy(angleName, "zAngle.ang");
612
613
614
615 ifstream crystalIn(fileName);
616
617 ifstream angleIn(angleName);
618
619
620
621 // check to see if these files are present in the execution directory
622
623 if (!crystalIn) {
624
625 sprintf(painCave.errMsg,
626
627 "Restraints Error: Unable to open idealCrystal.in for reading.\n"
628
629 "\tMake sure a ref. crystal file is in the working directory.\n");
630
631 painCave.severity = OOPSE_ERROR;
632
633 painCave.isFatal = 1;
634
635 simError();
636
637 }
638
639
640
641 // it's not fatal to lack a zAngle.ang file, it just means you're starting
642
643 // from the ideal crystal state
644
645 if (!angleIn) {
646
647 sprintf(painCave.errMsg,
648
649 "Restraints Warning: The lack of a zAngle.ang file is mildly\n"
650
651 "\tunsettling... This means the simulation is starting from the\n"
652
653 "\tidealCrystal.in reference configuration, so the omega values\n"
654
655 "\twill all be set to zero. If this is not the case, the energy\n"
656
657 "\tcalculations will be wrong.\n");
658
659 painCave.severity = OOPSE_WARNING;
660
661 painCave.isFatal = 0;
662
663 simError();
664
665 }
666
667
668
669 // A rather specific reader for OOPSE .eor files...
670
671 // Let's read in the perfect crystal file
672
673 crystalIn.getline(inLine,999,'\n');
674
675 // check to see if the crystal file is the same length as starting config.
676
677 token = strtok(inLine,delimit);
678
679 strcpy(inValue,token);
680
681 idealSize = atoi(inValue);
682
683 if (idealSize != vecParticles.size()) {
684
685 sprintf(painCave.errMsg,
686
687 "Restraints Error: Reference crystal file is not valid.\n"
688
689 "\tMake sure the idealCrystal.in file is the same size as the\n"
690
691 "\tstarting configuration. Using an incompatable crystal will\n"
692
693 "\tlead to energy calculation failures.\n");
694
695 painCave.severity = OOPSE_ERROR;
696
697 painCave.isFatal = 1;
698
699 simError();
700
701 }
702
703 // else, the file is okay... let's continue
704
705 crystalIn.getline(inLine,999,'\n');
706
707
708
709 for (i=0; i<vecParticles.size(); i++) {
710
711 crystalIn.getline(inLine,999,'\n');
712
713 token = strtok(inLine,delimit);
714
715 token = strtok(NULL,delimit);
716
717 strcpy(inValue,token);
718
719 cofmPosX.push_back(atof(inValue));
720
721 token = strtok(NULL,delimit);
722
723 strcpy(inValue,token);
724
725 cofmPosY.push_back(atof(inValue));
726
727 token = strtok(NULL,delimit);
728
729 strcpy(inValue,token);
730
731 cofmPosZ.push_back(atof(inValue));
732
733 token = strtok(NULL,delimit);
734
735 token = strtok(NULL,delimit);
736
737 token = strtok(NULL,delimit);
738
739 token = strtok(NULL,delimit);
740
741 strcpy(inValue,token);
742
743 quat0 = atof(inValue);
744
745 token = strtok(NULL,delimit);
746
747 strcpy(inValue,token);
748
749 quat1 = atof(inValue);
750
751 token = strtok(NULL,delimit);
752
753 strcpy(inValue,token);
754
755 quat2 = atof(inValue);
756
757 token = strtok(NULL,delimit);
758
759 strcpy(inValue,token);
760
761 quat3 = atof(inValue);
762
763
764
765 // now build the rotation matrix and find the unit vectors
766
767 RfromQ[0][0] = quat0*quat0 + quat1*quat1 - quat2*quat2 - quat3*quat3;
768
769 RfromQ[0][1] = 2*(quat1*quat2 + quat0*quat3);
770
771 RfromQ[0][2] = 2*(quat1*quat3 - quat0*quat2);
772
773 RfromQ[1][0] = 2*(quat1*quat2 - quat0*quat3);
774
775 RfromQ[1][1] = quat0*quat0 - quat1*quat1 + quat2*quat2 - quat3*quat3;
776
777 RfromQ[1][2] = 2*(quat2*quat3 + quat0*quat1);
778
779 RfromQ[2][0] = 2*(quat1*quat3 + quat0*quat2);
780
781 RfromQ[2][1] = 2*(quat2*quat3 - quat0*quat1);
782
783 RfromQ[2][2] = quat0*quat0 - quat1*quat1 - quat2*quat2 + quat3*quat3;
784
785
786
787 normalize = sqrt(RfromQ[2][0]*RfromQ[2][0] + RfromQ[2][1]*RfromQ[2][1]
788
789 + RfromQ[2][2]*RfromQ[2][2]);
790
791 uX0.push_back(RfromQ[2][0]/normalize);
792
793 uY0.push_back(RfromQ[2][1]/normalize);
794
795 uZ0.push_back(RfromQ[2][2]/normalize);
796
797
798
799 normalize = sqrt(RfromQ[1][0]*RfromQ[1][0] + RfromQ[1][1]*RfromQ[1][1]
800
801 + RfromQ[1][2]*RfromQ[1][2]);
802
803 vX0.push_back(RfromQ[1][0]/normalize);
804
805 vY0.push_back(RfromQ[1][1]/normalize);
806
807 vZ0.push_back(RfromQ[1][2]/normalize);
808
809 }
810
811 crystalIn.close();
812
813
814
815 // now we read in the zAngle.ang file
816
817 if (angleIn){
818
819 angleIn.getline(inLine,999,'\n');
820
821 angleIn.getline(inLine,999,'\n');
822
823 while (!angleIn.eof()) {
824
825 token = strtok(inLine,delimit);
826
827 strcpy(inValue,token);
828
829 tempZangs.push_back(atof(inValue));
830
831 angleIn.getline(inLine,999,'\n');
832
833 }
834
835
836
837 // test to make sure the zAngle.ang file is the proper length
838
839 if (tempZangs.size() == vecParticles.size())
840
841 for (i=0; i<vecParticles.size(); i++)
842
843 vecParticles[i]->setZangle(tempZangs[i]);
844
845 else {
846
847 sprintf(painCave.errMsg,
848
849 "Restraints Error: the supplied zAngle file is not valid.\n"
850
851 "\tMake sure the zAngle.ang file matches with the initial\n"
852
853 "\tconfiguration (i.e. they're the same length). Using the wrong\n"
854
855 "\tzAngle file will lead to errors in the energy calculations.\n");
856
857 painCave.severity = OOPSE_ERROR;
858
859 painCave.isFatal = 1;
860
861 simError();
862
863 }
864
865 }
866
867 angleIn.close();
868
869
870
871 return;
872
873 }
874
875
876
877 void Restraints::Write_zAngle_File(vector<StuntDouble*> vecParticles){
878
879
880
881 char zOutName[200];
882
883
884
885 strcpy(zOutName,"zAngle.ang");
886
887
888
889 ofstream angleOut(zOutName);
890
891 angleOut << "This file contains the omega values for the .eor file\n";
892
893 for (i=0; i<vecParticles.size(); i++) {
894
895 angleOut << vecParticles[i]->getZangle() << "\n";
896
897 }
898
899 return;
900
901 }
902
903
904
905 double Restraints::getVharm(){
906
907 return harmPotent;
908
909 }
910
911
912