ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 693
Committed: Wed Aug 13 19:21:53 2003 UTC (20 years, 10 months ago) by tim
File size: 23205 byte(s)
Log Message:
harmonic potential & z-contraint method

File Contents

# User Rev Content
1 tim 658 #include "Integrator.hpp"
2     #include "simError.h"
3 tim 676 #include <cmath>
4 tim 658 template<typename T> ZConstraint<T>::ZConstraint(SimInfo* theInfo, ForceFields* the_ff)
5 tim 676 : T(theInfo, the_ff), fz(NULL),
6     indexOfZConsMols(NULL)
7 tim 658 {
8    
9     //get properties from SimInfo
10     GenericData* data;
11 tim 682 ZConsParaData* zConsParaData;
12 tim 658 DoubleData* sampleTime;
13 tim 682 DoubleData* tolerance;
14 tim 658 StringData* filename;
15 tim 682 double COM[3];
16 tim 658
17 tim 682 //by default, the direction of constraint is z
18     // 0 --> x
19     // 1 --> y
20     // 2 --> z
21     whichDirection = 2;
22 tim 658
23 tim 682 //estimate the force constant of harmonical potential
24     double Kb = 1.986E-3 ; //in kcal/K
25    
26     double halfOfLargestBox = max(info->boxL[0], max(info->boxL[1], info->boxL[2])) /2;
27     zForceConst = Kb * info->target_temp /(halfOfLargestBox * halfOfLargestBox);
28 tim 676
29     //retrieve sample time of z-contraint
30 tim 682 data = info->getProperty(ZCONSTIME_ID);
31 tim 658
32     if(!data) {
33    
34     sprintf( painCave.errMsg,
35     "ZConstraint error: If you use an ZConstraint\n"
36     " , you must set sample time.\n");
37     painCave.isFatal = 1;
38     simError();
39     }
40     else{
41    
42     sampleTime = dynamic_cast<DoubleData*>(data);
43    
44     if(!sampleTime){
45    
46     sprintf( painCave.errMsg,
47     "ZConstraint error: Can not get property from SimInfo\n");
48     painCave.isFatal = 1;
49     simError();
50    
51     }
52     else{
53     this->zconsTime = sampleTime->getData();
54     }
55    
56     }
57    
58 tim 676 //retrieve output filename of z force
59 tim 682 data = info->getProperty(ZCONSFILENAME_ID);
60 tim 658 if(!data) {
61    
62    
63     sprintf( painCave.errMsg,
64     "ZConstraint error: If you use an ZConstraint\n"
65     " , you must set output filename of z-force.\n");
66     painCave.isFatal = 1;
67     simError();
68    
69     }
70     else{
71    
72     filename = dynamic_cast<StringData*>(data);
73    
74     if(!filename){
75    
76     sprintf( painCave.errMsg,
77     "ZConstraint error: Can not get property from SimInfo\n");
78     painCave.isFatal = 1;
79     simError();
80    
81     }
82     else{
83     this->zconsOutput = filename->getData();
84     }
85    
86    
87     }
88 tim 682
89     //retrieve tolerance for z-constraint molecuels
90     data = info->getProperty(ZCONSTOL_ID);
91 tim 658
92 tim 682 if(!data) {
93    
94     sprintf( painCave.errMsg,
95     "ZConstraint error: can not get tolerance \n");
96     painCave.isFatal = 1;
97     simError();
98     }
99     else{
100    
101     tolerance = dynamic_cast<DoubleData*>(data);
102    
103     if(!tolerance){
104    
105     sprintf( painCave.errMsg,
106     "ZConstraint error: Can not get property from SimInfo\n");
107     painCave.isFatal = 1;
108     simError();
109    
110     }
111     else{
112     this->zconsTol = tolerance->getData();
113     }
114    
115     }
116    
117     //retrieve index of z-constraint molecules
118     data = info->getProperty(ZCONSPARADATA_ID);
119     if(!data) {
120    
121     sprintf( painCave.errMsg,
122     "ZConstraint error: If you use an ZConstraint\n"
123     " , you must set index of z-constraint molecules.\n");
124     painCave.isFatal = 1;
125     simError();
126     }
127     else{
128    
129     zConsParaData = dynamic_cast<ZConsParaData*>(data);
130    
131     if(!zConsParaData){
132    
133     sprintf( painCave.errMsg,
134     "ZConstraint error: Can not get parameters of zconstraint method from SimInfo\n");
135     painCave.isFatal = 1;
136     simError();
137    
138     }
139     else{
140    
141     parameters = zConsParaData->getData();
142    
143     //check the range of zconsIndex
144     //and the minimum value of index is the first one (we already sorted the data)
145     //the maximum value of index is the last one
146    
147     int maxIndex;
148     int minIndex;
149     int totalNumMol;
150    
151     minIndex = (*parameters)[0].zconsIndex;
152     if(minIndex < 0){
153     sprintf( painCave.errMsg,
154     "ZConstraint error: index is out of range\n");
155     painCave.isFatal = 1;
156     simError();
157     }
158    
159 tim 693 maxIndex = (*parameters)[parameters->size() - 1].zconsIndex;
160 tim 682
161     #ifndef IS_MPI
162     totalNumMol = nMols;
163     #else
164     totalNumMol = mpiSim->getTotNmol();
165     #endif
166    
167     if(maxIndex > totalNumMol - 1){
168     sprintf( painCave.errMsg,
169     "ZConstraint error: index is out of range\n");
170     painCave.isFatal = 1;
171     simError();
172     }
173    
174     //if user does not specify the zpos for the zconstraint molecule
175     //its initial z coordinate will be used as default
176     for(int i = 0; i < parameters->size(); i++){
177    
178     if(!(*parameters)[i].havingZPos){
179    
180     #ifndef IS_MPI
181     for(int j = 0; j < nMols; j++){
182 tim 693 if (molecules[j].getGlobalIndex() == (*parameters)[i].zconsIndex){
183     molecules[j].getCOM(COM);
184 tim 682 break;
185     }
186     }
187     #else
188     //query which processor current zconstraint molecule belongs to
189     int *MolToProcMap;
190     int whichNode;
191     double initZPos;
192     MolToProcMap = mpiSim->getMolToProcMap();
193     whichNode = MolToProcMap[(*parameters)[i].zconsIndex];
194    
195     //broadcast the zpos of current z-contraint molecule
196     //the node which contain this
197    
198     if (worldRank == whichNode ){
199    
200 tim 693 for(int j = 0; j < nMols; j++)
201     if (molecules[j].getGlobalIndex() == (*parameters)[i].zconsIndex){
202     molecules[j].getCOM(COM);
203 tim 682 break;
204     }
205    
206     }
207    
208     MPI_Bcast(&COM[whichDirection], 1, MPI_DOUBLE_PRECISION, whichNode, MPI_COMM_WORLD);
209     #endif
210    
211     (*parameters)[i].zPos = COM[whichDirection];
212    
213     sprintf( painCave.errMsg,
214     "ZConstraint warningr: Does not specify zpos for z-constraint molecule "
215     "initial z coornidate will be used \n");
216     painCave.isFatal = 0;
217     simError();
218    
219     }
220     }
221    
222     }//end if (!zConsParaData)
223     }//end if (!data)
224    
225     //
226 tim 658 #ifdef IS_MPI
227     update();
228     #else
229     int searchResult;
230 tim 676
231 tim 658 for(int i = 0; i < nMols; i++){
232    
233     searchResult = isZConstraintMol(&molecules[i]);
234    
235     if(searchResult > -1){
236    
237     zconsMols.push_back(&molecules[i]);
238     massOfZConsMols.push_back(molecules[i].getTotalMass());
239 tim 682
240     zPos.push_back((*parameters)[searchResult].zPos);
241     kz.push_back((*parameters)[searchResult]. kRatio * zForceConst);
242 tim 676
243 tim 658 molecules[i].getCOM(COM);
244     }
245     else
246     {
247    
248     unconsMols.push_back(&molecules[i]);
249     massOfUnconsMols.push_back(molecules[i].getTotalMass());
250    
251     }
252     }
253    
254     fz = new double[zconsMols.size()];
255     indexOfZConsMols = new int [zconsMols.size()];
256    
257     if(!fz || !indexOfZConsMols){
258     sprintf( painCave.errMsg,
259     "Memory allocation failure in class Zconstraint\n");
260     painCave.isFatal = 1;
261     simError();
262     }
263    
264 tim 693 //determine the states of z-constraint molecules
265     for(int i = 0; i < zconsMols.size(); i++){
266 tim 658 indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex();
267 tim 693
268     zconsMols[i]->getCOM(COM);
269     if (fabs(zPos[i] - COM[whichDirection]) < zconsTol)
270     states.push_back(zcsFixed);
271     else
272     states.push_back(zcsMoving);
273     }
274 tim 658
275     #endif
276 tim 676
277 tim 693 //get total masss of unconstraint molecules
278     double totalMassOfUncons_local;
279     totalMassOfUncons_local = 0;
280    
281     for(int i = 0; i < unconsMols.size(); i++)
282     totalMassOfUncons_local += unconsMols[i]->getTotalMass();
283    
284     #ifndef IS_MPI
285     totalMassOfUncons = totalMassOfUncons_local;
286     #else
287     MPI_Allreduce(&totalMassOfUncons_local, &totalMassOfUncons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
288     #endif
289    
290    
291 tim 676 //get total number of unconstrained atoms
292     int nUnconsAtoms_local;
293     nUnconsAtoms_local = 0;
294     for(int i = 0; i < unconsMols.size(); i++)
295     nUnconsAtoms_local += unconsMols[i]->getNAtoms();
296    
297     #ifndef IS_MPI
298     totNumOfUnconsAtoms = nUnconsAtoms_local;
299     #else
300     MPI_Allreduce(&nUnconsAtoms_local, &totNumOfUnconsAtoms, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
301 tim 693 #endif
302 tim 676
303 tim 693 // creat zconsWriter
304 tim 658 fzOut = new ZConsWriter(zconsOutput.c_str());
305    
306     if(!fzOut){
307     sprintf( painCave.errMsg,
308     "Memory allocation failure in class Zconstraint\n");
309     painCave.isFatal = 1;
310     simError();
311     }
312    
313     }
314    
315     template<typename T> ZConstraint<T>::~ZConstraint()
316     {
317     if(fz)
318     delete[] fz;
319    
320     if(indexOfZConsMols)
321     delete[] indexOfZConsMols;
322    
323     if(fzOut)
324     delete fzOut;
325     }
326    
327     #ifdef IS_MPI
328     template<typename T> void ZConstraint<T>::update()
329     {
330     double COM[3];
331     int index;
332    
333     zconsMols.clear();
334     massOfZConsMols.clear();
335 tim 682 zPos.clear();
336     kz.clear();
337 tim 658
338     unconsMols.clear();
339     massOfUnconsMols.clear();
340    
341    
342     //creat zconsMol and unconsMol lists
343     for(int i = 0; i < nMols; i++){
344    
345     index = isZConstraintMol(&molecules[i]);
346    
347     if(index > -1){
348    
349     zconsMols.push_back(&molecules[i]);
350 tim 682 zPos.push_back((*parameters)[index].zPos);
351 tim 693 kz.push_back((*parameters)[index].kRatio * zForceConst);
352    
353 tim 658 massOfZConsMols.push_back(molecules[i].getTotalMass());
354    
355     molecules[i].getCOM(COM);
356     }
357     else
358     {
359    
360     unconsMols.push_back(&molecules[i]);
361     massOfUnconsMols.push_back(molecules[i].getTotalMass());
362    
363     }
364     }
365 tim 693
366     //determine the states of z-constraint molecules
367     for(int i = 0; i < zconsMols.size(); i++){
368     zconsMols[i]->getCOM(COM);
369     if (fabs(zPos[i] - COM[whichDirection]) < zconsTol)
370     states.push_back(zcsFixed);
371     else
372     states.push_back(zcsMoving);
373     }
374    
375 tim 658
376     //The reason to declare fz and indexOfZconsMols as pointer to array is
377     // that we want to make the MPI communication simple
378     if(fz)
379     delete[] fz;
380    
381     if(indexOfZConsMols)
382     delete[] indexOfZConsMols;
383    
384     if (zconsMols.size() > 0){
385     fz = new double[zconsMols.size()];
386     indexOfZConsMols = new int[zconsMols.size()];
387    
388     if(!fz || !indexOfZConsMols){
389     sprintf( painCave.errMsg,
390     "Memory allocation failure in class Zconstraint\n");
391     painCave.isFatal = 1;
392     simError();
393     }
394    
395     for(int i = 0; i < zconsMols.size(); i++){
396     indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex();
397     }
398    
399     }
400     else{
401     fz = NULL;
402     indexOfZConsMols = NULL;
403     }
404    
405     }
406    
407     #endif
408    
409     /** Function Name: isZConstraintMol
410     ** Parameter
411     ** Molecule* mol
412     ** Return value:
413     ** -1, if the molecule is not z-constraint molecule,
414     ** other non-negative values, its index in indexOfAllZConsMols vector
415     */
416    
417     template<typename T> int ZConstraint<T>::isZConstraintMol(Molecule* mol)
418     {
419     int index;
420     int low;
421     int high;
422     int mid;
423    
424     index = mol->getGlobalIndex();
425    
426     low = 0;
427 tim 682 high = parameters->size() - 1;
428 tim 658
429     //Binary Search (we have sorted the array)
430     while(low <= high){
431     mid = (low + high) /2;
432 tim 682 if ((*parameters)[mid].zconsIndex == index)
433 tim 658 return mid;
434 tim 682 else if ((*parameters)[mid].zconsIndex > index )
435 tim 658 high = mid -1;
436     else
437     low = mid + 1;
438     }
439    
440     return -1;
441     }
442    
443 tim 676 template<typename T> void ZConstraint<T>::integrate(){
444 tim 658
445 tim 676 //zero out the velocities of center of mass of unconstrained molecules
446     //and the velocities of center of mass of every single z-constrained molecueles
447     zeroOutVel();
448    
449     T::integrate();
450    
451 tim 658 }
452 tim 676
453 tim 658
454 tim 676 /**
455     *
456     *
457     *
458     *
459 tim 658 */
460    
461 tim 676
462     template<typename T> void ZConstraint<T>::calcForce(int calcPot, int calcStress){
463 tim 693 double zsys;
464 tim 676
465     T::calcForce(calcPot, calcStress);
466    
467     if (checkZConsState())
468 tim 693 zeroOutVel();
469    
470     zsys = calcZSys();
471     cout << "---------------------------------------------------------------------" <<endl;
472     cout << "current time: " << info->getTime() <<"\tcenter of mass at z: " << zsys << endl;
473     cout << "before calcForce, the COMVel of unconstraint molecules is " << calcCOMVel() <<endl;
474    
475 tim 676
476     //do zconstraint force;
477     if (haveFixedZMols())
478     this->doZconstraintForce();
479 tim 693
480    
481    
482 tim 676 //use harmonical poteintial to move the molecules to the specified positions
483     if (haveMovingZMols())
484 tim 693 this->doHarmonic();
485 tim 676
486     fzOut->writeFZ(info->getTime(), zconsMols.size(),indexOfZConsMols, fz);
487 tim 693 cout << "after calcForce, the COMVel of unconstraint molecules is " << calcCOMVel() <<endl;
488 tim 676 }
489    
490     template<typename T> double ZConstraint<T>::calcZSys()
491 tim 658 {
492 tim 676 //calculate reference z coordinate for z-constraint molecules
493     double totalMass_local;
494     double totalMass;
495     double totalMZ_local;
496     double totalMZ;
497     double massOfUncons_local;
498     double massOfCurMol;
499     double COM[3];
500    
501     totalMass_local = 0;
502     totalMass = 0;
503     totalMZ_local = 0;
504     totalMZ = 0;
505     massOfUncons_local = 0;
506    
507    
508     for(int i = 0; i < nMols; i++){
509     massOfCurMol = molecules[i].getTotalMass();
510     molecules[i].getCOM(COM);
511    
512     totalMass_local += massOfCurMol;
513     totalMZ_local += massOfCurMol * COM[whichDirection];
514    
515     if(isZConstraintMol(&molecules[i]) == -1){
516    
517     massOfUncons_local += massOfCurMol;
518     }
519    
520     }
521    
522    
523     #ifdef IS_MPI
524     MPI_Allreduce(&totalMass_local, &totalMass, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
525     MPI_Allreduce(&totalMZ_local, &totalMZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
526     MPI_Allreduce(&massOfUncons_local, &totalMassOfUncons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
527     #else
528     totalMass = totalMass_local;
529     totalMZ = totalMZ_local;
530     totalMassOfUncons = massOfUncons_local;
531     #endif
532 mmeineke 671
533 tim 658 double zsys;
534 tim 676 zsys = totalMZ / totalMass;
535 tim 658
536 tim 676 return zsys;
537     }
538    
539     /**
540     *
541     */
542     template<typename T> void ZConstraint<T>::thermalize( void ){
543    
544     T::thermalize();
545     zeroOutVel();
546     }
547    
548     /**
549     *
550     *
551     *
552     */
553    
554     template<typename T> void ZConstraint<T>::zeroOutVel(){
555    
556     Atom** fixedZAtoms;
557     double COMvel[3];
558     double vel[3];
559 tim 693
560     double tempMass = 0;
561     double tempMVz =0;
562     double tempVz = 0;
563     for(int i = 0; i < nMols; i++){
564     molecules[i].getCOMvel(COMvel);
565     tempMass +=molecules[i].getTotalMass();
566     tempMVz += molecules[i].getTotalMass() * COMvel[whichDirection];
567     tempVz += COMvel[whichDirection];
568     }
569     cout << "initial velocity of center of mass is " << tempMVz / tempMass << endl;
570    
571 tim 676 //zero out the velocities of center of mass of fixed z-constrained molecules
572    
573 tim 658 for(int i = 0; i < zconsMols.size(); i++){
574 tim 676
575     if (states[i] == zcsFixed){
576    
577 tim 693 zconsMols[i]->getCOMvel(COMvel);
578     cout << "before resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
579    
580 tim 676 fixedZAtoms = zconsMols[i]->getMyAtoms();
581    
582     for(int j =0; j < zconsMols[i]->getNAtoms(); j++){
583     fixedZAtoms[j]->getVel(vel);
584 tim 693 vel[whichDirection] -= COMvel[whichDirection];
585     fixedZAtoms[j]->setVel(vel);
586 tim 676 }
587 tim 693
588     zconsMols[i]->getCOMvel(COMvel);
589     cout << "after resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
590 tim 676 }
591    
592 tim 658 }
593 tim 693
594     cout << "before resetting the COMVel of unconstraint molecules is " << calcCOMVel() <<endl;
595    
596 tim 676 // calculate the vz of center of mass of unconstrained molecules and moving z-constrained molecules
597     double MVzOfMovingMols_local;
598     double MVzOfMovingMols;
599     double totalMassOfMovingZMols_local;
600     double totalMassOfMovingZMols;
601    
602     MVzOfMovingMols_local = 0;
603     totalMassOfMovingZMols_local = 0;
604 tim 658
605 tim 676 for(int i =0; i < unconsMols.size(); i++){
606     unconsMols[i]->getCOMvel(COMvel);
607     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
608     }
609    
610 tim 693 for(int i = 0; i < zconsMols.size(); i++){
611 tim 676 if (states[i] == zcsMoving){
612     zconsMols[i]->getCOMvel(COMvel);
613     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
614     totalMassOfMovingZMols_local += massOfZConsMols[i];
615     }
616    
617     }
618    
619     #ifndef IS_MPI
620     MVzOfMovingMols = MVzOfMovingMols_local;
621     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
622 tim 658 #else
623 tim 676 MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
624     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
625 tim 658 #endif
626    
627 tim 676 double vzOfMovingMols;
628     vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
629    
630     //modify the velocites of unconstrained molecules
631     Atom** unconsAtoms;
632 tim 658 for(int i = 0; i < unconsMols.size(); i++){
633 tim 676
634     unconsAtoms = unconsMols[i]->getMyAtoms();
635     for(int j = 0; j < unconsMols[i]->getNAtoms();j++){
636     unconsAtoms[j]->getVel(vel);
637     vel[whichDirection] -= vzOfMovingMols;
638     unconsAtoms[j]->setVel(vel);
639     }
640    
641     }
642    
643     //modify the velocities of moving z-constrained molecuels
644     Atom** movingZAtoms;
645 tim 693 for(int i = 0; i < zconsMols.size(); i++){
646 tim 676
647     if (states[i] ==zcsMoving){
648    
649     movingZAtoms = zconsMols[i]->getMyAtoms();
650 tim 693 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
651 tim 676 movingZAtoms[j]->getVel(vel);
652     vel[whichDirection] -= vzOfMovingMols;
653 tim 693 movingZAtoms[j]->setVel(vel);
654     }
655 tim 676
656 tim 693 }
657 tim 676
658 tim 693 }
659 tim 676
660 tim 693 cout << "after resetting the COMVel of unconstraint molecules is " << calcCOMVel() <<endl;
661    
662 tim 676 }
663    
664     template<typename T> void ZConstraint<T>::doZconstraintForce(){
665    
666     Atom** zconsAtoms;
667     double totalFZ;
668     double totalFZ_local;
669     double COMvel[3];
670     double COM[3];
671     double force[3];
672    
673     int nMovingZMols_local;
674     int nMovingZMols;
675    
676     //constrain the molecules which do not reach the specified positions
677    
678     //Zero Out the force of z-contrained molecules
679     totalFZ_local = 0;
680    
681     //calculate the total z-contrained force of fixed z-contrained molecules
682 tim 682 cout << "Fixed Molecules" << endl;
683 tim 676 for(int i = 0; i < zconsMols.size(); i++){
684    
685     if (states[i] == zcsFixed){
686    
687     zconsMols[i]->getCOM(COM);
688     zconsAtoms = zconsMols[i]->getMyAtoms();
689    
690     fz[i] = 0;
691     for(int j =0; j < zconsMols[i]->getNAtoms(); j++) {
692     zconsAtoms[j]->getFrc(force);
693     fz[i] += force[whichDirection];
694     }
695     totalFZ_local += fz[i];
696    
697     cout << "index: " << indexOfZConsMols[i] <<"\tcurrent zpos: " << COM[whichDirection] << endl;
698    
699     }
700    
701     }
702    
703     //calculate the number of atoms of moving z-constrained molecules
704     nMovingZMols_local = 0;
705 tim 693 for(int i = 0; i < zconsMols.size(); i++)
706 tim 676 if(states[i] == zcsMoving)
707 tim 693 nMovingZMols_local += massOfZConsMols[i];
708    
709 tim 658 #ifdef IS_MPI
710 tim 676 MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
711     MPI_Allreduce(&nMovingZMols_local, &nMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
712 tim 658 #else
713 tim 676 totalFZ = totalFZ_local;
714     nMovingZMols = nMovingZMols_local;
715     #endif
716    
717     force[0]= 0;
718     force[1]= 0;
719     force[2]= 0;
720     force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZMols);
721    
722 tim 693 //modify the forces of unconstrained molecules
723 tim 676 for(int i = 0; i < unconsMols.size(); i++){
724    
725     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
726    
727     for(int j = 0; j < unconsMols[i]->getNAtoms(); j++)
728     unconsAtoms[j]->addFrc(force);
729    
730     }
731    
732 tim 693 //modify the forces of moving z-constrained molecules
733 tim 676 for(int i = 0; i < zconsMols.size(); i++) {
734     if (states[i] == zcsMoving){
735    
736     Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
737    
738     for(int j = 0; j < zconsMols[i]->getNAtoms(); j++)
739     movingZAtoms[j]->addFrc(force);
740     }
741     }
742    
743     // apply negative to fixed z-constrained molecues;
744     force[0]= 0;
745     force[1]= 0;
746     force[2]= 0;
747    
748     for(int i = 0; i < zconsMols.size(); i++){
749    
750     if (states[i] == zcsFixed){
751    
752     int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms();
753     zconsAtoms = zconsMols[i]->getMyAtoms();
754    
755     for(int j =0; j < nAtomOfCurZConsMol; j++) {
756     force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol;
757     zconsAtoms[j]->addFrc(force);
758     }
759    
760     }
761    
762     }
763    
764     }
765    
766     template<typename T> bool ZConstraint<T>::checkZConsState(){
767     double COM[3];
768     double diff;
769 tim 658
770 tim 676 bool changed;
771    
772     changed = false;
773    
774     for(int i =0; i < zconsMols.size(); i++){
775    
776 tim 658 zconsMols[i]->getCOM(COM);
777 tim 682 diff = fabs(COM[whichDirection] - zPos[i]);
778     if ( diff <= zconsTol && states[i] == zcsMoving){
779 tim 676 states[i] = zcsFixed;
780     changed = true;
781     }
782 tim 682 else if ( diff > zconsTol && states[i] == zcsFixed){
783 tim 676 states[i] = zcsMoving;
784     changed = true;
785     }
786    
787 tim 658 }
788    
789 tim 676 return changed;
790 tim 658 }
791 tim 676
792     template<typename T> bool ZConstraint<T>::haveFixedZMols(){
793     for(int i = 0; i < zconsMols.size(); i++)
794     if (states[i] == zcsFixed)
795     return true;
796    
797     return false;
798     }
799    
800    
801     /**
802     *
803     */
804     template<typename T> bool ZConstraint<T>::haveMovingZMols(){
805     for(int i = 0; i < zconsMols.size(); i++)
806     if (states[i] == zcsMoving)
807     return true;
808    
809     return false;
810    
811 tim 682 }
812    
813     /**
814     *
815     *
816     */
817    
818     template<typename T> void ZConstraint<T>::doHarmonic(){
819     double force[3];
820     double harmonicU;
821 tim 693 double harmonicF;
822 tim 682 double COM[3];
823     double diff;
824 tim 693 double totalFZ;
825 tim 682
826     force[0] = 0;
827     force[1] = 0;
828     force[2] = 0;
829    
830 tim 693 totalFZ = 0;
831    
832 tim 682 cout << "Moving Molecules" << endl;
833     for(int i = 0; i < zconsMols.size(); i++) {
834    
835     if (states[i] == zcsMoving){
836 tim 693 zconsMols[i]->getCOM(COM);
837 tim 682 cout << "index: " << indexOfZConsMols[i] <<"\tcurrent zpos: " << COM[whichDirection] << endl;
838    
839     diff = COM[whichDirection] -zPos[i];
840    
841     harmonicU = 0.5 * kz[i] * diff * diff;
842 tim 693 info->lrPot += harmonicU;
843 tim 682
844 tim 693 harmonicF = - kz[i] * diff / zconsMols[i]->getNAtoms();
845     force[whichDirection] = harmonicF;
846     totalFZ += harmonicF;
847 tim 682
848     Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
849    
850     for(int j = 0; j < zconsMols[i]->getNAtoms(); j++)
851     movingZAtoms[j]->addFrc(force);
852     }
853    
854     }
855    
856 tim 693 force[0]= 0;
857     force[1]= 0;
858     force[2]= 0;
859     force[whichDirection] = -totalFZ /totNumOfUnconsAtoms;
860    
861     //modify the forces of unconstrained molecules
862     for(int i = 0; i < unconsMols.size(); i++){
863    
864     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
865    
866     for(int j = 0; j < unconsMols[i]->getNAtoms(); j++)
867     unconsAtoms[j]->addFrc(force);
868     }
869    
870 tim 682 }
871 tim 693
872     template<typename T> double ZConstraint<T>::calcCOMVel()
873     {
874     double MVzOfMovingMols_local;
875     double MVzOfMovingMols;
876     double totalMassOfMovingZMols_local;
877     double totalMassOfMovingZMols;
878     double COMvel[3];
879    
880     MVzOfMovingMols_local = 0;
881     totalMassOfMovingZMols_local = 0;
882    
883     for(int i =0; i < unconsMols.size(); i++){
884     unconsMols[i]->getCOMvel(COMvel);
885     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
886     }
887    
888     for(int i = 0; i < zconsMols.size(); i++){
889    
890     if (states[i] == zcsMoving){
891     zconsMols[i]->getCOMvel(COMvel);
892     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
893     totalMassOfMovingZMols_local += massOfZConsMols[i];
894     }
895    
896     }
897    
898     #ifndef IS_MPI
899     MVzOfMovingMols = MVzOfMovingMols_local;
900     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
901     #else
902     MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
903     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
904     #endif
905    
906     double vzOfMovingMols;
907     vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
908    
909     return vzOfMovingMols;
910     }
911    
912    
913     template<typename T> double ZConstraint<T>::calcCOMVel2()
914     {
915     double COMvel[3];
916     double tempMVz = 0;
917     int index;
918    
919     for(int i =0 ; i < nMols; i++){
920     index = isZConstraintMol(&molecules[i]);
921     if( index == -1){
922     molecules[i].getCOMvel(COMvel);
923     tempMVz += molecules[i].getTotalMass()*COMvel[whichDirection];
924     }
925     else if(states[i] == zcsMoving){
926     zconsMols[index]->getCOMvel(COMvel);
927     tempMVz += massOfZConsMols[index]*COMvel[whichDirection];
928     }
929     }
930    
931     return tempMVz /totalMassOfUncons;
932     }