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