ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-1.0/libmdtools/ZConstraint.cpp
Revision: 1353
Committed: Mon Jul 19 21:25:21 2004 UTC (19 years, 11 months ago) by tim
File size: 32862 byte(s)
Log Message:
remove some comment lines

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 forcePolicy->update();
480 }
481
482 #endif
483
484 /**
485 * Function Name: isZConstraintMol
486 * Parameter
487 * Molecule* mol
488 * Return value:
489 * -1, if the molecule is not z-constraint molecule,
490 * other non-negative values, its index in indexOfAllZConsMols vector
491 */
492
493 template<typename T> int ZConstraint<T>::isZConstraintMol(Molecule* mol){
494 int index;
495 int low;
496 int high;
497 int mid;
498
499 index = mol->getGlobalIndex();
500
501 low = 0;
502 high = parameters->size() - 1;
503
504 //Binary Search (we have sorted the array)
505 while (low <= high){
506 mid = (low + high) / 2;
507 if ((*parameters)[mid].zconsIndex == index)
508 return mid;
509 else if ((*parameters)[mid].zconsIndex > index)
510 high = mid - 1;
511 else
512 low = mid + 1;
513 }
514
515 return -1;
516 }
517
518 template<typename T> void ZConstraint<T>::integrate(){
519 // creat zconsWriter
520 fzOut = new ZConsWriter(zconsOutput.c_str(), parameters);
521
522 if (!fzOut){
523 sprintf(painCave.errMsg, "Memory allocation failure in class Zconstraint\n");
524 painCave.isFatal = 1;
525 simError();
526 }
527
528 //zero out the velocities of center of mass of unconstrained molecules
529 //and the velocities of center of mass of every single z-constrained molecueles
530 zeroOutVel();
531
532 curZconsTime = zconsTime + info->getTime();
533
534 T::integrate();
535 }
536
537 template<typename T> void ZConstraint<T>::calcForce(int calcPot, int calcStress){
538 double zsys;
539 double COM[3];
540 double force[3];
541 double zSysCOMVel;
542
543 T::calcForce(calcPot, calcStress);
544
545
546 if (hasZConsGap){
547 updateZPos();
548 }
549
550 if (checkZConsState()){
551 zeroOutVel();
552 forcePolicy->update();
553 }
554
555 zsys = calcZSys();
556 zSysCOMVel = calcSysCOMVel();
557 #ifdef IS_MPI
558 if (worldRank == 0){
559 #endif
560
561 #ifdef IS_MPI
562 }
563 #endif
564
565 //do zconstraint force;
566 if (haveFixedZMols()){
567 this->doZconstraintForce();
568 }
569
570 //use external force to move the molecules to the specified positions
571 if (haveMovingZMols()){
572 if (usingSMD)
573 this->doHarmonic(cantPos);
574 else
575 this->doHarmonic(zPos);
576 }
577
578 //write out forces and current positions of z-constraint molecules
579 if (info->getTime() >= curZconsTime){
580 for (int i = 0; i < (int) (zconsMols.size()); i++){
581 zconsMols[i]->getCOM(COM);
582 curZPos[i] = COM[whichDirection];
583
584 //if the z-constraint molecule is still moving, just record its force
585 if (states[i] == zcsMoving){
586 fz[i] = 0;
587 Atom** movingZAtoms;
588 movingZAtoms = zconsMols[i]->getMyAtoms();
589 for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
590 movingZAtoms[j]->getFrc(force);
591 fz[i] += force[whichDirection];
592 }
593 }
594 }
595 fzOut->writeFZ(info->getTime(), zconsMols.size(), &indexOfZConsMols[0], &fz[0],
596 &curZPos[0], &zPos[0]);
597 curZconsTime += zconsTime;
598 }
599
600 zSysCOMVel = calcSysCOMVel();
601 #ifdef IS_MPI
602 if (worldRank == 0){
603 #endif
604 #ifdef IS_MPI
605 }
606 #endif
607 }
608
609
610 template<typename T> double ZConstraint<T>::calcZSys(){
611 //calculate reference z coordinate for z-constraint molecules
612 double totalMass_local;
613 double totalMass;
614 double totalMZ_local;
615 double totalMZ;
616 double massOfCurMol;
617 double COM[3];
618
619 totalMass_local = 0;
620 totalMZ_local = 0;
621
622 for (int i = 0; i < nMols; i++){
623 massOfCurMol = molecules[i].getTotalMass();
624 molecules[i].getCOM(COM);
625
626 totalMass_local += massOfCurMol;
627 totalMZ_local += massOfCurMol * COM[whichDirection];
628 }
629
630
631 #ifdef IS_MPI
632 MPI_Allreduce(&totalMass_local, &totalMass, 1, MPI_DOUBLE, MPI_SUM,
633 MPI_COMM_WORLD);
634 MPI_Allreduce(&totalMZ_local, &totalMZ, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
635 #else
636 totalMass = totalMass_local;
637 totalMZ = totalMZ_local;
638 #endif
639
640 double zsys;
641 zsys = totalMZ / totalMass;
642
643 return zsys;
644 }
645
646 template<typename T> void ZConstraint<T>::thermalize(void){
647 T::thermalize();
648 zeroOutVel();
649 }
650
651 template<typename T> void ZConstraint<T>::zeroOutVel(){
652 Atom** fixedZAtoms;
653 double COMvel[3];
654 double vel[3];
655 double zSysCOMVel;
656
657 //zero out the velocities of center of mass of fixed z-constrained molecules
658
659 for (int i = 0; i < (int) (zconsMols.size()); i++){
660 if (states[i] == zcsFixed){
661 zconsMols[i]->getCOMvel(COMvel);
662 //cout << "before resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
663
664 fixedZAtoms = zconsMols[i]->getMyAtoms();
665
666 for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
667 fixedZAtoms[j]->getVel(vel);
668 vel[whichDirection] -= COMvel[whichDirection];
669 fixedZAtoms[j]->setVel(vel);
670 }
671
672 zconsMols[i]->getCOMvel(COMvel);
673 }
674 }
675
676 zSysCOMVel = calcSysCOMVel();
677 #ifdef IS_MPI
678 if (worldRank == 0){
679 #endif
680 #ifdef IS_MPI
681 }
682 #endif
683
684 // calculate the vz of center of mass of unconstrained molecules and moving z-constrained molecules
685 double MVzOfMovingMols_local;
686 double MVzOfMovingMols;
687 double totalMassOfMovingZMols_local;
688 double totalMassOfMovingZMols;
689
690 MVzOfMovingMols_local = 0;
691 totalMassOfMovingZMols_local = 0;
692
693 for (int i = 0; i < (int) (unconsMols.size()); i++){
694 unconsMols[i]->getCOMvel(COMvel);
695 MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
696 }
697
698 for (int i = 0; i < (int) (zconsMols.size()); i++){
699 if (states[i] == zcsMoving){
700 zconsMols[i]->getCOMvel(COMvel);
701 MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
702 totalMassOfMovingZMols_local += massOfZConsMols[i];
703 }
704 }
705
706 #ifndef IS_MPI
707 MVzOfMovingMols = MVzOfMovingMols_local;
708 totalMassOfMovingZMols = totalMassOfMovingZMols_local;
709 #else
710 MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,
711 MPI_SUM, MPI_COMM_WORLD);
712 MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1,
713 MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
714 #endif
715
716 double vzOfMovingMols;
717 vzOfMovingMols = MVzOfMovingMols /
718 (totalMassOfUncons + totalMassOfMovingZMols);
719
720 //modify the velocites of unconstrained molecules
721 Atom** unconsAtoms;
722 for (int i = 0; i < (int) (unconsMols.size()); i++){
723 unconsAtoms = unconsMols[i]->getMyAtoms();
724 for (int j = 0; j < unconsMols[i]->getNAtoms(); j++){
725 unconsAtoms[j]->getVel(vel);
726 vel[whichDirection] -= vzOfMovingMols;
727 unconsAtoms[j]->setVel(vel);
728 }
729 }
730
731 //modify the velocities of moving z-constrained molecuels
732 Atom** movingZAtoms;
733 for (int i = 0; i < (int) (zconsMols.size()); i++){
734 if (states[i] == zcsMoving){
735 movingZAtoms = zconsMols[i]->getMyAtoms();
736 for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
737 movingZAtoms[j]->getVel(vel);
738 vel[whichDirection] -= vzOfMovingMols;
739 movingZAtoms[j]->setVel(vel);
740 }
741 }
742 }
743
744
745 zSysCOMVel = calcSysCOMVel();
746 #ifdef IS_MPI
747 if (worldRank == 0){
748 #endif
749 #ifdef IS_MPI
750 }
751 #endif
752 }
753
754
755 template<typename T> void ZConstraint<T>::doZconstraintForce(){
756 Atom** zconsAtoms;
757 double totalFZ;
758 double totalFZ_local;
759 double COM[3];
760 double force[3];
761
762 //constrain the molecules which do not reach the specified positions
763
764 //Zero Out the force of z-contrained molecules
765 totalFZ_local = 0;
766
767 //calculate the total z-contrained force of fixed z-contrained molecules
768
769 for (int i = 0; i < (int) (zconsMols.size()); i++){
770 if (states[i] == zcsFixed){
771 zconsMols[i]->getCOM(COM);
772 zconsAtoms = zconsMols[i]->getMyAtoms();
773
774 fz[i] = 0;
775 for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
776 zconsAtoms[j]->getFrc(force);
777 fz[i] += force[whichDirection];
778 }
779 totalFZ_local += fz[i];
780
781 }
782 }
783
784 //calculate total z-constraint force
785 #ifdef IS_MPI
786 MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
787 #else
788 totalFZ = totalFZ_local;
789 #endif
790
791
792 // apply negative to fixed z-constrained molecues;
793 force[0] = 0;
794 force[1] = 0;
795 force[2] = 0;
796
797 for (int i = 0; i < (int) (zconsMols.size()); i++){
798 if (states[i] == zcsFixed){
799 int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms();
800 zconsAtoms = zconsMols[i]->getMyAtoms();
801
802 for (int j = 0; j < nAtomOfCurZConsMol; j++){
803 //force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol;
804 force[whichDirection] = -forcePolicy->getZFOfFixedZMols(zconsMols[i],
805 zconsAtoms[j],
806 fz[i]);
807 zconsAtoms[j]->addFrc(force);
808 }
809 }
810 }
811
812 force[0] = 0;
813 force[1] = 0;
814 force[2] = 0;
815
816 //modify the forces of unconstrained molecules
817 for (int i = 0; i < (int) (unconsMols.size()); i++){
818 Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
819
820 for (int j = 0; j < unconsMols[i]->getNAtoms(); j++){
821 //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
822 force[whichDirection] = forcePolicy->getZFOfMovingMols(unconsAtoms[j],
823 totalFZ);
824 unconsAtoms[j]->addFrc(force);
825 }
826 }
827
828 //modify the forces of moving z-constrained molecules
829 for (int i = 0; i < (int) (zconsMols.size()); i++){
830 if (states[i] == zcsMoving){
831 Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
832
833 for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
834 //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
835 force[whichDirection] = forcePolicy->getZFOfMovingMols(movingZAtoms[j],
836 totalFZ);
837 movingZAtoms[j]->addFrc(force);
838 }
839 }
840 }
841 }
842
843
844 template<typename T> void ZConstraint<T>::doHarmonic(vector<double>& resPos){
845 double force[3];
846 double harmonicU;
847 double harmonicF;
848 double COM[3];
849 double diff;
850 double totalFZ_local;
851 double totalFZ;
852
853 force[0] = 0;
854 force[1] = 0;
855 force[2] = 0;
856
857 totalFZ_local = 0;
858
859 for (int i = 0; i < (int) (zconsMols.size()); i++){
860 if (states[i] == zcsMoving){
861 zconsMols[i]->getCOM(COM);
862
863 diff = COM[whichDirection] - resPos[i];
864
865 harmonicU = 0.5 * kz[i] * diff * diff;
866 info->lrPot += harmonicU;
867
868 harmonicF = -kz[i] * diff;
869 totalFZ_local += harmonicF;
870
871 //adjust force
872
873 Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
874
875 for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
876 force[whichDirection] = forcePolicy->getHFOfFixedZMols(zconsMols[i],
877 movingZAtoms[j],
878 harmonicF);
879 movingZAtoms[j]->addFrc(force);
880 }
881 }
882 }
883
884 #ifndef IS_MPI
885 totalFZ = totalFZ_local;
886 #else
887 MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
888 #endif
889
890 force[0] = 0;
891 force[1] = 0;
892 force[2] = 0;
893
894 //modify the forces of unconstrained molecules
895 for (int i = 0; i < (int) (unconsMols.size()); i++){
896 Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
897
898 for (int j = 0; j < unconsMols[i]->getNAtoms(); j++){
899 //force[whichDirection] = - totalFZ /totNumOfUnconsAtoms;
900 force[whichDirection] = -forcePolicy->getHFOfUnconsMols(unconsAtoms[j],
901 totalFZ);
902 unconsAtoms[j]->addFrc(force);
903 }
904 }
905
906 }
907
908 template<typename T> bool ZConstraint<T>::checkZConsState(){
909 double COM[3];
910 double diff;
911
912 int changed_local;
913 int changed;
914
915 changed_local = 0;
916
917 for (int i = 0; i < (int) (zconsMols.size()); i++){
918 zconsMols[i]->getCOM(COM);
919 diff = fabs(COM[whichDirection] - zPos[i]);
920 if (diff <= zconsTol && states[i] == zcsMoving){
921 states[i] = zcsFixed;
922 changed_local = 1;
923
924 if(usingSMD)
925 prevCantPos = cantPos;
926
927 if (hasZConsGap)
928 endFixTime[i] = info->getTime() + zconsFixTime;
929 }
930 else if (diff > zconsTol && states[i] == zcsFixed){
931 states[i] = zcsMoving;
932 changed_local = 1;
933
934 if(usingSMD)
935 cantPos = prevCantPos;
936
937 if (hasZConsGap)
938 endFixTime[i] = INFINITE_TIME;
939 }
940 }
941
942 #ifndef IS_MPI
943 changed = changed_local;
944 #else
945 MPI_Allreduce(&changed_local, &changed, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
946 #endif
947
948 return (changed > 0);
949 }
950
951 template<typename T> bool ZConstraint<T>::haveFixedZMols(){
952 int havingFixed_local;
953 int havingFixed;
954
955 havingFixed_local = 0;
956
957 for (int i = 0; i < (int) (zconsMols.size()); i++)
958 if (states[i] == zcsFixed){
959 havingFixed_local = 1;
960 break;
961 }
962
963 #ifndef IS_MPI
964 havingFixed = havingFixed_local;
965 #else
966 MPI_Allreduce(&havingFixed_local, &havingFixed, 1, MPI_INT, MPI_SUM,
967 MPI_COMM_WORLD);
968 #endif
969
970 return (havingFixed > 0);
971 }
972
973
974 template<typename T> bool ZConstraint<T>::haveMovingZMols(){
975 int havingMoving_local;
976 int havingMoving;
977
978 havingMoving_local = 0;
979
980 for (int i = 0; i < (int) (zconsMols.size()); i++)
981 if (states[i] == zcsMoving){
982 havingMoving_local = 1;
983 break;
984 }
985
986 #ifndef IS_MPI
987 havingMoving = havingMoving_local;
988 #else
989 MPI_Allreduce(&havingMoving_local, &havingMoving, 1, MPI_INT, MPI_SUM,
990 MPI_COMM_WORLD);
991 #endif
992
993 return (havingMoving > 0);
994 }
995
996
997 template<typename T> double ZConstraint<T>::calcMovingMolsCOMVel(){
998 double MVzOfMovingMols_local;
999 double MVzOfMovingMols;
1000 double totalMassOfMovingZMols_local;
1001 double totalMassOfMovingZMols;
1002 double COMvel[3];
1003
1004 MVzOfMovingMols_local = 0;
1005 totalMassOfMovingZMols_local = 0;
1006
1007 for (int i = 0; i < unconsMols.size(); i++){
1008 unconsMols[i]->getCOMvel(COMvel);
1009 MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
1010 }
1011
1012 for (int i = 0; i < zconsMols.size(); i++){
1013 if (states[i] == zcsMoving){
1014 zconsMols[i]->getCOMvel(COMvel);
1015 MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
1016 totalMassOfMovingZMols_local += massOfZConsMols[i];
1017 }
1018 }
1019
1020 #ifndef IS_MPI
1021 MVzOfMovingMols = MVzOfMovingMols_local;
1022 totalMassOfMovingZMols = totalMassOfMovingZMols_local;
1023 #else
1024 MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,
1025 MPI_SUM, MPI_COMM_WORLD);
1026 MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1,
1027 MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
1028 #endif
1029
1030 double vzOfMovingMols;
1031 vzOfMovingMols = MVzOfMovingMols /
1032 (totalMassOfUncons + totalMassOfMovingZMols);
1033
1034 return vzOfMovingMols;
1035 }
1036
1037 template<typename T> double ZConstraint<T>::calcSysCOMVel(){
1038 double COMvel[3];
1039 double tempMVz_local;
1040 double tempMVz;
1041 double massOfZCons_local;
1042 double massOfZCons;
1043
1044
1045 tempMVz_local = 0;
1046
1047 for (int i = 0 ; i < nMols; i++){
1048 molecules[i].getCOMvel(COMvel);
1049 tempMVz_local += molecules[i].getTotalMass() * COMvel[whichDirection];
1050 }
1051
1052 massOfZCons_local = 0;
1053
1054 for (int i = 0; i < (int) (massOfZConsMols.size()); i++){
1055 massOfZCons_local += massOfZConsMols[i];
1056 }
1057 #ifndef IS_MPI
1058 massOfZCons = massOfZCons_local;
1059 tempMVz = tempMVz_local;
1060 #else
1061 MPI_Allreduce(&massOfZCons_local, &massOfZCons, 1, MPI_DOUBLE, MPI_SUM,
1062 MPI_COMM_WORLD);
1063 MPI_Allreduce(&tempMVz_local, &tempMVz, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
1064 #endif
1065
1066 return tempMVz / (totalMassOfUncons + massOfZCons);
1067 }
1068
1069 template<typename T> double ZConstraint<T>::calcTotalForce(){
1070 double force[3];
1071 double totalForce_local;
1072 double totalForce;
1073
1074 totalForce_local = 0;
1075
1076 for (int i = 0; i < nAtoms; i++){
1077 atoms[i]->getFrc(force);
1078 totalForce_local += force[whichDirection];
1079 }
1080
1081 #ifndef IS_MPI
1082 totalForce = totalForce_local;
1083 #else
1084 MPI_Allreduce(&totalForce_local, &totalForce, 1, MPI_DOUBLE, MPI_SUM,
1085 MPI_COMM_WORLD);
1086 #endif
1087
1088 return totalForce;
1089 }
1090
1091 template<typename T> void ZConstraint<T>::PolicyByNumber::update(){
1092 //calculate the number of atoms of moving z-constrained molecules
1093 int nMovingZAtoms_local;
1094 int nMovingZAtoms;
1095
1096 nMovingZAtoms_local = 0;
1097 for (int i = 0; i < (int) ((zconsIntegrator->zconsMols).size()); i++)
1098 if ((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving)){
1099 nMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getNAtoms();
1100 }
1101
1102 #ifdef IS_MPI
1103 MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1, MPI_INT, MPI_SUM,
1104 MPI_COMM_WORLD);
1105 #else
1106 nMovingZAtoms = nMovingZAtoms_local;
1107 #endif
1108 totNumOfMovingAtoms = nMovingZAtoms + zconsIntegrator->totNumOfUnconsAtoms;
1109 }
1110
1111 template<typename T> double ZConstraint<T>::PolicyByNumber::getZFOfFixedZMols(Molecule* mol,
1112 Atom* atom,
1113 double totalForce){
1114 return totalForce / mol->getNAtoms();
1115 }
1116
1117 template<typename T> double ZConstraint<T>::PolicyByNumber::getZFOfMovingMols(Atom* atom,
1118 double totalForce){
1119 return totalForce / totNumOfMovingAtoms;
1120 }
1121
1122 template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfFixedZMols(Molecule* mol,
1123 Atom* atom,
1124 double totalForce){
1125 return totalForce / mol->getNAtoms();
1126 }
1127
1128 template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfUnconsMols(Atom* atom,
1129 double totalForce){
1130 return totalForce / zconsIntegrator->totNumOfUnconsAtoms;
1131 }
1132
1133
1134 template<typename T> void ZConstraint<T>::PolicyByMass::update(){
1135 //calculate the number of atoms of moving z-constrained molecules
1136 double massOfMovingZAtoms_local;
1137 double massOfMovingZAtoms;
1138
1139 massOfMovingZAtoms_local = 0;
1140 for (int i = 0; i < (int) ((zconsIntegrator->zconsMols).size()); i++)
1141 if ((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving)){
1142 massOfMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getTotalMass();
1143 }
1144
1145 #ifdef IS_MPI
1146 MPI_Allreduce(&massOfMovingZAtoms_local, &massOfMovingZAtoms, 1, MPI_DOUBLE,
1147 MPI_SUM, MPI_COMM_WORLD);
1148 #else
1149 massOfMovingZAtoms = massOfMovingZAtoms_local;
1150 #endif
1151 totMassOfMovingAtoms = massOfMovingZAtoms +
1152 zconsIntegrator->totalMassOfUncons;
1153 }
1154
1155 template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfFixedZMols(Molecule* mol,
1156 Atom* atom,
1157 double totalForce){
1158 return totalForce * atom->getMass() / mol->getTotalMass();
1159 }
1160
1161 template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfMovingMols(Atom* atom,
1162 double totalForce){
1163 return totalForce * atom->getMass() / totMassOfMovingAtoms;
1164 }
1165
1166 template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfFixedZMols(Molecule* mol,
1167 Atom* atom,
1168 double totalForce){
1169 return totalForce * atom->getMass() / mol->getTotalMass();
1170 }
1171
1172 template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfUnconsMols(Atom* atom,
1173 double totalForce){
1174 return totalForce * atom->getMass() / zconsIntegrator->totalMassOfUncons;
1175 }
1176
1177 template<typename T> void ZConstraint<T>::updateZPos(){
1178 double curTime;
1179 double COM[3];
1180
1181 curTime = info->getTime();
1182
1183 for (size_t i = 0; i < zconsMols.size(); i++){
1184
1185 if (states[i] == zcsFixed && curTime >= endFixTime[i]){
1186 zPos[i] += zconsGap;
1187
1188 if (usingSMD){
1189 zconsMols[i]->getCOM(COM);
1190 cantPos[i] = COM[whichDirection];
1191 }
1192
1193 }
1194
1195 }
1196
1197 }
1198
1199 template<typename T> void ZConstraint<T>::updateCantPos(){
1200 double curTime;
1201 double dt;
1202
1203 curTime = info->getTime();
1204 dt = info->dt;
1205
1206 for (size_t i = 0; i < zconsMols.size(); i++){
1207 if (states[i] == zcsMoving){
1208 cantPos[i] += cantVel[i] * dt;
1209 }
1210 }
1211
1212 }