ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 738
Committed: Tue Sep 2 14:30:12 2003 UTC (20 years, 10 months ago) by tim
File size: 31319 byte(s)
Log Message:
fix a bug at MPI version of PolicyByMass

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