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

# User Rev Content
1 tim 658 #include "Integrator.hpp"
2     #include "simError.h"
3 tim 676 #include <cmath>
4 tim 658 template<typename T> ZConstraint<T>::ZConstraint(SimInfo* theInfo, ForceFields* the_ff)
5 tim 699 : T(theInfo, the_ff), fz(NULL), curZPos(NULL),
6 tim 701 indexOfZConsMols(NULL), forcePolicy(NULL), curZconsTime(0)
7 tim 658 {
8    
9     //get properties from SimInfo
10     GenericData* data;
11 tim 682 ZConsParaData* zConsParaData;
12 tim 658 DoubleData* sampleTime;
13 tim 682 DoubleData* tolerance;
14 tim 699 StringData* policy;
15 tim 658 StringData* filename;
16 tim 682 double COM[3];
17 tim 658
18 tim 682 //by default, the direction of constraint is z
19     // 0 --> x
20     // 1 --> y
21     // 2 --> z
22     whichDirection = 2;
23 tim 658
24 tim 682 //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 tim 676
30 tim 699 //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 tim 726 "PolicyByMass is used\n");
36 tim 699 painCave.isFatal = 0;
37     simError();
38    
39 tim 726 forcePolicy = (ForceSubstractionPolicy*) new PolicyByMass(this);
40 tim 699 }
41     else{
42     policy = dynamic_cast<StringData*>(data);
43 tim 701
44     if(!policy){
45 tim 699 sprintf( painCave.errMsg,
46     "ZConstraint Error: Convertion from GenericData to StringData failure, "
47 tim 726 "PolicyByMass is used\n");
48 tim 699 painCave.isFatal = 0;
49     simError();
50    
51 tim 726 forcePolicy = (ForceSubstractionPolicy*) new PolicyByMass(this);
52 tim 701 }
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 tim 699 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 tim 701 }
65     }
66 tim 699 }
67    
68 tim 701
69 tim 676 //retrieve sample time of z-contraint
70 tim 682 data = info->getProperty(ZCONSTIME_ID);
71 tim 658
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 tim 676 //retrieve output filename of z force
99 tim 682 data = info->getProperty(ZCONSFILENAME_ID);
100 tim 658 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 tim 701 filename = dynamic_cast<StringData*>(data);
113 tim 658
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 tim 682
128     //retrieve tolerance for z-constraint molecuels
129     data = info->getProperty(ZCONSTOL_ID);
130 tim 658
131 tim 682 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 tim 701
156 tim 682 //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 tim 701 }
197 tim 682
198 tim 693 maxIndex = (*parameters)[parameters->size() - 1].zconsIndex;
199 tim 682
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 tim 701 if(!(*parameters)[i].havingZPos){
218 tim 682 #ifndef IS_MPI
219 tim 701 for(int j = 0; j < nMols; j++){
220     if (molecules[j].getGlobalIndex() == (*parameters)[i].zconsIndex){
221     molecules[j].getCOM(COM);
222     break;
223 tim 682 }
224 tim 701 }
225 tim 682 #else
226     //query which processor current zconstraint molecule belongs to
227 tim 701 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 tim 682
236 tim 701 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 tim 682
246 tim 701 MPI_Bcast(&COM[whichDirection], 1, MPI_DOUBLE_PRECISION, whichNode, MPI_COMM_WORLD);
247 tim 682 #endif
248    
249 tim 701 (*parameters)[i].zPos = COM[whichDirection];
250 tim 682
251 tim 701 sprintf( painCave.errMsg,
252 tim 682 "ZConstraint warningr: Does not specify zpos for z-constraint molecule "
253     "initial z coornidate will be used \n");
254 tim 701 painCave.isFatal = 0;
255     simError();
256    
257     }
258     }
259    
260 tim 682 }//end if (!zConsParaData)
261     }//end if (!data)
262    
263     //
264 tim 658 #ifdef IS_MPI
265     update();
266     #else
267     int searchResult;
268 tim 676
269 tim 658 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 tim 682
278     zPos.push_back((*parameters)[searchResult].zPos);
279 mmeineke 723 // cout << "index: "<< (*parameters)[searchResult].zconsIndex
280     // <<"\tzPos = " << (*parameters)[searchResult].zPos << endl;
281 tim 701 kz.push_back((*parameters)[searchResult]. kRatio * zForceConst);
282 tim 676
283 tim 658 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 tim 699 curZPos = new double[zconsMols.size()];
296 tim 658 indexOfZConsMols = new int [zconsMols.size()];
297    
298 tim 699 if(!fz || !curZPos || !indexOfZConsMols){
299 tim 658 sprintf( painCave.errMsg,
300     "Memory allocation failure in class Zconstraint\n");
301     painCave.isFatal = 1;
302     simError();
303     }
304    
305 tim 693 //determine the states of z-constraint molecules
306     for(int i = 0; i < zconsMols.size(); i++){
307 tim 658 indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex();
308 tim 693
309 tim 701 zconsMols[i]->getCOM(COM);
310 tim 693 if (fabs(zPos[i] - COM[whichDirection]) < zconsTol)
311 tim 701 states.push_back(zcsFixed);
312     else
313     states.push_back(zcsMoving);
314 tim 693 }
315 tim 658
316     #endif
317 tim 676
318 tim 693 //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 tim 701 MPI_Allreduce(&totalMassOfUncons_local, &totalMassOfUncons, 1,
329     MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
330 tim 693 #endif
331    
332    
333 tim 676 //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 tim 701 MPI_Allreduce(&nUnconsAtoms_local, &totNumOfUnconsAtoms, 1,
343     MPI_INT,MPI_SUM, MPI_COMM_WORLD);
344 tim 693 #endif
345 tim 676
346 tim 693 // creat zconsWriter
347 tim 699 fzOut = new ZConsWriter(zconsOutput.c_str(), parameters);
348 tim 658
349     if(!fzOut){
350     sprintf( painCave.errMsg,
351     "Memory allocation failure in class Zconstraint\n");
352     painCave.isFatal = 1;
353     simError();
354     }
355 tim 699
356     forcePolicy->update();
357 tim 658 }
358    
359     template<typename T> ZConstraint<T>::~ZConstraint()
360     {
361     if(fz)
362     delete[] fz;
363 tim 699
364     if(curZPos)
365     delete[] curZPos;
366 tim 658
367     if(indexOfZConsMols)
368     delete[] indexOfZConsMols;
369    
370     if(fzOut)
371     delete fzOut;
372 tim 701
373 tim 699 if(forcePolicy)
374     delete forcePolicy;
375 tim 658 }
376    
377 tim 701
378     /**
379     *
380     */
381    
382 tim 658 #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 tim 682 zPos.clear();
391     kz.clear();
392 tim 658
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 tim 682 zPos.push_back((*parameters)[index].zPos);
406 tim 701 kz.push_back((*parameters)[index].kRatio * zForceConst);
407    
408 tim 658 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 tim 693
421     //determine the states of z-constraint molecules
422     for(int i = 0; i < zconsMols.size(); i++){
423 tim 701 zconsMols[i]->getCOM(COM);
424 tim 693 if (fabs(zPos[i] - COM[whichDirection]) < zconsTol)
425 tim 701 states.push_back(zcsFixed);
426     else
427     states.push_back(zcsMoving);
428 tim 693 }
429    
430 tim 658
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 tim 701
436 tim 699 if(curZPos)
437     delete[] curZPos;
438 tim 658
439     if(indexOfZConsMols)
440     delete[] indexOfZConsMols;
441    
442     if (zconsMols.size() > 0){
443     fz = new double[zconsMols.size()];
444 tim 701 curZPos = new double[zconsMols.size()];
445 tim 658 indexOfZConsMols = new int[zconsMols.size()];
446    
447 tim 699 if(!fz || !curZPos || !indexOfZConsMols){
448 tim 658 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 tim 701 curZPos = NULL;
462 tim 658 indexOfZConsMols = NULL;
463     }
464 tim 701
465 tim 699 //
466     forcePolicy->update();
467 tim 658
468     }
469    
470     #endif
471    
472 tim 701 /**
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 tim 658 */
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 tim 682 high = parameters->size() - 1;
492 tim 658
493     //Binary Search (we have sorted the array)
494     while(low <= high){
495     mid = (low + high) /2;
496 tim 682 if ((*parameters)[mid].zconsIndex == index)
497 tim 658 return mid;
498 tim 682 else if ((*parameters)[mid].zconsIndex > index )
499 tim 658 high = mid -1;
500     else
501     low = mid + 1;
502     }
503    
504     return -1;
505     }
506    
507 tim 676 template<typename T> void ZConstraint<T>::integrate(){
508 tim 658
509 tim 676 //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 mmeineke 711
513     curZconsTime = zconsTime + info->getTime();
514 tim 676
515     T::integrate();
516    
517 tim 658 }
518 tim 676
519 tim 658
520 tim 676 /**
521     *
522     *
523     *
524     *
525 tim 696 */
526 tim 676 template<typename T> void ZConstraint<T>::calcForce(int calcPot, int calcStress){
527 tim 693 double zsys;
528 tim 699 double COM[3];
529     double force[3];
530 tim 702 double zSysCOMVel;
531 tim 676
532     T::calcForce(calcPot, calcStress);
533    
534 tim 699 if (checkZConsState()){
535 mmeineke 711
536     #ifdef IS_MPI
537     if(worldRank == 0){
538     #endif
539 mmeineke 723 // std::cerr << "\n"
540     // << "*******************************************\n"
541     // << " about to call zeroOutVel()\n"
542     // << "*******************************************\n"
543     // << "\n";
544 mmeineke 711 #ifdef IS_MPI
545     }
546     #endif
547 tim 696 zeroOutVel();
548 mmeineke 711
549     #ifdef IS_MPI
550     if(worldRank == 0){
551     #endif
552 mmeineke 723 // std::cerr << "\n"
553     // << "*******************************************\n"
554     // << " finished zeroOutVel()\n"
555     // << "*******************************************\n"
556     // << "\n";
557 mmeineke 711 #ifdef IS_MPI
558     }
559     #endif
560    
561     forcePolicy->update();
562 tim 699 }
563 mmeineke 711
564 tim 693 zsys = calcZSys();
565 tim 702 zSysCOMVel = calcSysCOMVel();
566     #ifdef IS_MPI
567     if(worldRank == 0){
568     #endif
569 mmeineke 723 // 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 tim 676
574 tim 702 #ifdef IS_MPI
575     }
576     #endif
577 tim 696
578 tim 676 //do zconstraint force;
579     if (haveFixedZMols())
580     this->doZconstraintForce();
581 tim 733
582 tim 676 //use harmonical poteintial to move the molecules to the specified positions
583     if (haveMovingZMols())
584 tim 693 this->doHarmonic();
585 tim 696
586 tim 699 //write out forces and current positions of z-constraint molecules
587 tim 701 if(info->getTime() >= curZconsTime){
588     for(int i = 0; i < zconsMols.size(); i++){
589 tim 699 zconsMols[i]->getCOM(COM);
590 tim 701 curZPos[i] = COM[whichDirection];
591 tim 699
592 tim 701 //if the z-constraint molecule is still moving, just record its force
593     if(states[i] == zcsMoving){
594 tim 699 fz[i] = 0;
595 tim 701 Atom** movingZAtoms;
596     movingZAtoms = zconsMols[i]->getMyAtoms();
597     for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
598 tim 699 movingZAtoms[j]->getFrc(force);
599     fz[i] += force[whichDirection];
600 tim 701 }
601     }
602     }
603 tim 699 fzOut->writeFZ(info->getTime(), zconsMols.size(), indexOfZConsMols, fz, curZPos);
604 tim 701 curZconsTime += zconsTime;
605 tim 699 }
606 tim 702
607     zSysCOMVel = calcSysCOMVel();
608     #ifdef IS_MPI
609     if(worldRank == 0){
610     #endif
611 mmeineke 723 // cout << "after calcForce, the COMVel of system is " << zSysCOMVel <<endl;
612 tim 702 #ifdef IS_MPI
613     }
614     #endif
615 tim 676 }
616 tim 701
617    
618     /**
619     *
620     */
621 tim 676
622     template<typename T> double ZConstraint<T>::calcZSys()
623 tim 658 {
624 tim 676 //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 tim 701
632 tim 676 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 tim 696
642 tim 676 }
643 tim 696
644 tim 676
645     #ifdef IS_MPI
646 tim 701 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 tim 696 #else
651 tim 676 totalMass = totalMass_local;
652     totalMZ = totalMZ_local;
653 tim 696 #endif
654 mmeineke 671
655 tim 658 double zsys;
656 tim 676 zsys = totalMZ / totalMass;
657 tim 658
658 tim 676 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 tim 701 double zSysCOMVel;
680 tim 693
681 tim 676 //zero out the velocities of center of mass of fixed z-constrained molecules
682    
683 tim 658 for(int i = 0; i < zconsMols.size(); i++){
684 tim 676
685 tim 701 if (states[i] == zcsFixed){
686 tim 676
687 tim 701 zconsMols[i]->getCOMvel(COMvel);
688     //cout << "before resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
689 tim 693
690 tim 676 fixedZAtoms = zconsMols[i]->getMyAtoms();
691 tim 701
692 tim 676 for(int j =0; j < zconsMols[i]->getNAtoms(); j++){
693     fixedZAtoms[j]->getVel(vel);
694 tim 701 vel[whichDirection] -= COMvel[whichDirection];
695     fixedZAtoms[j]->setVel(vel);
696 tim 676 }
697 tim 693
698 tim 701 zconsMols[i]->getCOMvel(COMvel);
699     //cout << "after resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
700 tim 676 }
701 tim 701
702 tim 658 }
703 tim 693
704 tim 701 //cout << "before resetting the COMVel of moving molecules is " << calcMovingMolsCOMVel() <<endl;
705 tim 699
706 tim 701 zSysCOMVel = calcSysCOMVel();
707 tim 699 #ifdef IS_MPI
708 tim 701 if(worldRank == 0){
709 tim 699 #endif
710 mmeineke 723 // cout << "before resetting the COMVel of sytem is " << zSysCOMVel << endl;
711 tim 699 #ifdef IS_MPI
712     }
713     #endif
714 tim 701
715 tim 676 // 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 tim 658
724 tim 676 for(int i =0; i < unconsMols.size(); i++){
725     unconsMols[i]->getCOMvel(COMvel);
726     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
727     }
728    
729 tim 693 for(int i = 0; i < zconsMols.size(); i++){
730 tim 676 if (states[i] == zcsMoving){
731     zconsMols[i]->getCOMvel(COMvel);
732     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
733 tim 701 totalMassOfMovingZMols_local += massOfZConsMols[i];
734 tim 676 }
735 tim 701
736 tim 676 }
737    
738     #ifndef IS_MPI
739     MVzOfMovingMols = MVzOfMovingMols_local;
740     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
741 tim 658 #else
742 tim 676 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 tim 658 #endif
745    
746 tim 676 double vzOfMovingMols;
747     vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
748    
749     //modify the velocites of unconstrained molecules
750     Atom** unconsAtoms;
751 tim 658 for(int i = 0; i < unconsMols.size(); i++){
752 tim 676
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 tim 693 for(int i = 0; i < zconsMols.size(); i++){
765 tim 676
766     if (states[i] ==zcsMoving){
767    
768     movingZAtoms = zconsMols[i]->getMyAtoms();
769 tim 701 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
770 tim 676 movingZAtoms[j]->getVel(vel);
771     vel[whichDirection] -= vzOfMovingMols;
772 tim 701 movingZAtoms[j]->setVel(vel);
773     }
774    
775 tim 693 }
776 tim 676
777 tim 693 }
778 tim 676
779 tim 701
780     zSysCOMVel = calcSysCOMVel();
781 tim 699 #ifdef IS_MPI
782 tim 701 if(worldRank == 0){
783 tim 699 #endif
784 mmeineke 723 // cout << "after resetting the COMVel of moving molecules is " << zSysCOMVel << endl;
785 tim 699 #ifdef IS_MPI
786     }
787     #endif
788 tim 693
789 tim 676 }
790    
791 tim 701 /**
792     *
793     */
794    
795 tim 676 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 tim 701 //constrain the molecules which do not reach the specified positions
805 tim 676
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 tim 699
811 tim 676 for(int i = 0; i < zconsMols.size(); i++){
812 tim 701
813 tim 676 if (states[i] == zcsFixed){
814 tim 701
815 tim 676 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 tim 701 }
823 tim 676 totalFZ_local += fz[i];
824    
825 tim 726 //cout << "Fixed Molecule\tindex: " << indexOfZConsMols[i]
826     // <<"\tcurrent zpos: " << COM[whichDirection]
827     // << "\tcurrent fz: " <<fz[i] << endl;
828 tim 676
829 tim 726
830 tim 676 }
831 tim 701
832 tim 676 }
833 tim 699
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 tim 701
842 tim 696 // apply negative to fixed z-constrained molecues;
843     force[0]= 0;
844     force[1]= 0;
845     force[2]= 0;
846 tim 676
847 tim 696 for(int i = 0; i < zconsMols.size(); i++){
848    
849     if (states[i] == zcsFixed){
850 tim 701
851 tim 696 int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms();
852     zconsAtoms = zconsMols[i]->getMyAtoms();
853    
854     for(int j =0; j < nAtomOfCurZConsMol; j++) {
855 tim 726 //force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol;
856     force[whichDirection] = - forcePolicy->getZFOfFixedZMols(zconsMols[i], zconsAtoms[j], fz[i]);
857 tim 696 zconsAtoms[j]->addFrc(force);
858     }
859 tim 701
860 tim 696 }
861 tim 701
862 tim 696 }
863    
864 mmeineke 711 // cout << "after zero out z-constraint force on fixed z-constraint molecuels "
865     // << "total force is " << calcTotalForce() << endl;
866 tim 699
867 tim 676 force[0]= 0;
868     force[1]= 0;
869     force[2]= 0;
870    
871 tim 693 //modify the forces of unconstrained molecules
872 tim 676 for(int i = 0; i < unconsMols.size(); i++){
873    
874     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
875    
876 tim 699 for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){
877 tim 726 //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
878     force[whichDirection] = forcePolicy->getZFOfMovingMols(unconsAtoms[j],totalFZ);
879 tim 676 unconsAtoms[j]->addFrc(force);
880 tim 699 }
881 tim 676
882     }
883    
884 tim 693 //modify the forces of moving z-constrained molecules
885 tim 676 for(int i = 0; i < zconsMols.size(); i++) {
886 tim 696 if (states[i] == zcsMoving){
887 tim 701
888 tim 696 Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
889 tim 676
890 tim 699 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
891 tim 726 //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
892     force[whichDirection] = forcePolicy->getZFOfMovingMols(movingZAtoms[j],totalFZ);
893 tim 696 movingZAtoms[j]->addFrc(force);
894 tim 699 }
895 tim 696 }
896 tim 676 }
897    
898 tim 699 //cout << "after substracting z-constraint force from moving molecuels "
899 tim 701 // << "total force is " << calcTotalForce() << endl;
900 tim 699
901 tim 676 }
902    
903 tim 701 /**
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 mmeineke 723 // cout << "Moving Molecule\tindex: " << indexOfZConsMols[i]
928     // << "\tcurrent zpos: " << COM[whichDirection] << endl;
929 tim 726
930     diff = COM[whichDirection] -zPos[i];
931 tim 701
932     harmonicU = 0.5 * kz[i] * diff * diff;
933 tim 726 info->lrPot += harmonicU;
934 tim 701
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 tim 726 //force[whichDirection] = harmonicF / zconsMols[i]->getNAtoms();
944     force[whichDirection] = forcePolicy->getHFOfFixedZMols(zconsMols[i], movingZAtoms[j], harmonicF);
945 tim 701 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 tim 726 //force[whichDirection] = - totalFZ /totNumOfUnconsAtoms;
968     force[whichDirection] = - forcePolicy->getHFOfUnconsMols(unconsAtoms[j], totalFZ);
969 tim 701 unconsAtoms[j]->addFrc(force);
970     }
971     }
972    
973     }
974    
975     /**
976     *
977     */
978    
979 tim 676 template<typename T> bool ZConstraint<T>::checkZConsState(){
980     double COM[3];
981     double diff;
982 tim 658
983 tim 699 int changed_local;
984     int changed;
985 tim 701
986 tim 699 changed_local = 0;
987 tim 676
988     for(int i =0; i < zconsMols.size(); i++){
989    
990 tim 658 zconsMols[i]->getCOM(COM);
991 tim 682 diff = fabs(COM[whichDirection] - zPos[i]);
992     if ( diff <= zconsTol && states[i] == zcsMoving){
993 tim 676 states[i] = zcsFixed;
994 tim 701 changed_local = 1;
995 tim 676 }
996 tim 682 else if ( diff > zconsTol && states[i] == zcsFixed){
997 tim 676 states[i] = zcsMoving;
998 tim 701 changed_local = 1;
999 tim 676 }
1000    
1001 tim 658 }
1002    
1003 tim 699 #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 tim 726
1009 mmeineke 711 return (changed > 0);
1010 tim 726
1011 tim 658 }
1012 tim 676
1013     template<typename T> bool ZConstraint<T>::haveFixedZMols(){
1014 tim 699
1015     int havingFixed_local;
1016     int havingFixed;
1017    
1018     havingFixed_local = 0;
1019    
1020 tim 676 for(int i = 0; i < zconsMols.size(); i++)
1021 tim 699 if (states[i] == zcsFixed){
1022     havingFixed_local = 1;
1023 tim 701 break;
1024 tim 699 }
1025 tim 676
1026 tim 699 #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 tim 726 return (havingFixed > 0);
1033 tim 676 }
1034    
1035    
1036     /**
1037     *
1038     */
1039     template<typename T> bool ZConstraint<T>::haveMovingZMols(){
1040 tim 699
1041     int havingMoving_local;
1042     int havingMoving;
1043    
1044     havingMoving_local = 0;
1045    
1046 tim 676 for(int i = 0; i < zconsMols.size(); i++)
1047 tim 699 if (states[i] == zcsMoving){
1048     havingMoving_local = 1;
1049 tim 701 break;
1050 tim 699 }
1051 tim 676
1052 tim 699 #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 tim 726 return (havingMoving > 0);
1059 tim 676
1060 tim 682 }
1061    
1062     /**
1063 tim 701 *
1064     */
1065 tim 682
1066 tim 696 template<typename T> double ZConstraint<T>::calcMovingMolsCOMVel()
1067 tim 693 {
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 tim 701 totalMassOfMovingZMols_local += massOfZConsMols[i];
1088 tim 693 }
1089 tim 701
1090 tim 693 }
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 tim 701 /**
1107     *
1108     */
1109 tim 693
1110 tim 696 template<typename T> double ZConstraint<T>::calcSysCOMVel()
1111 tim 693 {
1112     double COMvel[3];
1113 tim 699 double tempMVz_local;
1114     double tempMVz;
1115     double massOfZCons_local;
1116     double massOfZCons;
1117    
1118    
1119     tempMVz_local = 0;
1120    
1121 tim 693 for(int i =0 ; i < nMols; i++){
1122 tim 696 molecules[i].getCOMvel(COMvel);
1123 tim 701 tempMVz_local += molecules[i].getTotalMass()*COMvel[whichDirection];
1124 tim 693 }
1125 tim 696
1126     massOfZCons_local = 0;
1127 tim 701
1128 tim 696 for(int i = 0; i < massOfZConsMols.size(); i++){
1129     massOfZCons_local += massOfZConsMols[i];
1130     }
1131     #ifndef IS_MPI
1132     massOfZCons = massOfZCons_local;
1133 tim 699 tempMVz = tempMVz_local;
1134 tim 696 #else
1135     MPI_Allreduce(&massOfZCons_local, &massOfZCons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1136 tim 699 MPI_Allreduce(&tempMVz_local, &tempMVz, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1137 tim 696 #endif
1138    
1139     return tempMVz /(totalMassOfUncons + massOfZCons);
1140 tim 693 }
1141 tim 696
1142 tim 701 /**
1143     *
1144     */
1145    
1146 tim 696 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 tim 699
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 tim 701
1178 tim 699 nMovingZAtoms_local = 0;
1179     for(int i = 0; i < (zconsIntegrator->zconsMols).size(); i++)
1180     if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1181 tim 701 nMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getNAtoms();
1182 tim 699
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 mmeineke 711
1190     #ifdef IS_MPI
1191     if(worldRank == 0){
1192     #endif
1193 mmeineke 723 // std::cerr << "\n"
1194     // << "*******************************************\n"
1195     // << " fiished Policy by numbr()\n"
1196     // << "*******************************************\n"
1197     // << "\n";
1198 mmeineke 711 #ifdef IS_MPI
1199     }
1200     #endif
1201 tim 699 }
1202    
1203 tim 701 template<typename T>double ZConstraint<T>::PolicyByNumber::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1204 tim 699 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 tim 701
1228 tim 699 massOfMovingZAtoms_local = 0;
1229     for(int i = 0; i < (zconsIntegrator->zconsMols).size(); i++)
1230     if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1231 tim 701 massOfMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getTotalMass();
1232 tim 699
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