ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 711
Committed: Fri Aug 22 20:04:39 2003 UTC (20 years, 10 months ago) by mmeineke
File size: 32138 byte(s)
Log Message:
small bug fix on frequency of output dumps.

File Contents

# Content
1 #include "Integrator.hpp"
2 #include "simError.h"
3 #include <cmath>
4 template<typename T> ZConstraint<T>::ZConstraint(SimInfo* theInfo, ForceFields* the_ff)
5 : T(theInfo, the_ff), fz(NULL), curZPos(NULL),
6 indexOfZConsMols(NULL), forcePolicy(NULL), curZconsTime(0)
7 {
8
9 //get properties from SimInfo
10 GenericData* data;
11 ZConsParaData* zConsParaData;
12 DoubleData* sampleTime;
13 DoubleData* tolerance;
14 StringData* policy;
15 StringData* filename;
16 double COM[3];
17
18 //by default, the direction of constraint is z
19 // 0 --> x
20 // 1 --> y
21 // 2 --> z
22 whichDirection = 2;
23
24 //estimate the force constant of harmonical potential
25 double Kb = 1.986E-3 ; //in kcal/K
26
27 double halfOfLargestBox = max(info->boxL[0], max(info->boxL[1], info->boxL[2])) /2;
28 zForceConst = Kb * info->target_temp /(halfOfLargestBox * halfOfLargestBox);
29
30 //creat force substraction policy
31 data = info->getProperty(ZCONSFORCEPOLICY_ID);
32 if(!data){
33 sprintf( painCave.errMsg,
34 "ZConstraint Warning: User does not set force substraction policy, "
35 "average force substraction policy is used\n");
36 painCave.isFatal = 0;
37 simError();
38
39 forcePolicy = (ForceSubstractionPolicy*) new PolicyByNumber(this);
40 }
41 else{
42 policy = dynamic_cast<StringData*>(data);
43
44 if(!policy){
45 sprintf( painCave.errMsg,
46 "ZConstraint Error: Convertion from GenericData to StringData failure, "
47 "average force substraction policy is used\n");
48 painCave.isFatal = 0;
49 simError();
50
51 forcePolicy = (ForceSubstractionPolicy*) new PolicyByNumber(this);
52 }
53 else{
54 if(policy->getData() == "BYNUMBER")
55 forcePolicy = (ForceSubstractionPolicy*) new PolicyByNumber(this);
56 else if(policy->getData() == "BYMASS")
57 forcePolicy = (ForceSubstractionPolicy*) new PolicyByMass(this);
58 else{
59 sprintf( painCave.errMsg,
60 "ZConstraint Warning: unknown force substraction policy, "
61 "average force substraction policy is used\n");
62 painCave.isFatal = 0;
63 simError();
64 }
65 }
66 }
67
68
69 //retrieve sample time of z-contraint
70 data = info->getProperty(ZCONSTIME_ID);
71
72 if(!data) {
73
74 sprintf( painCave.errMsg,
75 "ZConstraint error: If you use an ZConstraint\n"
76 " , you must set sample time.\n");
77 painCave.isFatal = 1;
78 simError();
79 }
80 else{
81
82 sampleTime = dynamic_cast<DoubleData*>(data);
83
84 if(!sampleTime){
85
86 sprintf( painCave.errMsg,
87 "ZConstraint error: Can not get property from SimInfo\n");
88 painCave.isFatal = 1;
89 simError();
90
91 }
92 else{
93 this->zconsTime = sampleTime->getData();
94 }
95
96 }
97
98 //retrieve output filename of z force
99 data = info->getProperty(ZCONSFILENAME_ID);
100 if(!data) {
101
102
103 sprintf( painCave.errMsg,
104 "ZConstraint error: If you use an ZConstraint\n"
105 " , you must set output filename of z-force.\n");
106 painCave.isFatal = 1;
107 simError();
108
109 }
110 else{
111
112 filename = dynamic_cast<StringData*>(data);
113
114 if(!filename){
115
116 sprintf( painCave.errMsg,
117 "ZConstraint error: Can not get property from SimInfo\n");
118 painCave.isFatal = 1;
119 simError();
120
121 }
122 else{
123 this->zconsOutput = filename->getData();
124 }
125
126 }
127
128 //retrieve tolerance for z-constraint molecuels
129 data = info->getProperty(ZCONSTOL_ID);
130
131 if(!data) {
132
133 sprintf( painCave.errMsg,
134 "ZConstraint error: can not get tolerance \n");
135 painCave.isFatal = 1;
136 simError();
137 }
138 else{
139
140 tolerance = dynamic_cast<DoubleData*>(data);
141
142 if(!tolerance){
143
144 sprintf( painCave.errMsg,
145 "ZConstraint error: Can not get property from SimInfo\n");
146 painCave.isFatal = 1;
147 simError();
148
149 }
150 else{
151 this->zconsTol = tolerance->getData();
152 }
153
154 }
155
156 //retrieve index of z-constraint molecules
157 data = info->getProperty(ZCONSPARADATA_ID);
158 if(!data) {
159
160 sprintf( painCave.errMsg,
161 "ZConstraint error: If you use an ZConstraint\n"
162 " , you must set index of z-constraint molecules.\n");
163 painCave.isFatal = 1;
164 simError();
165 }
166 else{
167
168 zConsParaData = dynamic_cast<ZConsParaData*>(data);
169
170 if(!zConsParaData){
171
172 sprintf( painCave.errMsg,
173 "ZConstraint error: Can not get parameters of zconstraint method from SimInfo\n");
174 painCave.isFatal = 1;
175 simError();
176
177 }
178 else{
179
180 parameters = zConsParaData->getData();
181
182 //check the range of zconsIndex
183 //and the minimum value of index is the first one (we already sorted the data)
184 //the maximum value of index is the last one
185
186 int maxIndex;
187 int minIndex;
188 int totalNumMol;
189
190 minIndex = (*parameters)[0].zconsIndex;
191 if(minIndex < 0){
192 sprintf( painCave.errMsg,
193 "ZConstraint error: index is out of range\n");
194 painCave.isFatal = 1;
195 simError();
196 }
197
198 maxIndex = (*parameters)[parameters->size() - 1].zconsIndex;
199
200 #ifndef IS_MPI
201 totalNumMol = nMols;
202 #else
203 totalNumMol = mpiSim->getTotNmol();
204 #endif
205
206 if(maxIndex > totalNumMol - 1){
207 sprintf( painCave.errMsg,
208 "ZConstraint error: index is out of range\n");
209 painCave.isFatal = 1;
210 simError();
211 }
212
213 //if user does not specify the zpos for the zconstraint molecule
214 //its initial z coordinate will be used as default
215 for(int i = 0; i < parameters->size(); i++){
216
217 if(!(*parameters)[i].havingZPos){
218 #ifndef IS_MPI
219 for(int j = 0; j < nMols; j++){
220 if (molecules[j].getGlobalIndex() == (*parameters)[i].zconsIndex){
221 molecules[j].getCOM(COM);
222 break;
223 }
224 }
225 #else
226 //query which processor current zconstraint molecule belongs to
227 int *MolToProcMap;
228 int whichNode;
229 double initZPos;
230 MolToProcMap = mpiSim->getMolToProcMap();
231 whichNode = MolToProcMap[(*parameters)[i].zconsIndex];
232
233 //broadcast the zpos of current z-contraint molecule
234 //the node which contain this
235
236 if (worldRank == whichNode ){
237
238 for(int j = 0; j < nMols; j++)
239 if (molecules[j].getGlobalIndex() == (*parameters)[i].zconsIndex){
240 molecules[j].getCOM(COM);
241 break;
242 }
243
244 }
245
246 MPI_Bcast(&COM[whichDirection], 1, MPI_DOUBLE_PRECISION, whichNode, MPI_COMM_WORLD);
247 #endif
248
249 (*parameters)[i].zPos = COM[whichDirection];
250
251 sprintf( painCave.errMsg,
252 "ZConstraint warningr: Does not specify zpos for z-constraint molecule "
253 "initial z coornidate will be used \n");
254 painCave.isFatal = 0;
255 simError();
256
257 }
258 }
259
260 }//end if (!zConsParaData)
261 }//end if (!data)
262
263 //
264 #ifdef IS_MPI
265 update();
266 #else
267 int searchResult;
268
269 for(int i = 0; i < nMols; i++){
270
271 searchResult = isZConstraintMol(&molecules[i]);
272
273 if(searchResult > -1){
274
275 zconsMols.push_back(&molecules[i]);
276 massOfZConsMols.push_back(molecules[i].getTotalMass());
277
278 zPos.push_back((*parameters)[searchResult].zPos);
279 cout << "index: "<< (*parameters)[searchResult].zconsIndex
280 <<"\tzPos = " << (*parameters)[searchResult].zPos << endl;
281 kz.push_back((*parameters)[searchResult]. kRatio * zForceConst);
282
283 molecules[i].getCOM(COM);
284 }
285 else
286 {
287
288 unconsMols.push_back(&molecules[i]);
289 massOfUnconsMols.push_back(molecules[i].getTotalMass());
290
291 }
292 }
293
294 fz = new double[zconsMols.size()];
295 curZPos = new double[zconsMols.size()];
296 indexOfZConsMols = new int [zconsMols.size()];
297
298 if(!fz || !curZPos || !indexOfZConsMols){
299 sprintf( painCave.errMsg,
300 "Memory allocation failure in class Zconstraint\n");
301 painCave.isFatal = 1;
302 simError();
303 }
304
305 //determine the states of z-constraint molecules
306 for(int i = 0; i < zconsMols.size(); i++){
307 indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex();
308
309 zconsMols[i]->getCOM(COM);
310 if (fabs(zPos[i] - COM[whichDirection]) < zconsTol)
311 states.push_back(zcsFixed);
312 else
313 states.push_back(zcsMoving);
314 }
315
316 #endif
317
318 //get total masss of unconstraint molecules
319 double totalMassOfUncons_local;
320 totalMassOfUncons_local = 0;
321
322 for(int i = 0; i < unconsMols.size(); i++)
323 totalMassOfUncons_local += unconsMols[i]->getTotalMass();
324
325 #ifndef IS_MPI
326 totalMassOfUncons = totalMassOfUncons_local;
327 #else
328 MPI_Allreduce(&totalMassOfUncons_local, &totalMassOfUncons, 1,
329 MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
330 #endif
331
332
333 //get total number of unconstrained atoms
334 int nUnconsAtoms_local;
335 nUnconsAtoms_local = 0;
336 for(int i = 0; i < unconsMols.size(); i++)
337 nUnconsAtoms_local += unconsMols[i]->getNAtoms();
338
339 #ifndef IS_MPI
340 totNumOfUnconsAtoms = nUnconsAtoms_local;
341 #else
342 MPI_Allreduce(&nUnconsAtoms_local, &totNumOfUnconsAtoms, 1,
343 MPI_INT,MPI_SUM, MPI_COMM_WORLD);
344 #endif
345
346 // creat zconsWriter
347 fzOut = new ZConsWriter(zconsOutput.c_str(), parameters);
348
349 if(!fzOut){
350 sprintf( painCave.errMsg,
351 "Memory allocation failure in class Zconstraint\n");
352 painCave.isFatal = 1;
353 simError();
354 }
355
356 forcePolicy->update();
357 }
358
359 template<typename T> ZConstraint<T>::~ZConstraint()
360 {
361 if(fz)
362 delete[] fz;
363
364 if(curZPos)
365 delete[] curZPos;
366
367 if(indexOfZConsMols)
368 delete[] indexOfZConsMols;
369
370 if(fzOut)
371 delete fzOut;
372
373 if(forcePolicy)
374 delete forcePolicy;
375 }
376
377
378 /**
379 *
380 */
381
382 #ifdef IS_MPI
383 template<typename T> void ZConstraint<T>::update()
384 {
385 double COM[3];
386 int index;
387
388 zconsMols.clear();
389 massOfZConsMols.clear();
390 zPos.clear();
391 kz.clear();
392
393 unconsMols.clear();
394 massOfUnconsMols.clear();
395
396
397 //creat zconsMol and unconsMol lists
398 for(int i = 0; i < nMols; i++){
399
400 index = isZConstraintMol(&molecules[i]);
401
402 if(index > -1){
403
404 zconsMols.push_back(&molecules[i]);
405 zPos.push_back((*parameters)[index].zPos);
406 kz.push_back((*parameters)[index].kRatio * zForceConst);
407
408 massOfZConsMols.push_back(molecules[i].getTotalMass());
409
410 molecules[i].getCOM(COM);
411 }
412 else
413 {
414
415 unconsMols.push_back(&molecules[i]);
416 massOfUnconsMols.push_back(molecules[i].getTotalMass());
417
418 }
419 }
420
421 //determine the states of z-constraint molecules
422 for(int i = 0; i < zconsMols.size(); i++){
423 zconsMols[i]->getCOM(COM);
424 if (fabs(zPos[i] - COM[whichDirection]) < zconsTol)
425 states.push_back(zcsFixed);
426 else
427 states.push_back(zcsMoving);
428 }
429
430
431 //The reason to declare fz and indexOfZconsMols as pointer to array is
432 // that we want to make the MPI communication simple
433 if(fz)
434 delete[] fz;
435
436 if(curZPos)
437 delete[] curZPos;
438
439 if(indexOfZConsMols)
440 delete[] indexOfZConsMols;
441
442 if (zconsMols.size() > 0){
443 fz = new double[zconsMols.size()];
444 curZPos = new double[zconsMols.size()];
445 indexOfZConsMols = new int[zconsMols.size()];
446
447 if(!fz || !curZPos || !indexOfZConsMols){
448 sprintf( painCave.errMsg,
449 "Memory allocation failure in class Zconstraint\n");
450 painCave.isFatal = 1;
451 simError();
452 }
453
454 for(int i = 0; i < zconsMols.size(); i++){
455 indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex();
456 }
457
458 }
459 else{
460 fz = NULL;
461 curZPos = NULL;
462 indexOfZConsMols = NULL;
463 }
464
465 //
466 forcePolicy->update();
467
468 }
469
470 #endif
471
472 /**
473 * Function Name: isZConstraintMol
474 * Parameter
475 * Molecule* mol
476 * Return value:
477 * -1, if the molecule is not z-constraint molecule,
478 * other non-negative values, its index in indexOfAllZConsMols vector
479 */
480
481 template<typename T> int ZConstraint<T>::isZConstraintMol(Molecule* mol)
482 {
483 int index;
484 int low;
485 int high;
486 int mid;
487
488 index = mol->getGlobalIndex();
489
490 low = 0;
491 high = parameters->size() - 1;
492
493 //Binary Search (we have sorted the array)
494 while(low <= high){
495 mid = (low + high) /2;
496 if ((*parameters)[mid].zconsIndex == index)
497 return mid;
498 else if ((*parameters)[mid].zconsIndex > index )
499 high = mid -1;
500 else
501 low = mid + 1;
502 }
503
504 return -1;
505 }
506
507 template<typename T> void ZConstraint<T>::integrate(){
508
509 //zero out the velocities of center of mass of unconstrained molecules
510 //and the velocities of center of mass of every single z-constrained molecueles
511 zeroOutVel();
512
513 curZconsTime = zconsTime + info->getTime();
514
515 T::integrate();
516
517 }
518
519
520 /**
521 *
522 *
523 *
524 *
525 */
526 template<typename T> void ZConstraint<T>::calcForce(int calcPot, int calcStress){
527 double zsys;
528 double COM[3];
529 double force[3];
530 double zSysCOMVel;
531
532 T::calcForce(calcPot, calcStress);
533
534 if (checkZConsState()){
535
536 #ifdef IS_MPI
537 if(worldRank == 0){
538 #endif
539 std::cerr << "\n"
540 << "*******************************************\n"
541 << " about to call zeroOutVel()\n"
542 << "*******************************************\n"
543 << "\n";
544 #ifdef IS_MPI
545 }
546 #endif
547 zeroOutVel();
548
549 #ifdef IS_MPI
550 if(worldRank == 0){
551 #endif
552 std::cerr << "\n"
553 << "*******************************************\n"
554 << " finished zeroOutVel()\n"
555 << "*******************************************\n"
556 << "\n";
557 #ifdef IS_MPI
558 }
559 #endif
560
561 forcePolicy->update();
562 }
563
564 zsys = calcZSys();
565 zSysCOMVel = calcSysCOMVel();
566 #ifdef IS_MPI
567 if(worldRank == 0){
568 #endif
569 cout << "---------------------------------------------------------------------" <<endl;
570 cout << "current time: " << info->getTime() << endl;
571 cout << "center of mass at z: " << zsys << endl;
572 cout << "before calcForce, the COMVel of system is " << zSysCOMVel <<endl;
573
574 #ifdef IS_MPI
575 }
576 #endif
577
578 //do zconstraint force;
579 if (haveFixedZMols())
580 this->doZconstraintForce();
581
582 //use harmonical poteintial to move the molecules to the specified positions
583 if (haveMovingZMols())
584 this->doHarmonic();
585
586 //write out forces and current positions of z-constraint molecules
587 if(info->getTime() >= curZconsTime){
588 for(int i = 0; i < zconsMols.size(); i++){
589 zconsMols[i]->getCOM(COM);
590 curZPos[i] = COM[whichDirection];
591
592 //if the z-constraint molecule is still moving, just record its force
593 if(states[i] == zcsMoving){
594 fz[i] = 0;
595 Atom** movingZAtoms;
596 movingZAtoms = zconsMols[i]->getMyAtoms();
597 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
598 movingZAtoms[j]->getFrc(force);
599 fz[i] += force[whichDirection];
600 }
601 }
602 }
603 fzOut->writeFZ(info->getTime(), zconsMols.size(), indexOfZConsMols, fz, curZPos);
604 curZconsTime += zconsTime;
605 }
606
607 zSysCOMVel = calcSysCOMVel();
608 #ifdef IS_MPI
609 if(worldRank == 0){
610 #endif
611 cout << "after calcForce, the COMVel of system is " << zSysCOMVel <<endl;
612 #ifdef IS_MPI
613 }
614 #endif
615
616 }
617
618
619 /**
620 *
621 */
622
623 template<typename T> double ZConstraint<T>::calcZSys()
624 {
625 //calculate reference z coordinate for z-constraint molecules
626 double totalMass_local;
627 double totalMass;
628 double totalMZ_local;
629 double totalMZ;
630 double massOfCurMol;
631 double COM[3];
632
633 totalMass_local = 0;
634 totalMZ_local = 0;
635
636 for(int i = 0; i < nMols; i++){
637 massOfCurMol = molecules[i].getTotalMass();
638 molecules[i].getCOM(COM);
639
640 totalMass_local += massOfCurMol;
641 totalMZ_local += massOfCurMol * COM[whichDirection];
642
643 }
644
645
646 #ifdef IS_MPI
647 MPI_Allreduce(&totalMass_local, &totalMass, 1,
648 MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
649 MPI_Allreduce(&totalMZ_local, &totalMZ, 1,
650 MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
651 #else
652 totalMass = totalMass_local;
653 totalMZ = totalMZ_local;
654 #endif
655
656 double zsys;
657 zsys = totalMZ / totalMass;
658
659 return zsys;
660 }
661
662 /**
663 *
664 */
665 template<typename T> void ZConstraint<T>::thermalize( void ){
666
667 T::thermalize();
668 zeroOutVel();
669 }
670
671 /**
672 *
673 */
674
675 template<typename T> void ZConstraint<T>::zeroOutVel(){
676
677 Atom** fixedZAtoms;
678 double COMvel[3];
679 double vel[3];
680 double zSysCOMVel;
681
682 //zero out the velocities of center of mass of fixed z-constrained molecules
683
684 for(int i = 0; i < zconsMols.size(); i++){
685
686 if (states[i] == zcsFixed){
687
688 zconsMols[i]->getCOMvel(COMvel);
689 //cout << "before resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
690
691 fixedZAtoms = zconsMols[i]->getMyAtoms();
692
693 for(int j =0; j < zconsMols[i]->getNAtoms(); j++){
694 fixedZAtoms[j]->getVel(vel);
695 vel[whichDirection] -= COMvel[whichDirection];
696 fixedZAtoms[j]->setVel(vel);
697 }
698
699 zconsMols[i]->getCOMvel(COMvel);
700 //cout << "after resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
701 }
702
703 }
704
705 //cout << "before resetting the COMVel of moving molecules is " << calcMovingMolsCOMVel() <<endl;
706
707 zSysCOMVel = calcSysCOMVel();
708 #ifdef IS_MPI
709 if(worldRank == 0){
710 #endif
711 cout << "before resetting the COMVel of sytem is " << zSysCOMVel << endl;
712 #ifdef IS_MPI
713 }
714 #endif
715
716 // calculate the vz of center of mass of unconstrained molecules and moving z-constrained molecules
717 double MVzOfMovingMols_local;
718 double MVzOfMovingMols;
719 double totalMassOfMovingZMols_local;
720 double totalMassOfMovingZMols;
721
722 MVzOfMovingMols_local = 0;
723 totalMassOfMovingZMols_local = 0;
724
725 for(int i =0; i < unconsMols.size(); i++){
726 unconsMols[i]->getCOMvel(COMvel);
727 MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
728 }
729
730 for(int i = 0; i < zconsMols.size(); i++){
731 if (states[i] == zcsMoving){
732 zconsMols[i]->getCOMvel(COMvel);
733 MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
734 totalMassOfMovingZMols_local += massOfZConsMols[i];
735 }
736
737 }
738
739 #ifndef IS_MPI
740 MVzOfMovingMols = MVzOfMovingMols_local;
741 totalMassOfMovingZMols = totalMassOfMovingZMols_local;
742 #else
743 MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
744 MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
745 #endif
746
747 double vzOfMovingMols;
748 vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
749
750 //modify the velocites of unconstrained molecules
751 Atom** unconsAtoms;
752 for(int i = 0; i < unconsMols.size(); i++){
753
754 unconsAtoms = unconsMols[i]->getMyAtoms();
755 for(int j = 0; j < unconsMols[i]->getNAtoms();j++){
756 unconsAtoms[j]->getVel(vel);
757 vel[whichDirection] -= vzOfMovingMols;
758 unconsAtoms[j]->setVel(vel);
759 }
760
761 }
762
763 //modify the velocities of moving z-constrained molecuels
764 Atom** movingZAtoms;
765 for(int i = 0; i < zconsMols.size(); i++){
766
767 if (states[i] ==zcsMoving){
768
769 movingZAtoms = zconsMols[i]->getMyAtoms();
770 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
771 movingZAtoms[j]->getVel(vel);
772 vel[whichDirection] -= vzOfMovingMols;
773 movingZAtoms[j]->setVel(vel);
774 }
775
776 }
777
778 }
779
780
781 zSysCOMVel = calcSysCOMVel();
782 #ifdef IS_MPI
783 if(worldRank == 0){
784 #endif
785 cout << "after resetting the COMVel of moving molecules is " << zSysCOMVel << endl;
786 #ifdef IS_MPI
787 }
788 #endif
789
790 }
791
792 /**
793 *
794 */
795
796 template<typename T> void ZConstraint<T>::doZconstraintForce(){
797
798 Atom** zconsAtoms;
799 double totalFZ;
800 double totalFZ_local;
801 double COMvel[3];
802 double COM[3];
803 double force[3];
804
805
806
807 //constrain the molecules which do not reach the specified positions
808
809 //Zero Out the force of z-contrained molecules
810 totalFZ_local = 0;
811
812 //calculate the total z-contrained force of fixed z-contrained molecules
813
814 for(int i = 0; i < zconsMols.size(); i++){
815
816 if (states[i] == zcsFixed){
817
818 zconsMols[i]->getCOM(COM);
819 zconsAtoms = zconsMols[i]->getMyAtoms();
820
821 fz[i] = 0;
822 for(int j =0; j < zconsMols[i]->getNAtoms(); j++) {
823 zconsAtoms[j]->getFrc(force);
824 fz[i] += force[whichDirection];
825 }
826 totalFZ_local += fz[i];
827
828 // cout << "Fixed Molecule\tindex: " << indexOfZConsMols[i]
829 // <<"\tcurrent zpos: " << COM[whichDirection]
830 // << "\tcurrent fz: " <<fz[i] << endl;
831
832 }
833
834 }
835
836 //calculate total z-constraint force
837 #ifdef IS_MPI
838 MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
839 #else
840 totalFZ = totalFZ_local;
841 #endif
842
843
844 // apply negative to fixed z-constrained molecues;
845 force[0]= 0;
846 force[1]= 0;
847 force[2]= 0;
848
849 for(int i = 0; i < zconsMols.size(); i++){
850
851 if (states[i] == zcsFixed){
852
853 int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms();
854 zconsAtoms = zconsMols[i]->getMyAtoms();
855
856 for(int j =0; j < nAtomOfCurZConsMol; j++) {
857 force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol;
858 //force[whichDirection] = - forcePolicy->getZFOfFixedZMols(zconsMols[i], zconsAtoms[j], fz[i]);
859 zconsAtoms[j]->addFrc(force);
860 }
861
862 }
863
864 }
865
866 // cout << "after zero out z-constraint force on fixed z-constraint molecuels "
867 // << "total force is " << calcTotalForce() << endl;
868
869 //calculate the number of atoms of moving z-constrained molecules
870 int nMovingZAtoms_local;
871 int nMovingZAtoms;
872
873 nMovingZAtoms_local = 0;
874 for(int i = 0; i < zconsMols.size(); i++)
875 if(states[i] == zcsMoving)
876 nMovingZAtoms_local += zconsMols[i]->getNAtoms();
877
878 #ifdef IS_MPI
879 MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1,
880 MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
881 #else
882 nMovingZAtoms = nMovingZAtoms_local;
883 #endif
884
885 force[0]= 0;
886 force[1]= 0;
887 force[2]= 0;
888
889 //modify the forces of unconstrained molecules
890 for(int i = 0; i < unconsMols.size(); i++){
891
892 Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
893
894 for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){
895 force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
896 //force[whichDirection] = forcePolicy->getZFOfMovingMols(unconsAtoms[j],totalFZ);
897 unconsAtoms[j]->addFrc(force);
898 }
899
900 }
901
902 //modify the forces of moving z-constrained molecules
903 for(int i = 0; i < zconsMols.size(); i++) {
904 if (states[i] == zcsMoving){
905
906 Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
907
908 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
909 force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
910 //force[whichDirection] = forcePolicy->getZFOfMovingMols(movingZAtoms[j],totalFZ);
911 movingZAtoms[j]->addFrc(force);
912 }
913 }
914 }
915
916 //cout << "after substracting z-constraint force from moving molecuels "
917 // << "total force is " << calcTotalForce() << endl;
918
919 }
920
921 /**
922 *
923 *
924 */
925
926 template<typename T> void ZConstraint<T>::doHarmonic(){
927 double force[3];
928 double harmonicU;
929 double harmonicF;
930 double COM[3];
931 double diff;
932 double totalFZ_local;
933 double totalFZ;
934
935 force[0] = 0;
936 force[1] = 0;
937 force[2] = 0;
938
939 totalFZ_local = 0;
940
941 for(int i = 0; i < zconsMols.size(); i++) {
942
943 if (states[i] == zcsMoving){
944 zconsMols[i]->getCOM(COM);
945 cout << "Moving Molecule\tindex: " << indexOfZConsMols[i]
946 << "\tcurrent zpos: " << COM[whichDirection] << endl;
947
948 diff = COM[whichDirection] -zPos[i];
949
950 harmonicU = 0.5 * kz[i] * diff * diff;
951 info->lrPot += harmonicU;
952
953 harmonicF = - kz[i] * diff;
954 totalFZ_local += harmonicF;
955
956 //adjust force
957
958 Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
959
960 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
961 force[whichDirection] = harmonicF / zconsMols[i]->getNAtoms();
962 //force[whichDirection] = forcePolicy->getHFOfFixedZMols(zconsMols[i], movingZAtoms[j], harmonicF);
963 movingZAtoms[j]->addFrc(force);
964 }
965 }
966
967 }
968
969 #ifndef IS_MPI
970 totalFZ = totalFZ_local;
971 #else
972 MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
973 #endif
974
975 force[0]= 0;
976 force[1]= 0;
977 force[2]= 0;
978
979 //modify the forces of unconstrained molecules
980 for(int i = 0; i < unconsMols.size(); i++){
981
982 Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
983
984 for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){
985 force[whichDirection] = - totalFZ /totNumOfUnconsAtoms;
986 //force[whichDirection] = - forcePolicy->getHFOfUnconsMols(unconsAtoms[j], totalFZ);
987 unconsAtoms[j]->addFrc(force);
988 }
989 }
990
991 }
992
993 /**
994 *
995 */
996
997 template<typename T> bool ZConstraint<T>::checkZConsState(){
998 double COM[3];
999 double diff;
1000
1001 int changed_local;
1002 int changed;
1003
1004 changed_local = 0;
1005
1006 for(int i =0; i < zconsMols.size(); i++){
1007
1008 zconsMols[i]->getCOM(COM);
1009 diff = fabs(COM[whichDirection] - zPos[i]);
1010 if ( diff <= zconsTol && states[i] == zcsMoving){
1011 states[i] = zcsFixed;
1012 changed_local = 1;
1013 }
1014 else if ( diff > zconsTol && states[i] == zcsFixed){
1015 states[i] = zcsMoving;
1016 changed_local = 1;
1017 }
1018
1019 }
1020
1021 #ifndef IS_MPI
1022 changed =changed_local;
1023 #else
1024 MPI_Allreduce(&changed_local, &changed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1025 #endif
1026
1027 return (changed > 0);
1028 }
1029
1030 template<typename T> bool ZConstraint<T>::haveFixedZMols(){
1031
1032 int havingFixed_local;
1033 int havingFixed;
1034
1035 havingFixed_local = 0;
1036
1037 for(int i = 0; i < zconsMols.size(); i++)
1038 if (states[i] == zcsFixed){
1039 havingFixed_local = 1;
1040 break;
1041 }
1042
1043 #ifndef IS_MPI
1044 havingFixed = havingFixed_local;
1045 #else
1046 MPI_Allreduce(&havingFixed_local, &havingFixed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1047 #endif
1048
1049 return havingFixed > 0 ? true : false;
1050 }
1051
1052
1053 /**
1054 *
1055 */
1056 template<typename T> bool ZConstraint<T>::haveMovingZMols(){
1057
1058 int havingMoving_local;
1059 int havingMoving;
1060
1061 havingMoving_local = 0;
1062
1063 for(int i = 0; i < zconsMols.size(); i++)
1064 if (states[i] == zcsMoving){
1065 havingMoving_local = 1;
1066 break;
1067 }
1068
1069 #ifndef IS_MPI
1070 havingMoving = havingMoving_local;
1071 #else
1072 MPI_Allreduce(&havingMoving_local, &havingMoving, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1073 #endif
1074
1075 return havingMoving > 0 ? true : false;
1076
1077 }
1078
1079 /**
1080 *
1081 */
1082
1083 template<typename T> double ZConstraint<T>::calcMovingMolsCOMVel()
1084 {
1085 double MVzOfMovingMols_local;
1086 double MVzOfMovingMols;
1087 double totalMassOfMovingZMols_local;
1088 double totalMassOfMovingZMols;
1089 double COMvel[3];
1090
1091 MVzOfMovingMols_local = 0;
1092 totalMassOfMovingZMols_local = 0;
1093
1094 for(int i =0; i < unconsMols.size(); i++){
1095 unconsMols[i]->getCOMvel(COMvel);
1096 MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
1097 }
1098
1099 for(int i = 0; i < zconsMols.size(); i++){
1100
1101 if (states[i] == zcsMoving){
1102 zconsMols[i]->getCOMvel(COMvel);
1103 MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
1104 totalMassOfMovingZMols_local += massOfZConsMols[i];
1105 }
1106
1107 }
1108
1109 #ifndef IS_MPI
1110 MVzOfMovingMols = MVzOfMovingMols_local;
1111 totalMassOfMovingZMols = totalMassOfMovingZMols_local;
1112 #else
1113 MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1114 MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1115 #endif
1116
1117 double vzOfMovingMols;
1118 vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
1119
1120 return vzOfMovingMols;
1121 }
1122
1123 /**
1124 *
1125 */
1126
1127 template<typename T> double ZConstraint<T>::calcSysCOMVel()
1128 {
1129 double COMvel[3];
1130 double tempMVz_local;
1131 double tempMVz;
1132 double massOfZCons_local;
1133 double massOfZCons;
1134
1135
1136 tempMVz_local = 0;
1137
1138 for(int i =0 ; i < nMols; i++){
1139 molecules[i].getCOMvel(COMvel);
1140 tempMVz_local += molecules[i].getTotalMass()*COMvel[whichDirection];
1141 }
1142
1143 massOfZCons_local = 0;
1144
1145 for(int i = 0; i < massOfZConsMols.size(); i++){
1146 massOfZCons_local += massOfZConsMols[i];
1147 }
1148 #ifndef IS_MPI
1149 massOfZCons = massOfZCons_local;
1150 tempMVz = tempMVz_local;
1151 #else
1152 MPI_Allreduce(&massOfZCons_local, &massOfZCons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1153 MPI_Allreduce(&tempMVz_local, &tempMVz, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1154 #endif
1155
1156 return tempMVz /(totalMassOfUncons + massOfZCons);
1157 }
1158
1159 /**
1160 *
1161 */
1162
1163 template<typename T> double ZConstraint<T>::calcTotalForce(){
1164
1165 double force[3];
1166 double totalForce_local;
1167 double totalForce;
1168
1169 totalForce_local = 0;
1170
1171 for(int i = 0; i < nAtoms; i++){
1172 atoms[i]->getFrc(force);
1173 totalForce_local += force[whichDirection];
1174 }
1175
1176 #ifndef IS_MPI
1177 totalForce = totalForce_local;
1178 #else
1179 MPI_Allreduce(&totalForce_local, &totalForce, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1180 #endif
1181
1182 return totalForce;
1183
1184 }
1185
1186 /**
1187 *
1188 */
1189
1190 template<typename T> void ZConstraint<T>::PolicyByNumber::update(){
1191 //calculate the number of atoms of moving z-constrained molecules
1192 int nMovingZAtoms_local;
1193 int nMovingZAtoms;
1194
1195 nMovingZAtoms_local = 0;
1196 for(int i = 0; i < (zconsIntegrator->zconsMols).size(); i++)
1197 if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1198 nMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getNAtoms();
1199
1200 #ifdef IS_MPI
1201 MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
1202 #else
1203 nMovingZAtoms = nMovingZAtoms_local;
1204 #endif
1205 totNumOfMovingAtoms = nMovingZAtoms + zconsIntegrator->totNumOfUnconsAtoms;
1206
1207 #ifdef IS_MPI
1208 if(worldRank == 0){
1209 #endif
1210 std::cerr << "\n"
1211 << "*******************************************\n"
1212 << " fiished Policy by numbr()\n"
1213 << "*******************************************\n"
1214 << "\n";
1215 #ifdef IS_MPI
1216 }
1217 #endif
1218 }
1219
1220 template<typename T>double ZConstraint<T>::PolicyByNumber::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1221 return totalForce / mol->getNAtoms();
1222 }
1223
1224 template<typename T> double ZConstraint<T>::PolicyByNumber::getZFOfMovingMols(Atom* atom, double totalForce){
1225 return totalForce / totNumOfMovingAtoms;
1226 }
1227
1228 template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1229 return totalForce / mol->getNAtoms();
1230 }
1231
1232 template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfUnconsMols(Atom* atom, double totalForce){
1233 return totalForce / zconsIntegrator->totNumOfUnconsAtoms;
1234 }
1235
1236 /**
1237 *
1238 */
1239
1240 template<typename T> void ZConstraint<T>::PolicyByMass::update(){
1241 //calculate the number of atoms of moving z-constrained molecules
1242 double massOfMovingZAtoms_local;
1243 double massOfMovingZAtoms;
1244
1245 massOfMovingZAtoms_local = 0;
1246 for(int i = 0; i < (zconsIntegrator->zconsMols).size(); i++)
1247 if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1248 massOfMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getTotalMass();
1249
1250 #ifdef IS_MPI
1251 MPI_Allreduce(&massOfMovingZAtoms_local, &massOfMovingZAtoms, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1252 #else
1253 massOfMovingZAtoms = massOfMovingZAtoms_local;
1254 #endif
1255 totMassOfMovingAtoms = massOfMovingZAtoms_local + zconsIntegrator->totalMassOfUncons;
1256 }
1257
1258 template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1259 return totalForce * atom->getMass() / mol->getTotalMass();
1260 }
1261
1262 template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfMovingMols( Atom* atom, double totalForce){
1263 return totalForce * atom->getMass() / totMassOfMovingAtoms;
1264 }
1265
1266 template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1267 return totalForce * atom->getMass() / mol->getTotalMass();
1268 }
1269
1270 template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfUnconsMols(Atom* atom, double totalForce){
1271 return totalForce * atom->getMass() / zconsIntegrator->totalMassOfUncons;
1272 }
1273