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