ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 702
Committed: Wed Aug 20 14:50:32 2003 UTC (20 years, 10 months ago) by tim
File size: 31314 byte(s)
Log Message:
*** empty log message ***

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