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

File Contents

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