ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 1093
Committed: Wed Mar 17 14:22:59 2004 UTC (20 years, 3 months ago) by tim
File size: 35962 byte(s)
Log Message:
incorporate SMD into ZConstraint,it does not sound a good choice, next commit will seperate SMD and ZConstraint

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