ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 696
Committed: Thu Aug 14 16:16:39 2003 UTC (20 years, 10 months ago) by tim
File size: 23846 byte(s)
Log Message:
Stable ZConstraint with average force substraction strategy

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 696 */
460 tim 676 template<typename T> void ZConstraint<T>::calcForce(int calcPot, int calcStress){
461 tim 693 double zsys;
462 tim 676
463     T::calcForce(calcPot, calcStress);
464    
465     if (checkZConsState())
466 tim 696 zeroOutVel();
467 tim 693
468     zsys = calcZSys();
469     cout << "---------------------------------------------------------------------" <<endl;
470 tim 696 cout << "current time: " << info->getTime() << endl;
471     cout << "center of mass at z: " << zsys << endl;
472     //cout << "before calcForce, the COMVel of moving molecules is " << calcMovingMolsCOMVel() <<endl;
473     cout << "before calcForce, the COMVel of system is " << calcSysCOMVel() <<endl;
474 tim 676
475 tim 696 //cout << "before doZConstraintForce, totalForce is " << calcTotalForce() << endl;
476    
477 tim 676 //do zconstraint force;
478     if (haveFixedZMols())
479     this->doZconstraintForce();
480 tim 696
481 tim 676 //use harmonical poteintial to move the molecules to the specified positions
482     if (haveMovingZMols())
483 tim 693 this->doHarmonic();
484 tim 696
485     //cout << "after doHarmonic, totalForce is " << calcTotalForce() << endl;
486    
487 tim 676 fzOut->writeFZ(info->getTime(), zconsMols.size(),indexOfZConsMols, fz);
488 tim 696 //cout << "after calcForce, the COMVel of moving molecules is " << calcMovingMolsCOMVel() <<endl;
489     cout << "after calcForce, the COMVel of system is " << calcSysCOMVel() <<endl;
490 tim 676 }
491    
492     template<typename T> double ZConstraint<T>::calcZSys()
493 tim 658 {
494 tim 676 //calculate reference z coordinate for z-constraint molecules
495     double totalMass_local;
496     double totalMass;
497     double totalMZ_local;
498     double totalMZ;
499     double massOfCurMol;
500     double COM[3];
501 tim 696
502 tim 676 totalMass_local = 0;
503     totalMZ_local = 0;
504    
505     for(int i = 0; i < nMols; i++){
506     massOfCurMol = molecules[i].getTotalMass();
507     molecules[i].getCOM(COM);
508    
509     totalMass_local += massOfCurMol;
510     totalMZ_local += massOfCurMol * COM[whichDirection];
511 tim 696
512 tim 676 }
513 tim 696
514 tim 676
515     #ifdef IS_MPI
516     MPI_Allreduce(&totalMass_local, &totalMass, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
517     MPI_Allreduce(&totalMZ_local, &totalMZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
518 tim 696 #else
519 tim 676 totalMass = totalMass_local;
520     totalMZ = totalMZ_local;
521 tim 696 #endif
522 mmeineke 671
523 tim 658 double zsys;
524 tim 676 zsys = totalMZ / totalMass;
525 tim 658
526 tim 676 return zsys;
527     }
528    
529     /**
530     *
531     */
532     template<typename T> void ZConstraint<T>::thermalize( void ){
533    
534     T::thermalize();
535     zeroOutVel();
536     }
537    
538     /**
539     *
540     *
541     *
542     */
543    
544     template<typename T> void ZConstraint<T>::zeroOutVel(){
545    
546     Atom** fixedZAtoms;
547     double COMvel[3];
548     double vel[3];
549 tim 693
550 tim 676 //zero out the velocities of center of mass of fixed z-constrained molecules
551    
552 tim 658 for(int i = 0; i < zconsMols.size(); i++){
553 tim 676
554     if (states[i] == zcsFixed){
555    
556 tim 693 zconsMols[i]->getCOMvel(COMvel);
557 tim 696 //cout << "before resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
558 tim 693
559 tim 676 fixedZAtoms = zconsMols[i]->getMyAtoms();
560    
561     for(int j =0; j < zconsMols[i]->getNAtoms(); j++){
562     fixedZAtoms[j]->getVel(vel);
563 tim 693 vel[whichDirection] -= COMvel[whichDirection];
564     fixedZAtoms[j]->setVel(vel);
565 tim 676 }
566 tim 693
567     zconsMols[i]->getCOMvel(COMvel);
568 tim 696 //cout << "after resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
569 tim 676 }
570    
571 tim 658 }
572 tim 693
573 tim 696 //cout << "before resetting the COMVel of moving molecules is " << calcMovingMolsCOMVel() <<endl;
574     cout << "before resetting the COMVel of sytem is " << calcSysCOMVel() << endl;
575 tim 693
576 tim 676 // calculate the vz of center of mass of unconstrained molecules and moving z-constrained molecules
577     double MVzOfMovingMols_local;
578     double MVzOfMovingMols;
579     double totalMassOfMovingZMols_local;
580     double totalMassOfMovingZMols;
581    
582     MVzOfMovingMols_local = 0;
583     totalMassOfMovingZMols_local = 0;
584 tim 658
585 tim 676 for(int i =0; i < unconsMols.size(); i++){
586     unconsMols[i]->getCOMvel(COMvel);
587     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
588     }
589    
590 tim 693 for(int i = 0; i < zconsMols.size(); i++){
591 tim 676 if (states[i] == zcsMoving){
592     zconsMols[i]->getCOMvel(COMvel);
593     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
594     totalMassOfMovingZMols_local += massOfZConsMols[i];
595     }
596    
597     }
598    
599     #ifndef IS_MPI
600     MVzOfMovingMols = MVzOfMovingMols_local;
601     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
602 tim 658 #else
603 tim 676 MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
604     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
605 tim 658 #endif
606    
607 tim 676 double vzOfMovingMols;
608     vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
609    
610     //modify the velocites of unconstrained molecules
611     Atom** unconsAtoms;
612 tim 658 for(int i = 0; i < unconsMols.size(); i++){
613 tim 676
614     unconsAtoms = unconsMols[i]->getMyAtoms();
615     for(int j = 0; j < unconsMols[i]->getNAtoms();j++){
616     unconsAtoms[j]->getVel(vel);
617     vel[whichDirection] -= vzOfMovingMols;
618     unconsAtoms[j]->setVel(vel);
619     }
620    
621     }
622    
623     //modify the velocities of moving z-constrained molecuels
624     Atom** movingZAtoms;
625 tim 693 for(int i = 0; i < zconsMols.size(); i++){
626 tim 676
627     if (states[i] ==zcsMoving){
628    
629     movingZAtoms = zconsMols[i]->getMyAtoms();
630 tim 693 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
631 tim 676 movingZAtoms[j]->getVel(vel);
632     vel[whichDirection] -= vzOfMovingMols;
633 tim 693 movingZAtoms[j]->setVel(vel);
634     }
635 tim 676
636 tim 693 }
637 tim 676
638 tim 693 }
639 tim 676
640 tim 696 cout << "after resetting the COMVel of moving molecules is " << calcSysCOMVel() <<endl;
641 tim 693
642 tim 676 }
643    
644     template<typename T> void ZConstraint<T>::doZconstraintForce(){
645    
646     Atom** zconsAtoms;
647     double totalFZ;
648     double totalFZ_local;
649     double COMvel[3];
650     double COM[3];
651     double force[3];
652    
653    
654 tim 696
655 tim 676 //constrain the molecules which do not reach the specified positions
656    
657     //Zero Out the force of z-contrained molecules
658     totalFZ_local = 0;
659    
660     //calculate the total z-contrained force of fixed z-contrained molecules
661 tim 682 cout << "Fixed Molecules" << endl;
662 tim 676 for(int i = 0; i < zconsMols.size(); i++){
663    
664     if (states[i] == zcsFixed){
665    
666     zconsMols[i]->getCOM(COM);
667     zconsAtoms = zconsMols[i]->getMyAtoms();
668    
669     fz[i] = 0;
670     for(int j =0; j < zconsMols[i]->getNAtoms(); j++) {
671     zconsAtoms[j]->getFrc(force);
672     fz[i] += force[whichDirection];
673     }
674     totalFZ_local += fz[i];
675    
676 tim 696 cout << "index: " << indexOfZConsMols[i]
677     <<"\tcurrent zpos: " << COM[whichDirection]
678     << "\tcurrent fz: " <<fz[i] << endl;
679 tim 676
680     }
681    
682     }
683 tim 696
684     // apply negative to fixed z-constrained molecues;
685     force[0]= 0;
686     force[1]= 0;
687     force[2]= 0;
688 tim 676
689 tim 696 for(int i = 0; i < zconsMols.size(); i++){
690    
691     if (states[i] == zcsFixed){
692    
693     int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms();
694     zconsAtoms = zconsMols[i]->getMyAtoms();
695    
696     for(int j =0; j < nAtomOfCurZConsMol; j++) {
697     force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol;
698     zconsAtoms[j]->addFrc(force);
699     }
700    
701     }
702    
703     }
704    
705     cout << "after zero out z-constraint force on fixed z-constraint molecuels "
706     << "total force is " << calcTotalForce() << endl;
707 tim 676 //calculate the number of atoms of moving z-constrained molecules
708 tim 696 int nMovingZAtoms_local;
709     int nMovingZAtoms;
710    
711     nMovingZAtoms_local = 0;
712 tim 693 for(int i = 0; i < zconsMols.size(); i++)
713 tim 676 if(states[i] == zcsMoving)
714 tim 696 nMovingZAtoms_local += zconsMols[i]->getNAtoms();
715 tim 693
716 tim 658 #ifdef IS_MPI
717 tim 676 MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
718 tim 696 MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
719 tim 658 #else
720 tim 676 totalFZ = totalFZ_local;
721 tim 696 nMovingZAtoms = nMovingZAtoms_local;
722 tim 676 #endif
723    
724     force[0]= 0;
725     force[1]= 0;
726     force[2]= 0;
727 tim 696 force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
728 tim 676
729 tim 693 //modify the forces of unconstrained molecules
730 tim 696 int accessCount = 0;
731 tim 676 for(int i = 0; i < unconsMols.size(); i++){
732    
733     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
734    
735     for(int j = 0; j < unconsMols[i]->getNAtoms(); j++)
736     unconsAtoms[j]->addFrc(force);
737    
738     }
739    
740 tim 693 //modify the forces of moving z-constrained molecules
741 tim 676 for(int i = 0; i < zconsMols.size(); i++) {
742 tim 696 if (states[i] == zcsMoving){
743 tim 676
744 tim 696 Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
745 tim 676
746 tim 696 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++)
747     movingZAtoms[j]->addFrc(force);
748     }
749 tim 676 }
750    
751 tim 696 cout << "after substracting z-constraint force from moving molecuels "
752     << "total force is " << calcTotalForce() << endl;
753 tim 676
754     }
755    
756     template<typename T> bool ZConstraint<T>::checkZConsState(){
757     double COM[3];
758     double diff;
759 tim 658
760 tim 676 bool changed;
761    
762     changed = false;
763    
764     for(int i =0; i < zconsMols.size(); i++){
765    
766 tim 658 zconsMols[i]->getCOM(COM);
767 tim 682 diff = fabs(COM[whichDirection] - zPos[i]);
768     if ( diff <= zconsTol && states[i] == zcsMoving){
769 tim 676 states[i] = zcsFixed;
770     changed = true;
771     }
772 tim 682 else if ( diff > zconsTol && states[i] == zcsFixed){
773 tim 676 states[i] = zcsMoving;
774     changed = true;
775     }
776    
777 tim 658 }
778    
779 tim 676 return changed;
780 tim 658 }
781 tim 676
782     template<typename T> bool ZConstraint<T>::haveFixedZMols(){
783     for(int i = 0; i < zconsMols.size(); i++)
784     if (states[i] == zcsFixed)
785     return true;
786    
787     return false;
788     }
789    
790    
791     /**
792     *
793     */
794     template<typename T> bool ZConstraint<T>::haveMovingZMols(){
795     for(int i = 0; i < zconsMols.size(); i++)
796     if (states[i] == zcsMoving)
797     return true;
798    
799     return false;
800    
801 tim 682 }
802    
803     /**
804     *
805     *
806     */
807    
808     template<typename T> void ZConstraint<T>::doHarmonic(){
809     double force[3];
810     double harmonicU;
811 tim 693 double harmonicF;
812 tim 682 double COM[3];
813     double diff;
814 tim 693 double totalFZ;
815 tim 682
816     force[0] = 0;
817     force[1] = 0;
818     force[2] = 0;
819    
820 tim 693 totalFZ = 0;
821    
822 tim 682 cout << "Moving Molecules" << endl;
823     for(int i = 0; i < zconsMols.size(); i++) {
824    
825     if (states[i] == zcsMoving){
826 tim 693 zconsMols[i]->getCOM(COM);
827 tim 682 cout << "index: " << indexOfZConsMols[i] <<"\tcurrent zpos: " << COM[whichDirection] << endl;
828    
829     diff = COM[whichDirection] -zPos[i];
830    
831     harmonicU = 0.5 * kz[i] * diff * diff;
832 tim 693 info->lrPot += harmonicU;
833 tim 682
834 tim 696 harmonicF = - kz[i] * diff;
835 tim 693 totalFZ += harmonicF;
836 tim 696
837     //
838     force[whichDirection] = harmonicF / zconsMols[i]->getNAtoms();
839 tim 682
840     Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
841    
842     for(int j = 0; j < zconsMols[i]->getNAtoms(); j++)
843     movingZAtoms[j]->addFrc(force);
844     }
845    
846     }
847 tim 696
848 tim 693 force[0]= 0;
849     force[1]= 0;
850     force[2]= 0;
851     force[whichDirection] = -totalFZ /totNumOfUnconsAtoms;
852    
853     //modify the forces of unconstrained molecules
854     for(int i = 0; i < unconsMols.size(); i++){
855    
856     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
857    
858     for(int j = 0; j < unconsMols[i]->getNAtoms(); j++)
859     unconsAtoms[j]->addFrc(force);
860     }
861    
862 tim 682 }
863 tim 693
864 tim 696 template<typename T> double ZConstraint<T>::calcMovingMolsCOMVel()
865 tim 693 {
866     double MVzOfMovingMols_local;
867     double MVzOfMovingMols;
868     double totalMassOfMovingZMols_local;
869     double totalMassOfMovingZMols;
870     double COMvel[3];
871    
872     MVzOfMovingMols_local = 0;
873     totalMassOfMovingZMols_local = 0;
874    
875     for(int i =0; i < unconsMols.size(); i++){
876     unconsMols[i]->getCOMvel(COMvel);
877     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
878     }
879    
880     for(int i = 0; i < zconsMols.size(); i++){
881    
882     if (states[i] == zcsMoving){
883     zconsMols[i]->getCOMvel(COMvel);
884     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
885     totalMassOfMovingZMols_local += massOfZConsMols[i];
886     }
887    
888     }
889    
890     #ifndef IS_MPI
891     MVzOfMovingMols = MVzOfMovingMols_local;
892     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
893     #else
894     MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
895     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
896     #endif
897    
898     double vzOfMovingMols;
899     vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
900    
901     return vzOfMovingMols;
902     }
903    
904    
905 tim 696 template<typename T> double ZConstraint<T>::calcSysCOMVel()
906 tim 693 {
907     double COMvel[3];
908     double tempMVz = 0;
909    
910     for(int i =0 ; i < nMols; i++){
911 tim 696 molecules[i].getCOMvel(COMvel);
912     tempMVz += molecules[i].getTotalMass()*COMvel[whichDirection];
913 tim 693 }
914 tim 696
915     double massOfZCons_local;
916     double massOfZCons;
917    
918     massOfZCons_local = 0;
919 tim 693
920 tim 696 for(int i = 0; i < massOfZConsMols.size(); i++){
921     massOfZCons_local += massOfZConsMols[i];
922     }
923     #ifndef IS_MPI
924     massOfZCons = massOfZCons_local;
925     #else
926     MPI_Allreduce(&massOfZCons_local, &massOfZCons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
927     #endif
928    
929     return tempMVz /(totalMassOfUncons + massOfZCons);
930 tim 693 }
931 tim 696
932     template<typename T> double ZConstraint<T>::calcTotalForce(){
933    
934     double force[3];
935     double totalForce_local;
936     double totalForce;
937    
938     totalForce_local = 0;
939    
940     for(int i = 0; i < nAtoms; i++){
941     atoms[i]->getFrc(force);
942     totalForce_local += force[whichDirection];
943     }
944    
945     #ifndef IS_MPI
946     totalForce = totalForce_local;
947     #else
948     MPI_Allreduce(&totalForce_local, &totalForce, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
949     #endif
950    
951     return totalForce;
952    
953     }