ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 701
Committed: Wed Aug 20 14:34:04 2003 UTC (20 years, 10 months ago) by tim
File size: 31464 byte(s)
Log Message:
reformmating ZConstraint and fixe bug of error msg printing

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 676
529     T::calcForce(calcPot, calcStress);
530    
531 tim 699 if (checkZConsState()){
532 tim 696 zeroOutVel();
533 tim 701 forcePolicy->update();
534 tim 699 }
535 tim 693 zsys = calcZSys();
536     cout << "---------------------------------------------------------------------" <<endl;
537 tim 696 cout << "current time: " << info->getTime() << endl;
538 tim 701 cout << "center of mass at z: " << zsys << endl;
539 tim 696 //cout << "before calcForce, the COMVel of moving molecules is " << calcMovingMolsCOMVel() <<endl;
540     cout << "before calcForce, the COMVel of system is " << calcSysCOMVel() <<endl;
541 tim 676
542 tim 701 //cout << "before doZConstraintForce, totalForce is " << calcTotalForce() << endl;
543 tim 696
544 tim 676 //do zconstraint force;
545     if (haveFixedZMols())
546     this->doZconstraintForce();
547 tim 696
548 tim 676 //use harmonical poteintial to move the molecules to the specified positions
549     if (haveMovingZMols())
550 tim 693 this->doHarmonic();
551 tim 696
552 tim 701 //cout << "after doHarmonic, totalForce is " << calcTotalForce() << endl;
553 tim 696
554 tim 699 //write out forces and current positions of z-constraint molecules
555 tim 701 if(info->getTime() >= curZconsTime){
556     for(int i = 0; i < zconsMols.size(); i++){
557 tim 699 zconsMols[i]->getCOM(COM);
558 tim 701 curZPos[i] = COM[whichDirection];
559 tim 699
560 tim 701 //if the z-constraint molecule is still moving, just record its force
561     if(states[i] == zcsMoving){
562 tim 699 fz[i] = 0;
563 tim 701 Atom** movingZAtoms;
564     movingZAtoms = zconsMols[i]->getMyAtoms();
565     for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
566 tim 699 movingZAtoms[j]->getFrc(force);
567     fz[i] += force[whichDirection];
568 tim 701 }
569     }
570     }
571 tim 699 fzOut->writeFZ(info->getTime(), zconsMols.size(), indexOfZConsMols, fz, curZPos);
572 tim 701 curZconsTime += zconsTime;
573 tim 699 }
574 tim 701
575 tim 696 //cout << "after calcForce, the COMVel of moving molecules is " << calcMovingMolsCOMVel() <<endl;
576     cout << "after calcForce, the COMVel of system is " << calcSysCOMVel() <<endl;
577 tim 676 }
578 tim 701
579    
580     /**
581     *
582     */
583 tim 676
584     template<typename T> double ZConstraint<T>::calcZSys()
585 tim 658 {
586 tim 676 //calculate reference z coordinate for z-constraint molecules
587     double totalMass_local;
588     double totalMass;
589     double totalMZ_local;
590     double totalMZ;
591     double massOfCurMol;
592     double COM[3];
593 tim 701
594 tim 676 totalMass_local = 0;
595     totalMZ_local = 0;
596    
597     for(int i = 0; i < nMols; i++){
598     massOfCurMol = molecules[i].getTotalMass();
599     molecules[i].getCOM(COM);
600    
601     totalMass_local += massOfCurMol;
602     totalMZ_local += massOfCurMol * COM[whichDirection];
603 tim 696
604 tim 676 }
605 tim 696
606 tim 676
607     #ifdef IS_MPI
608 tim 701 MPI_Allreduce(&totalMass_local, &totalMass, 1,
609     MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
610     MPI_Allreduce(&totalMZ_local, &totalMZ, 1,
611     MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
612 tim 696 #else
613 tim 676 totalMass = totalMass_local;
614     totalMZ = totalMZ_local;
615 tim 696 #endif
616 mmeineke 671
617 tim 658 double zsys;
618 tim 676 zsys = totalMZ / totalMass;
619 tim 658
620 tim 676 return zsys;
621     }
622    
623     /**
624     *
625     */
626     template<typename T> void ZConstraint<T>::thermalize( void ){
627    
628     T::thermalize();
629     zeroOutVel();
630     }
631    
632     /**
633     *
634     */
635    
636     template<typename T> void ZConstraint<T>::zeroOutVel(){
637    
638     Atom** fixedZAtoms;
639     double COMvel[3];
640     double vel[3];
641 tim 701 double zSysCOMVel;
642 tim 693
643 tim 676 //zero out the velocities of center of mass of fixed z-constrained molecules
644    
645 tim 658 for(int i = 0; i < zconsMols.size(); i++){
646 tim 676
647 tim 701 if (states[i] == zcsFixed){
648 tim 676
649 tim 701 zconsMols[i]->getCOMvel(COMvel);
650     //cout << "before resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
651 tim 693
652 tim 676 fixedZAtoms = zconsMols[i]->getMyAtoms();
653 tim 701
654 tim 676 for(int j =0; j < zconsMols[i]->getNAtoms(); j++){
655     fixedZAtoms[j]->getVel(vel);
656 tim 701 vel[whichDirection] -= COMvel[whichDirection];
657     fixedZAtoms[j]->setVel(vel);
658 tim 676 }
659 tim 693
660 tim 701 zconsMols[i]->getCOMvel(COMvel);
661     //cout << "after resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl;
662 tim 676 }
663 tim 701
664 tim 658 }
665 tim 693
666 tim 701 //cout << "before resetting the COMVel of moving molecules is " << calcMovingMolsCOMVel() <<endl;
667 tim 699
668 tim 701 zSysCOMVel = calcSysCOMVel();
669 tim 699 #ifdef IS_MPI
670 tim 701 if(worldRank == 0){
671 tim 699 #endif
672 tim 701 cout << "before resetting the COMVel of sytem is " << zSysCOMVel << endl;
673 tim 699 #ifdef IS_MPI
674     }
675     #endif
676 tim 701
677 tim 676 // calculate the vz of center of mass of unconstrained molecules and moving z-constrained molecules
678     double MVzOfMovingMols_local;
679     double MVzOfMovingMols;
680     double totalMassOfMovingZMols_local;
681     double totalMassOfMovingZMols;
682    
683     MVzOfMovingMols_local = 0;
684     totalMassOfMovingZMols_local = 0;
685 tim 658
686 tim 676 for(int i =0; i < unconsMols.size(); i++){
687     unconsMols[i]->getCOMvel(COMvel);
688     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
689     }
690    
691 tim 693 for(int i = 0; i < zconsMols.size(); i++){
692 tim 676 if (states[i] == zcsMoving){
693     zconsMols[i]->getCOMvel(COMvel);
694     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
695 tim 701 totalMassOfMovingZMols_local += massOfZConsMols[i];
696 tim 676 }
697 tim 701
698 tim 676 }
699    
700     #ifndef IS_MPI
701     MVzOfMovingMols = MVzOfMovingMols_local;
702     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
703 tim 658 #else
704 tim 676 MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
705     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
706 tim 658 #endif
707    
708 tim 676 double vzOfMovingMols;
709     vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
710    
711     //modify the velocites of unconstrained molecules
712     Atom** unconsAtoms;
713 tim 658 for(int i = 0; i < unconsMols.size(); i++){
714 tim 676
715     unconsAtoms = unconsMols[i]->getMyAtoms();
716     for(int j = 0; j < unconsMols[i]->getNAtoms();j++){
717     unconsAtoms[j]->getVel(vel);
718     vel[whichDirection] -= vzOfMovingMols;
719     unconsAtoms[j]->setVel(vel);
720     }
721    
722     }
723    
724     //modify the velocities of moving z-constrained molecuels
725     Atom** movingZAtoms;
726 tim 693 for(int i = 0; i < zconsMols.size(); i++){
727 tim 676
728     if (states[i] ==zcsMoving){
729    
730     movingZAtoms = zconsMols[i]->getMyAtoms();
731 tim 701 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
732 tim 676 movingZAtoms[j]->getVel(vel);
733     vel[whichDirection] -= vzOfMovingMols;
734 tim 701 movingZAtoms[j]->setVel(vel);
735     }
736    
737 tim 693 }
738 tim 676
739 tim 693 }
740 tim 676
741 tim 701
742     zSysCOMVel = calcSysCOMVel();
743 tim 699 #ifdef IS_MPI
744 tim 701 if(worldRank == 0){
745 tim 699 #endif
746 tim 701 cout << "after resetting the COMVel of moving molecules is " << zSysCOMVel << endl;
747 tim 699 #ifdef IS_MPI
748     }
749     #endif
750 tim 693
751 tim 676 }
752    
753 tim 701 /**
754     *
755     */
756    
757 tim 676 template<typename T> void ZConstraint<T>::doZconstraintForce(){
758    
759     Atom** zconsAtoms;
760     double totalFZ;
761     double totalFZ_local;
762     double COMvel[3];
763     double COM[3];
764     double force[3];
765    
766    
767 tim 696
768 tim 701 //constrain the molecules which do not reach the specified positions
769 tim 676
770     //Zero Out the force of z-contrained molecules
771     totalFZ_local = 0;
772    
773     //calculate the total z-contrained force of fixed z-contrained molecules
774 tim 699
775 tim 676 for(int i = 0; i < zconsMols.size(); i++){
776 tim 701
777 tim 676 if (states[i] == zcsFixed){
778 tim 701
779 tim 676 zconsMols[i]->getCOM(COM);
780     zconsAtoms = zconsMols[i]->getMyAtoms();
781    
782     fz[i] = 0;
783     for(int j =0; j < zconsMols[i]->getNAtoms(); j++) {
784     zconsAtoms[j]->getFrc(force);
785     fz[i] += force[whichDirection];
786 tim 701 }
787 tim 676 totalFZ_local += fz[i];
788    
789 tim 701 cout << "Fixed Molecule --\tindex: " << indexOfZConsMols[i]
790     <<"\tcurrent zpos: " << COM[whichDirection]
791     << "\tcurrent fz: " <<fz[i] << endl;
792 tim 676
793     }
794 tim 701
795 tim 676 }
796 tim 699
797     //calculate total z-constraint force
798     #ifdef IS_MPI
799     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
800     #else
801     totalFZ = totalFZ_local;
802     #endif
803    
804 tim 701
805 tim 696 // apply negative to fixed z-constrained molecues;
806     force[0]= 0;
807     force[1]= 0;
808     force[2]= 0;
809 tim 676
810 tim 696 for(int i = 0; i < zconsMols.size(); i++){
811    
812     if (states[i] == zcsFixed){
813 tim 701
814 tim 696 int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms();
815     zconsAtoms = zconsMols[i]->getMyAtoms();
816    
817     for(int j =0; j < nAtomOfCurZConsMol; j++) {
818 tim 701 force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol;
819 tim 699 //force[whichDirection] = - forcePolicy->getZFOfFixedZMols(zconsMols[i], zconsAtoms[j], fz[i]);
820 tim 696 zconsAtoms[j]->addFrc(force);
821     }
822 tim 701
823 tim 696 }
824 tim 701
825 tim 696 }
826    
827 tim 699 //cout << "after zero out z-constraint force on fixed z-constraint molecuels "
828 tim 701 // << "total force is " << calcTotalForce() << endl;
829 tim 699
830 tim 676 //calculate the number of atoms of moving z-constrained molecules
831 tim 696 int nMovingZAtoms_local;
832     int nMovingZAtoms;
833 tim 701
834 tim 696 nMovingZAtoms_local = 0;
835 tim 693 for(int i = 0; i < zconsMols.size(); i++)
836 tim 676 if(states[i] == zcsMoving)
837 tim 701 nMovingZAtoms_local += zconsMols[i]->getNAtoms();
838 tim 693
839 tim 658 #ifdef IS_MPI
840 tim 701 MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1,
841     MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
842 tim 658 #else
843 tim 696 nMovingZAtoms = nMovingZAtoms_local;
844 tim 676 #endif
845    
846     force[0]= 0;
847     force[1]= 0;
848     force[2]= 0;
849    
850 tim 693 //modify the forces of unconstrained molecules
851 tim 676 for(int i = 0; i < unconsMols.size(); i++){
852    
853     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
854    
855 tim 699 for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){
856     force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
857     //force[whichDirection] = forcePolicy->getZFOfMovingMols(unconsAtoms[j],totalFZ);
858 tim 676 unconsAtoms[j]->addFrc(force);
859 tim 699 }
860 tim 676
861     }
862    
863 tim 693 //modify the forces of moving z-constrained molecules
864 tim 676 for(int i = 0; i < zconsMols.size(); i++) {
865 tim 696 if (states[i] == zcsMoving){
866 tim 701
867 tim 696 Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
868 tim 676
869 tim 699 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
870     force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
871     //force[whichDirection] = forcePolicy->getZFOfMovingMols(movingZAtoms[j],totalFZ);
872 tim 696 movingZAtoms[j]->addFrc(force);
873 tim 699 }
874 tim 696 }
875 tim 676 }
876    
877 tim 699 //cout << "after substracting z-constraint force from moving molecuels "
878 tim 701 // << "total force is " << calcTotalForce() << endl;
879 tim 699
880 tim 676 }
881    
882 tim 701 /**
883     *
884     *
885     */
886    
887     template<typename T> void ZConstraint<T>::doHarmonic(){
888     double force[3];
889     double harmonicU;
890     double harmonicF;
891     double COM[3];
892     double diff;
893     double totalFZ_local;
894     double totalFZ;
895    
896     force[0] = 0;
897     force[1] = 0;
898     force[2] = 0;
899    
900     totalFZ_local = 0;
901    
902     for(int i = 0; i < zconsMols.size(); i++) {
903    
904     if (states[i] == zcsMoving){
905     zconsMols[i]->getCOM(COM);
906     cout << "Moving Molecule --\tindex: " << indexOfZConsMols[i] <<"\tcurrent zpos: " << COM[whichDirection] << endl;
907    
908     diff = COM[whichDirection] -zPos[i];
909    
910     harmonicU = 0.5 * kz[i] * diff * diff;
911     info->lrPot += harmonicU;
912    
913     harmonicF = - kz[i] * diff;
914     totalFZ_local += harmonicF;
915    
916     //adjust force
917    
918     Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
919    
920     for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
921     force[whichDirection] = harmonicF / zconsMols[i]->getNAtoms();
922     //force[whichDirection] = forcePolicy->getHFOfFixedZMols(zconsMols[i], movingZAtoms[j], harmonicF);
923     movingZAtoms[j]->addFrc(force);
924     }
925     }
926    
927     }
928    
929     #ifndef IS_MPI
930     totalFZ = totalFZ_local;
931     #else
932     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
933     #endif
934    
935     force[0]= 0;
936     force[1]= 0;
937     force[2]= 0;
938    
939     //modify the forces of unconstrained molecules
940     for(int i = 0; i < unconsMols.size(); i++){
941    
942     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
943    
944     for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){
945     force[whichDirection] = - totalFZ /totNumOfUnconsAtoms;
946     //force[whichDirection] = - forcePolicy->getHFOfUnconsMols(unconsAtoms[j], totalFZ);
947     unconsAtoms[j]->addFrc(force);
948     }
949     }
950    
951     }
952    
953     /**
954     *
955     */
956    
957 tim 676 template<typename T> bool ZConstraint<T>::checkZConsState(){
958     double COM[3];
959     double diff;
960 tim 658
961 tim 699 int changed_local;
962     int changed;
963 tim 701
964 tim 699 changed_local = 0;
965 tim 676
966     for(int i =0; i < zconsMols.size(); i++){
967    
968 tim 658 zconsMols[i]->getCOM(COM);
969 tim 682 diff = fabs(COM[whichDirection] - zPos[i]);
970     if ( diff <= zconsTol && states[i] == zcsMoving){
971 tim 676 states[i] = zcsFixed;
972 tim 701 changed_local = 1;
973 tim 676 }
974 tim 682 else if ( diff > zconsTol && states[i] == zcsFixed){
975 tim 676 states[i] = zcsMoving;
976 tim 701 changed_local = 1;
977 tim 676 }
978    
979 tim 658 }
980    
981 tim 699 #ifndef IS_MPI
982     changed =changed_local;
983     #else
984     MPI_Allreduce(&changed_local, &changed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
985     #endif
986    
987     return changed > 0 ? true : false;
988 tim 658 }
989 tim 676
990     template<typename T> bool ZConstraint<T>::haveFixedZMols(){
991 tim 699
992     int havingFixed_local;
993     int havingFixed;
994    
995     havingFixed_local = 0;
996    
997 tim 676 for(int i = 0; i < zconsMols.size(); i++)
998 tim 699 if (states[i] == zcsFixed){
999     havingFixed_local = 1;
1000 tim 701 break;
1001 tim 699 }
1002 tim 676
1003 tim 699 #ifndef IS_MPI
1004     havingFixed = havingFixed_local;
1005     #else
1006     MPI_Allreduce(&havingFixed_local, &havingFixed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1007     #endif
1008    
1009     return havingFixed > 0 ? true : false;
1010 tim 676 }
1011    
1012    
1013     /**
1014     *
1015     */
1016     template<typename T> bool ZConstraint<T>::haveMovingZMols(){
1017 tim 699
1018     int havingMoving_local;
1019     int havingMoving;
1020    
1021     havingMoving_local = 0;
1022    
1023 tim 676 for(int i = 0; i < zconsMols.size(); i++)
1024 tim 699 if (states[i] == zcsMoving){
1025     havingMoving_local = 1;
1026 tim 701 break;
1027 tim 699 }
1028 tim 676
1029 tim 699 #ifndef IS_MPI
1030     havingMoving = havingMoving_local;
1031     #else
1032     MPI_Allreduce(&havingMoving_local, &havingMoving, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1033     #endif
1034    
1035     return havingMoving > 0 ? true : false;
1036 tim 676
1037 tim 682 }
1038    
1039     /**
1040 tim 701 *
1041     */
1042 tim 682
1043 tim 696 template<typename T> double ZConstraint<T>::calcMovingMolsCOMVel()
1044 tim 693 {
1045     double MVzOfMovingMols_local;
1046     double MVzOfMovingMols;
1047     double totalMassOfMovingZMols_local;
1048     double totalMassOfMovingZMols;
1049     double COMvel[3];
1050    
1051     MVzOfMovingMols_local = 0;
1052     totalMassOfMovingZMols_local = 0;
1053    
1054     for(int i =0; i < unconsMols.size(); i++){
1055     unconsMols[i]->getCOMvel(COMvel);
1056     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
1057     }
1058    
1059     for(int i = 0; i < zconsMols.size(); i++){
1060    
1061     if (states[i] == zcsMoving){
1062     zconsMols[i]->getCOMvel(COMvel);
1063     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
1064 tim 701 totalMassOfMovingZMols_local += massOfZConsMols[i];
1065 tim 693 }
1066 tim 701
1067 tim 693 }
1068    
1069     #ifndef IS_MPI
1070     MVzOfMovingMols = MVzOfMovingMols_local;
1071     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
1072     #else
1073     MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1074     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1075     #endif
1076    
1077     double vzOfMovingMols;
1078     vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
1079    
1080     return vzOfMovingMols;
1081     }
1082    
1083 tim 701 /**
1084     *
1085     */
1086 tim 693
1087 tim 696 template<typename T> double ZConstraint<T>::calcSysCOMVel()
1088 tim 693 {
1089     double COMvel[3];
1090 tim 699 double tempMVz_local;
1091     double tempMVz;
1092     double massOfZCons_local;
1093     double massOfZCons;
1094    
1095    
1096     tempMVz_local = 0;
1097    
1098 tim 693 for(int i =0 ; i < nMols; i++){
1099 tim 696 molecules[i].getCOMvel(COMvel);
1100 tim 701 tempMVz_local += molecules[i].getTotalMass()*COMvel[whichDirection];
1101 tim 693 }
1102 tim 696
1103     massOfZCons_local = 0;
1104 tim 701
1105 tim 696 for(int i = 0; i < massOfZConsMols.size(); i++){
1106     massOfZCons_local += massOfZConsMols[i];
1107     }
1108     #ifndef IS_MPI
1109     massOfZCons = massOfZCons_local;
1110 tim 699 tempMVz = tempMVz_local;
1111 tim 696 #else
1112     MPI_Allreduce(&massOfZCons_local, &massOfZCons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1113 tim 699 MPI_Allreduce(&tempMVz_local, &tempMVz, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1114 tim 696 #endif
1115    
1116     return tempMVz /(totalMassOfUncons + massOfZCons);
1117 tim 693 }
1118 tim 696
1119 tim 701 /**
1120     *
1121     */
1122    
1123 tim 696 template<typename T> double ZConstraint<T>::calcTotalForce(){
1124    
1125     double force[3];
1126     double totalForce_local;
1127     double totalForce;
1128    
1129     totalForce_local = 0;
1130    
1131     for(int i = 0; i < nAtoms; i++){
1132     atoms[i]->getFrc(force);
1133     totalForce_local += force[whichDirection];
1134     }
1135    
1136     #ifndef IS_MPI
1137     totalForce = totalForce_local;
1138     #else
1139     MPI_Allreduce(&totalForce_local, &totalForce, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1140     #endif
1141    
1142     return totalForce;
1143    
1144     }
1145 tim 699
1146     /**
1147     *
1148     */
1149    
1150     template<typename T> void ZConstraint<T>::PolicyByNumber::update(){
1151     //calculate the number of atoms of moving z-constrained molecules
1152     int nMovingZAtoms_local;
1153     int nMovingZAtoms;
1154 tim 701
1155 tim 699 nMovingZAtoms_local = 0;
1156     for(int i = 0; i < (zconsIntegrator->zconsMols).size(); i++)
1157     if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1158 tim 701 nMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getNAtoms();
1159 tim 699
1160     #ifdef IS_MPI
1161     MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
1162     #else
1163     nMovingZAtoms = nMovingZAtoms_local;
1164     #endif
1165     totNumOfMovingAtoms = nMovingZAtoms + zconsIntegrator->totNumOfUnconsAtoms;
1166     }
1167    
1168 tim 701 template<typename T>double ZConstraint<T>::PolicyByNumber::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1169 tim 699 return totalForce / mol->getNAtoms();
1170     }
1171    
1172     template<typename T> double ZConstraint<T>::PolicyByNumber::getZFOfMovingMols(Atom* atom, double totalForce){
1173     return totalForce / totNumOfMovingAtoms;
1174     }
1175    
1176     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1177     return totalForce / mol->getNAtoms();
1178     }
1179    
1180     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfUnconsMols(Atom* atom, double totalForce){
1181     return totalForce / zconsIntegrator->totNumOfUnconsAtoms;
1182     }
1183    
1184     /**
1185     *
1186     */
1187    
1188     template<typename T> void ZConstraint<T>::PolicyByMass::update(){
1189     //calculate the number of atoms of moving z-constrained molecules
1190     double massOfMovingZAtoms_local;
1191     double massOfMovingZAtoms;
1192 tim 701
1193 tim 699 massOfMovingZAtoms_local = 0;
1194     for(int i = 0; i < (zconsIntegrator->zconsMols).size(); i++)
1195     if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1196 tim 701 massOfMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getTotalMass();
1197 tim 699
1198     #ifdef IS_MPI
1199     MPI_Allreduce(&massOfMovingZAtoms_local, &massOfMovingZAtoms, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1200     #else
1201     massOfMovingZAtoms = massOfMovingZAtoms_local;
1202     #endif
1203     totMassOfMovingAtoms = massOfMovingZAtoms_local + zconsIntegrator->totalMassOfUncons;
1204     }
1205    
1206     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1207     return totalForce * atom->getMass() / mol->getTotalMass();
1208     }
1209    
1210     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfMovingMols( Atom* atom, double totalForce){
1211     return totalForce * atom->getMass() / totMassOfMovingAtoms;
1212     }
1213    
1214     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1215     return totalForce * atom->getMass() / mol->getTotalMass();
1216     }
1217    
1218     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfUnconsMols(Atom* atom, double totalForce){
1219     return totalForce * atom->getMass() / zconsIntegrator->totalMassOfUncons;
1220     }
1221