ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 1203
Committed: Thu May 27 18:59:17 2004 UTC (20 years, 1 month ago) by gezelter
File size: 34877 byte(s)
Log Message:
Cutoff group changes under MPI

File Contents

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