ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 699
Committed: Fri Aug 15 19:24:13 2003 UTC (20 years, 10 months ago) by tim
File size: 31203 byte(s)
Log Message:
Tested MPI version of Z-Constraint Method

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