ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-1.0/libmdtools/ZConstraint.cpp
Revision: 1353
Committed: Mon Jul 19 21:25:21 2004 UTC (19 years, 11 months ago) by tim
File size: 32862 byte(s)
Log Message:
remove some comment lines

File Contents

# User Rev Content
1 gezelter 1334 #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     usingSMD(false),
12     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     IntData* smdFlag;
23     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     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     }
164    
165    
166    
167     data = info->getProperty(ZCONSFIXTIME_ID);
168    
169     if (data){
170     fixtime = dynamic_cast<DoubleData*>(data);
171     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     }
181     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    
188    
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     }
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->getNMolGlobal();
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     kz.push_back((*parameters)[searchResult]. kRatio * zForceConst);
321    
322     if(usingSMD)
323     cantVel.push_back((*parameters)[searchResult].cantVel);
324    
325     }
326     else{
327     unconsMols.push_back(&molecules[i]);
328     massOfUnconsMols.push_back(molecules[i].getTotalMass());
329     }
330     }
331    
332     fz.resize(zconsMols.size());
333     curZPos.resize(zconsMols.size());
334     indexOfZConsMols.resize(zconsMols.size());
335    
336     //determine the states of z-constraint molecules
337     for (size_t i = 0; i < zconsMols.size(); i++){
338     indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex();
339    
340     zconsMols[i]->getCOM(COM);
341    
342     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    
355     if(usingSMD)
356     cantPos.push_back(COM[whichDirection]);
357     }
358    
359     if(usingSMD)
360     prevCantPos = cantPos;
361     #endif
362    
363    
364     //get total masss of unconstraint molecules
365     double totalMassOfUncons_local;
366     totalMassOfUncons_local = 0;
367    
368     for (size_t i = 0; i < unconsMols.size(); i++)
369     totalMassOfUncons_local += unconsMols[i]->getTotalMass();
370    
371     #ifndef IS_MPI
372     totalMassOfUncons = totalMassOfUncons_local;
373     #else
374     MPI_Allreduce(&totalMassOfUncons_local, &totalMassOfUncons, 1, MPI_DOUBLE,
375     MPI_SUM, MPI_COMM_WORLD);
376     #endif
377    
378     //get total number of unconstrained atoms
379     int nUnconsAtoms_local;
380     nUnconsAtoms_local = 0;
381     for (int i = 0; i < (int) (unconsMols.size()); i++)
382     nUnconsAtoms_local += unconsMols[i]->getNAtoms();
383    
384     #ifndef IS_MPI
385     totNumOfUnconsAtoms = nUnconsAtoms_local;
386     #else
387     MPI_Allreduce(&nUnconsAtoms_local, &totNumOfUnconsAtoms, 1, MPI_INT, MPI_SUM,
388     MPI_COMM_WORLD);
389     #endif
390    
391     forcePolicy->update();
392     }
393    
394     template<typename T> ZConstraint<T>::~ZConstraint(){
395    
396     if (fzOut){
397     delete fzOut;
398     }
399    
400     if (forcePolicy){
401     delete forcePolicy;
402     }
403     }
404    
405    
406     /**
407     *
408     */
409    
410     #ifdef IS_MPI
411     template<typename T> void ZConstraint<T>::update(){
412     double COM[3];
413     int index;
414    
415     zconsMols.clear();
416     massOfZConsMols.clear();
417     zPos.clear();
418     kz.clear();
419     cantPos.clear();
420     cantVel.clear();
421    
422     unconsMols.clear();
423     massOfUnconsMols.clear();
424    
425    
426     //creat zconsMol and unconsMol lists
427     for (int i = 0; i < nMols; i++){
428     index = isZConstraintMol(&molecules[i]);
429    
430     if (index > -1){
431     zconsMols.push_back(&molecules[i]);
432     zPos.push_back((*parameters)[index].zPos);
433     kz.push_back((*parameters)[index].kRatio * zForceConst);
434     massOfZConsMols.push_back(molecules[i].getTotalMass());
435    
436     if(usingSMD)
437     cantVel.push_back((*parameters)[index].cantVel);
438    
439     }
440     else{
441     unconsMols.push_back(&molecules[i]);
442     massOfUnconsMols.push_back(molecules[i].getTotalMass());
443     }
444     }
445    
446     fz.resize(zconsMols.size());
447     curZPos.resize(zconsMols.size());
448     indexOfZConsMols.resize(zconsMols.size());
449    
450     for (size_t i = 0; i < zconsMols.size(); i++){
451     indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex();
452     }
453    
454     //determine the states of z-constraint molecules
455     for (int i = 0; i < (int) (zconsMols.size()); i++){
456    
457     zconsMols[i]->getCOM(COM);
458    
459     if (fabs(zPos[i] - COM[whichDirection]) < zconsTol){
460     states.push_back(zcsFixed);
461    
462     if (hasZConsGap)
463     endFixTime.push_back(info->getTime() + zconsFixTime);
464     }
465     else{
466     states.push_back(zcsMoving);
467    
468     if (hasZConsGap)
469     endFixTime.push_back(INFINITE_TIME);
470     }
471    
472     if(usingSMD)
473     cantPos.push_back(COM[whichDirection]);
474     }
475    
476     if(usingSMD)
477     prevCantPos = cantPos;
478    
479     forcePolicy->update();
480     }
481    
482     #endif
483    
484     /**
485     * Function Name: isZConstraintMol
486     * Parameter
487     * Molecule* mol
488     * Return value:
489     * -1, if the molecule is not z-constraint molecule,
490     * other non-negative values, its index in indexOfAllZConsMols vector
491     */
492    
493     template<typename T> int ZConstraint<T>::isZConstraintMol(Molecule* mol){
494     int index;
495     int low;
496     int high;
497     int mid;
498    
499     index = mol->getGlobalIndex();
500    
501     low = 0;
502     high = parameters->size() - 1;
503    
504     //Binary Search (we have sorted the array)
505     while (low <= high){
506     mid = (low + high) / 2;
507     if ((*parameters)[mid].zconsIndex == index)
508     return mid;
509     else if ((*parameters)[mid].zconsIndex > index)
510     high = mid - 1;
511     else
512     low = mid + 1;
513     }
514    
515     return -1;
516     }
517    
518     template<typename T> void ZConstraint<T>::integrate(){
519     // creat zconsWriter
520     fzOut = new ZConsWriter(zconsOutput.c_str(), parameters);
521    
522     if (!fzOut){
523     sprintf(painCave.errMsg, "Memory allocation failure in class Zconstraint\n");
524     painCave.isFatal = 1;
525     simError();
526     }
527    
528     //zero out the velocities of center of mass of unconstrained molecules
529     //and the velocities of center of mass of every single z-constrained molecueles
530     zeroOutVel();
531    
532     curZconsTime = zconsTime + info->getTime();
533    
534     T::integrate();
535     }
536    
537     template<typename T> void ZConstraint<T>::calcForce(int calcPot, int calcStress){
538     double zsys;
539     double COM[3];
540     double force[3];
541     double zSysCOMVel;
542    
543     T::calcForce(calcPot, calcStress);
544    
545    
546     if (hasZConsGap){
547     updateZPos();
548     }
549    
550     if (checkZConsState()){
551     zeroOutVel();
552     forcePolicy->update();
553     }
554    
555     zsys = calcZSys();
556     zSysCOMVel = calcSysCOMVel();
557     #ifdef IS_MPI
558     if (worldRank == 0){
559     #endif
560    
561     #ifdef IS_MPI
562     }
563     #endif
564    
565     //do zconstraint force;
566     if (haveFixedZMols()){
567     this->doZconstraintForce();
568     }
569    
570     //use external force to move the molecules to the specified positions
571     if (haveMovingZMols()){
572     if (usingSMD)
573     this->doHarmonic(cantPos);
574     else
575     this->doHarmonic(zPos);
576     }
577    
578     //write out forces and current positions of z-constraint molecules
579     if (info->getTime() >= curZconsTime){
580     for (int i = 0; i < (int) (zconsMols.size()); i++){
581     zconsMols[i]->getCOM(COM);
582     curZPos[i] = COM[whichDirection];
583    
584     //if the z-constraint molecule is still moving, just record its force
585     if (states[i] == zcsMoving){
586     fz[i] = 0;
587     Atom** movingZAtoms;
588     movingZAtoms = zconsMols[i]->getMyAtoms();
589     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
590     movingZAtoms[j]->getFrc(force);
591     fz[i] += force[whichDirection];
592     }
593     }
594     }
595     fzOut->writeFZ(info->getTime(), zconsMols.size(), &indexOfZConsMols[0], &fz[0],
596     &curZPos[0], &zPos[0]);
597     curZconsTime += zconsTime;
598     }
599    
600     zSysCOMVel = calcSysCOMVel();
601     #ifdef IS_MPI
602     if (worldRank == 0){
603     #endif
604     #ifdef IS_MPI
605     }
606     #endif
607     }
608    
609    
610     template<typename T> double ZConstraint<T>::calcZSys(){
611     //calculate reference z coordinate for z-constraint molecules
612     double totalMass_local;
613     double totalMass;
614     double totalMZ_local;
615     double totalMZ;
616     double massOfCurMol;
617     double COM[3];
618    
619     totalMass_local = 0;
620     totalMZ_local = 0;
621    
622     for (int i = 0; i < nMols; i++){
623     massOfCurMol = molecules[i].getTotalMass();
624     molecules[i].getCOM(COM);
625    
626     totalMass_local += massOfCurMol;
627     totalMZ_local += massOfCurMol * COM[whichDirection];
628     }
629    
630    
631     #ifdef IS_MPI
632     MPI_Allreduce(&totalMass_local, &totalMass, 1, MPI_DOUBLE, MPI_SUM,
633     MPI_COMM_WORLD);
634     MPI_Allreduce(&totalMZ_local, &totalMZ, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
635     #else
636     totalMass = totalMass_local;
637     totalMZ = totalMZ_local;
638     #endif
639    
640     double zsys;
641     zsys = totalMZ / totalMass;
642    
643     return zsys;
644     }
645    
646     template<typename T> void ZConstraint<T>::thermalize(void){
647     T::thermalize();
648     zeroOutVel();
649     }
650    
651     template<typename T> void ZConstraint<T>::zeroOutVel(){
652     Atom** fixedZAtoms;
653     double COMvel[3];
654     double vel[3];
655     double zSysCOMVel;
656    
657     //zero out the velocities of center of mass of fixed z-constrained molecules
658    
659     for (int i = 0; i < (int) (zconsMols.size()); i++){
660     if (states[i] == zcsFixed){
661     zconsMols[i]->getCOMvel(COMvel);
662     //cout << "before resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
663    
664     fixedZAtoms = zconsMols[i]->getMyAtoms();
665    
666     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
667     fixedZAtoms[j]->getVel(vel);
668     vel[whichDirection] -= COMvel[whichDirection];
669     fixedZAtoms[j]->setVel(vel);
670     }
671    
672     zconsMols[i]->getCOMvel(COMvel);
673     }
674     }
675    
676     zSysCOMVel = calcSysCOMVel();
677     #ifdef IS_MPI
678     if (worldRank == 0){
679     #endif
680     #ifdef IS_MPI
681     }
682     #endif
683    
684     // calculate the vz of center of mass of unconstrained molecules and moving z-constrained molecules
685     double MVzOfMovingMols_local;
686     double MVzOfMovingMols;
687     double totalMassOfMovingZMols_local;
688     double totalMassOfMovingZMols;
689    
690     MVzOfMovingMols_local = 0;
691     totalMassOfMovingZMols_local = 0;
692    
693     for (int i = 0; i < (int) (unconsMols.size()); i++){
694     unconsMols[i]->getCOMvel(COMvel);
695     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
696     }
697    
698     for (int i = 0; i < (int) (zconsMols.size()); i++){
699     if (states[i] == zcsMoving){
700     zconsMols[i]->getCOMvel(COMvel);
701     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
702     totalMassOfMovingZMols_local += massOfZConsMols[i];
703     }
704     }
705    
706     #ifndef IS_MPI
707     MVzOfMovingMols = MVzOfMovingMols_local;
708     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
709     #else
710     MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,
711     MPI_SUM, MPI_COMM_WORLD);
712     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1,
713     MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
714     #endif
715    
716     double vzOfMovingMols;
717     vzOfMovingMols = MVzOfMovingMols /
718     (totalMassOfUncons + totalMassOfMovingZMols);
719    
720     //modify the velocites of unconstrained molecules
721     Atom** unconsAtoms;
722     for (int i = 0; i < (int) (unconsMols.size()); i++){
723     unconsAtoms = unconsMols[i]->getMyAtoms();
724     for (int j = 0; j < unconsMols[i]->getNAtoms(); j++){
725     unconsAtoms[j]->getVel(vel);
726     vel[whichDirection] -= vzOfMovingMols;
727     unconsAtoms[j]->setVel(vel);
728     }
729     }
730    
731     //modify the velocities of moving z-constrained molecuels
732     Atom** movingZAtoms;
733     for (int i = 0; i < (int) (zconsMols.size()); i++){
734     if (states[i] == zcsMoving){
735     movingZAtoms = zconsMols[i]->getMyAtoms();
736     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
737     movingZAtoms[j]->getVel(vel);
738     vel[whichDirection] -= vzOfMovingMols;
739     movingZAtoms[j]->setVel(vel);
740     }
741     }
742     }
743    
744    
745     zSysCOMVel = calcSysCOMVel();
746     #ifdef IS_MPI
747     if (worldRank == 0){
748     #endif
749     #ifdef IS_MPI
750     }
751     #endif
752     }
753    
754    
755     template<typename T> void ZConstraint<T>::doZconstraintForce(){
756     Atom** zconsAtoms;
757     double totalFZ;
758     double totalFZ_local;
759     double COM[3];
760     double force[3];
761    
762     //constrain the molecules which do not reach the specified positions
763    
764     //Zero Out the force of z-contrained molecules
765     totalFZ_local = 0;
766    
767     //calculate the total z-contrained force of fixed z-contrained molecules
768    
769     for (int i = 0; i < (int) (zconsMols.size()); i++){
770     if (states[i] == zcsFixed){
771     zconsMols[i]->getCOM(COM);
772     zconsAtoms = zconsMols[i]->getMyAtoms();
773    
774     fz[i] = 0;
775     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
776     zconsAtoms[j]->getFrc(force);
777     fz[i] += force[whichDirection];
778     }
779     totalFZ_local += fz[i];
780    
781     }
782     }
783    
784     //calculate total z-constraint force
785     #ifdef IS_MPI
786     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
787     #else
788     totalFZ = totalFZ_local;
789     #endif
790    
791    
792     // apply negative to fixed z-constrained molecues;
793     force[0] = 0;
794     force[1] = 0;
795     force[2] = 0;
796    
797     for (int i = 0; i < (int) (zconsMols.size()); i++){
798     if (states[i] == zcsFixed){
799     int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms();
800     zconsAtoms = zconsMols[i]->getMyAtoms();
801    
802     for (int j = 0; j < nAtomOfCurZConsMol; j++){
803     //force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol;
804     force[whichDirection] = -forcePolicy->getZFOfFixedZMols(zconsMols[i],
805     zconsAtoms[j],
806     fz[i]);
807     zconsAtoms[j]->addFrc(force);
808     }
809     }
810     }
811    
812     force[0] = 0;
813     force[1] = 0;
814     force[2] = 0;
815    
816     //modify the forces of unconstrained molecules
817     for (int i = 0; i < (int) (unconsMols.size()); i++){
818     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
819    
820     for (int j = 0; j < unconsMols[i]->getNAtoms(); j++){
821     //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
822     force[whichDirection] = forcePolicy->getZFOfMovingMols(unconsAtoms[j],
823     totalFZ);
824     unconsAtoms[j]->addFrc(force);
825     }
826     }
827    
828     //modify the forces of moving z-constrained molecules
829     for (int i = 0; i < (int) (zconsMols.size()); i++){
830     if (states[i] == zcsMoving){
831     Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
832    
833     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
834     //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
835     force[whichDirection] = forcePolicy->getZFOfMovingMols(movingZAtoms[j],
836     totalFZ);
837     movingZAtoms[j]->addFrc(force);
838     }
839     }
840     }
841     }
842    
843    
844     template<typename T> void ZConstraint<T>::doHarmonic(vector<double>& resPos){
845     double force[3];
846     double harmonicU;
847     double harmonicF;
848     double COM[3];
849     double diff;
850     double totalFZ_local;
851     double totalFZ;
852    
853     force[0] = 0;
854     force[1] = 0;
855     force[2] = 0;
856    
857     totalFZ_local = 0;
858    
859     for (int i = 0; i < (int) (zconsMols.size()); i++){
860     if (states[i] == zcsMoving){
861     zconsMols[i]->getCOM(COM);
862    
863     diff = COM[whichDirection] - resPos[i];
864    
865     harmonicU = 0.5 * kz[i] * diff * diff;
866     info->lrPot += harmonicU;
867    
868     harmonicF = -kz[i] * diff;
869     totalFZ_local += harmonicF;
870    
871     //adjust force
872    
873     Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
874    
875     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
876     force[whichDirection] = forcePolicy->getHFOfFixedZMols(zconsMols[i],
877     movingZAtoms[j],
878     harmonicF);
879     movingZAtoms[j]->addFrc(force);
880     }
881     }
882     }
883    
884     #ifndef IS_MPI
885     totalFZ = totalFZ_local;
886     #else
887     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
888     #endif
889    
890     force[0] = 0;
891     force[1] = 0;
892     force[2] = 0;
893    
894     //modify the forces of unconstrained molecules
895     for (int i = 0; i < (int) (unconsMols.size()); i++){
896     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
897    
898     for (int j = 0; j < unconsMols[i]->getNAtoms(); j++){
899     //force[whichDirection] = - totalFZ /totNumOfUnconsAtoms;
900     force[whichDirection] = -forcePolicy->getHFOfUnconsMols(unconsAtoms[j],
901     totalFZ);
902     unconsAtoms[j]->addFrc(force);
903     }
904     }
905    
906     }
907    
908     template<typename T> bool ZConstraint<T>::checkZConsState(){
909     double COM[3];
910     double diff;
911    
912     int changed_local;
913     int changed;
914    
915     changed_local = 0;
916    
917     for (int i = 0; i < (int) (zconsMols.size()); i++){
918     zconsMols[i]->getCOM(COM);
919     diff = fabs(COM[whichDirection] - zPos[i]);
920     if (diff <= zconsTol && states[i] == zcsMoving){
921     states[i] = zcsFixed;
922     changed_local = 1;
923    
924     if(usingSMD)
925     prevCantPos = cantPos;
926    
927     if (hasZConsGap)
928     endFixTime[i] = info->getTime() + zconsFixTime;
929     }
930     else if (diff > zconsTol && states[i] == zcsFixed){
931     states[i] = zcsMoving;
932     changed_local = 1;
933    
934     if(usingSMD)
935     cantPos = prevCantPos;
936    
937     if (hasZConsGap)
938     endFixTime[i] = INFINITE_TIME;
939     }
940     }
941    
942     #ifndef IS_MPI
943     changed = changed_local;
944     #else
945     MPI_Allreduce(&changed_local, &changed, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
946     #endif
947    
948     return (changed > 0);
949     }
950    
951     template<typename T> bool ZConstraint<T>::haveFixedZMols(){
952     int havingFixed_local;
953     int havingFixed;
954    
955     havingFixed_local = 0;
956    
957     for (int i = 0; i < (int) (zconsMols.size()); i++)
958     if (states[i] == zcsFixed){
959     havingFixed_local = 1;
960     break;
961     }
962    
963     #ifndef IS_MPI
964     havingFixed = havingFixed_local;
965     #else
966     MPI_Allreduce(&havingFixed_local, &havingFixed, 1, MPI_INT, MPI_SUM,
967     MPI_COMM_WORLD);
968     #endif
969    
970     return (havingFixed > 0);
971     }
972    
973    
974     template<typename T> bool ZConstraint<T>::haveMovingZMols(){
975     int havingMoving_local;
976     int havingMoving;
977    
978     havingMoving_local = 0;
979    
980     for (int i = 0; i < (int) (zconsMols.size()); i++)
981     if (states[i] == zcsMoving){
982     havingMoving_local = 1;
983     break;
984     }
985    
986     #ifndef IS_MPI
987     havingMoving = havingMoving_local;
988     #else
989     MPI_Allreduce(&havingMoving_local, &havingMoving, 1, MPI_INT, MPI_SUM,
990     MPI_COMM_WORLD);
991     #endif
992    
993     return (havingMoving > 0);
994     }
995    
996    
997     template<typename T> double ZConstraint<T>::calcMovingMolsCOMVel(){
998     double MVzOfMovingMols_local;
999     double MVzOfMovingMols;
1000     double totalMassOfMovingZMols_local;
1001     double totalMassOfMovingZMols;
1002     double COMvel[3];
1003    
1004     MVzOfMovingMols_local = 0;
1005     totalMassOfMovingZMols_local = 0;
1006    
1007     for (int i = 0; i < unconsMols.size(); i++){
1008     unconsMols[i]->getCOMvel(COMvel);
1009     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
1010     }
1011    
1012     for (int i = 0; i < zconsMols.size(); i++){
1013     if (states[i] == zcsMoving){
1014     zconsMols[i]->getCOMvel(COMvel);
1015     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
1016     totalMassOfMovingZMols_local += massOfZConsMols[i];
1017     }
1018     }
1019    
1020     #ifndef IS_MPI
1021     MVzOfMovingMols = MVzOfMovingMols_local;
1022     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
1023     #else
1024     MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,
1025     MPI_SUM, MPI_COMM_WORLD);
1026     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1,
1027     MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
1028     #endif
1029    
1030     double vzOfMovingMols;
1031     vzOfMovingMols = MVzOfMovingMols /
1032     (totalMassOfUncons + totalMassOfMovingZMols);
1033    
1034     return vzOfMovingMols;
1035     }
1036    
1037     template<typename T> double ZConstraint<T>::calcSysCOMVel(){
1038     double COMvel[3];
1039     double tempMVz_local;
1040     double tempMVz;
1041     double massOfZCons_local;
1042     double massOfZCons;
1043    
1044    
1045     tempMVz_local = 0;
1046    
1047     for (int i = 0 ; i < nMols; i++){
1048     molecules[i].getCOMvel(COMvel);
1049     tempMVz_local += molecules[i].getTotalMass() * COMvel[whichDirection];
1050     }
1051    
1052     massOfZCons_local = 0;
1053    
1054     for (int i = 0; i < (int) (massOfZConsMols.size()); i++){
1055     massOfZCons_local += massOfZConsMols[i];
1056     }
1057     #ifndef IS_MPI
1058     massOfZCons = massOfZCons_local;
1059     tempMVz = tempMVz_local;
1060     #else
1061     MPI_Allreduce(&massOfZCons_local, &massOfZCons, 1, MPI_DOUBLE, MPI_SUM,
1062     MPI_COMM_WORLD);
1063     MPI_Allreduce(&tempMVz_local, &tempMVz, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
1064     #endif
1065    
1066     return tempMVz / (totalMassOfUncons + massOfZCons);
1067     }
1068    
1069     template<typename T> double ZConstraint<T>::calcTotalForce(){
1070     double force[3];
1071     double totalForce_local;
1072     double totalForce;
1073    
1074     totalForce_local = 0;
1075    
1076     for (int i = 0; i < nAtoms; i++){
1077     atoms[i]->getFrc(force);
1078     totalForce_local += force[whichDirection];
1079     }
1080    
1081     #ifndef IS_MPI
1082     totalForce = totalForce_local;
1083     #else
1084     MPI_Allreduce(&totalForce_local, &totalForce, 1, MPI_DOUBLE, MPI_SUM,
1085     MPI_COMM_WORLD);
1086     #endif
1087    
1088     return totalForce;
1089     }
1090    
1091     template<typename T> void ZConstraint<T>::PolicyByNumber::update(){
1092     //calculate the number of atoms of moving z-constrained molecules
1093     int nMovingZAtoms_local;
1094     int nMovingZAtoms;
1095    
1096     nMovingZAtoms_local = 0;
1097     for (int i = 0; i < (int) ((zconsIntegrator->zconsMols).size()); i++)
1098     if ((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving)){
1099     nMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getNAtoms();
1100     }
1101    
1102     #ifdef IS_MPI
1103     MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1, MPI_INT, MPI_SUM,
1104     MPI_COMM_WORLD);
1105     #else
1106     nMovingZAtoms = nMovingZAtoms_local;
1107     #endif
1108     totNumOfMovingAtoms = nMovingZAtoms + zconsIntegrator->totNumOfUnconsAtoms;
1109     }
1110    
1111     template<typename T> double ZConstraint<T>::PolicyByNumber::getZFOfFixedZMols(Molecule* mol,
1112     Atom* atom,
1113     double totalForce){
1114     return totalForce / mol->getNAtoms();
1115     }
1116    
1117     template<typename T> double ZConstraint<T>::PolicyByNumber::getZFOfMovingMols(Atom* atom,
1118     double totalForce){
1119     return totalForce / totNumOfMovingAtoms;
1120     }
1121    
1122     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfFixedZMols(Molecule* mol,
1123     Atom* atom,
1124     double totalForce){
1125     return totalForce / mol->getNAtoms();
1126     }
1127    
1128     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfUnconsMols(Atom* atom,
1129     double totalForce){
1130     return totalForce / zconsIntegrator->totNumOfUnconsAtoms;
1131     }
1132    
1133    
1134     template<typename T> void ZConstraint<T>::PolicyByMass::update(){
1135     //calculate the number of atoms of moving z-constrained molecules
1136     double massOfMovingZAtoms_local;
1137     double massOfMovingZAtoms;
1138    
1139     massOfMovingZAtoms_local = 0;
1140     for (int i = 0; i < (int) ((zconsIntegrator->zconsMols).size()); i++)
1141     if ((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving)){
1142     massOfMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getTotalMass();
1143     }
1144    
1145     #ifdef IS_MPI
1146     MPI_Allreduce(&massOfMovingZAtoms_local, &massOfMovingZAtoms, 1, MPI_DOUBLE,
1147     MPI_SUM, MPI_COMM_WORLD);
1148     #else
1149     massOfMovingZAtoms = massOfMovingZAtoms_local;
1150     #endif
1151     totMassOfMovingAtoms = massOfMovingZAtoms +
1152     zconsIntegrator->totalMassOfUncons;
1153     }
1154    
1155     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfFixedZMols(Molecule* mol,
1156     Atom* atom,
1157     double totalForce){
1158     return totalForce * atom->getMass() / mol->getTotalMass();
1159     }
1160    
1161     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfMovingMols(Atom* atom,
1162     double totalForce){
1163     return totalForce * atom->getMass() / totMassOfMovingAtoms;
1164     }
1165    
1166     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfFixedZMols(Molecule* mol,
1167     Atom* atom,
1168     double totalForce){
1169     return totalForce * atom->getMass() / mol->getTotalMass();
1170     }
1171    
1172     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfUnconsMols(Atom* atom,
1173     double totalForce){
1174     return totalForce * atom->getMass() / zconsIntegrator->totalMassOfUncons;
1175     }
1176    
1177     template<typename T> void ZConstraint<T>::updateZPos(){
1178     double curTime;
1179     double COM[3];
1180    
1181     curTime = info->getTime();
1182    
1183     for (size_t i = 0; i < zconsMols.size(); i++){
1184    
1185     if (states[i] == zcsFixed && curTime >= endFixTime[i]){
1186     zPos[i] += zconsGap;
1187    
1188     if (usingSMD){
1189     zconsMols[i]->getCOM(COM);
1190     cantPos[i] = COM[whichDirection];
1191     }
1192    
1193     }
1194    
1195     }
1196    
1197     }
1198    
1199     template<typename T> void ZConstraint<T>::updateCantPos(){
1200     double curTime;
1201     double dt;
1202    
1203     curTime = info->getTime();
1204     dt = info->dt;
1205    
1206     for (size_t i = 0; i < zconsMols.size(); i++){
1207     if (states[i] == zcsMoving){
1208     cantPos[i] += cantVel[i] * dt;
1209     }
1210     }
1211    
1212     }