ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 723
Committed: Tue Aug 26 20:12:51 2003 UTC (20 years, 10 months ago) by mmeineke
File size: 32216 byte(s)
Log Message:
added define statemewnt to Statwriter and Dumpwriter to handle files larger than 2 gb.

commented out some print statements in Zconstraint

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