ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 733
Committed: Wed Aug 27 19:23:29 2003 UTC (20 years, 10 months ago) by tim
File size: 31670 byte(s)
Log Message:
fix bug of MPI_Allreduce in ZConstraint, the MPITYPE is set to MPI_DOUBLE,
however, the corret type is MPI_INT. Therefore, when we turn on the
optimization flag, it causes a seg fault

File Contents

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