ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 726
Committed: Tue Aug 26 20:37:30 2003 UTC (20 years, 10 months ago) by tim
File size: 32141 byte(s)
Log Message:
set default force substraction policy to 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 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 tim 726 "PolicyByMass is used\n");
36 tim 699 painCave.isFatal = 0;
37     simError();
38    
39 tim 726 forcePolicy = (ForceSubstractionPolicy*) 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 726 forcePolicy = (ForceSubstractionPolicy*) new PolicyByMass(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 tim 726 //cout << "Fixed Molecule\tindex: " << indexOfZConsMols[i]
829     // <<"\tcurrent zpos: " << COM[whichDirection]
830     // << "\tcurrent fz: " <<fz[i] << endl;
831 tim 676
832 tim 726
833 tim 676 }
834 tim 701
835 tim 676 }
836 tim 699
837     //calculate total z-constraint force
838     #ifdef IS_MPI
839     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
840     #else
841     totalFZ = totalFZ_local;
842     #endif
843    
844 tim 701
845 tim 696 // apply negative to fixed z-constrained molecues;
846     force[0]= 0;
847     force[1]= 0;
848     force[2]= 0;
849 tim 676
850 tim 696 for(int i = 0; i < zconsMols.size(); i++){
851    
852     if (states[i] == zcsFixed){
853 tim 701
854 tim 696 int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms();
855     zconsAtoms = zconsMols[i]->getMyAtoms();
856    
857     for(int j =0; j < nAtomOfCurZConsMol; j++) {
858 tim 726 //force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol;
859     force[whichDirection] = - forcePolicy->getZFOfFixedZMols(zconsMols[i], zconsAtoms[j], fz[i]);
860 tim 696 zconsAtoms[j]->addFrc(force);
861     }
862 tim 701
863 tim 696 }
864 tim 701
865 tim 696 }
866    
867 mmeineke 711 // cout << "after zero out z-constraint force on fixed z-constraint molecuels "
868     // << "total force is " << calcTotalForce() << endl;
869 tim 699
870 tim 676 //calculate the number of atoms of moving z-constrained molecules
871 tim 696 int nMovingZAtoms_local;
872     int nMovingZAtoms;
873 tim 701
874 tim 696 nMovingZAtoms_local = 0;
875 tim 693 for(int i = 0; i < zconsMols.size(); i++)
876 tim 676 if(states[i] == zcsMoving)
877 tim 701 nMovingZAtoms_local += zconsMols[i]->getNAtoms();
878 tim 693
879 tim 658 #ifdef IS_MPI
880 tim 701 MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1,
881     MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
882 tim 658 #else
883 tim 696 nMovingZAtoms = nMovingZAtoms_local;
884 tim 676 #endif
885    
886     force[0]= 0;
887     force[1]= 0;
888     force[2]= 0;
889    
890 tim 693 //modify the forces of unconstrained molecules
891 tim 676 for(int i = 0; i < unconsMols.size(); i++){
892    
893     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
894    
895 tim 699 for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){
896 tim 726 //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
897     force[whichDirection] = forcePolicy->getZFOfMovingMols(unconsAtoms[j],totalFZ);
898 tim 676 unconsAtoms[j]->addFrc(force);
899 tim 699 }
900 tim 676
901     }
902    
903 tim 693 //modify the forces of moving z-constrained molecules
904 tim 676 for(int i = 0; i < zconsMols.size(); i++) {
905 tim 696 if (states[i] == zcsMoving){
906 tim 701
907 tim 696 Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
908 tim 676
909 tim 699 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
910 tim 726 //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
911     force[whichDirection] = forcePolicy->getZFOfMovingMols(movingZAtoms[j],totalFZ);
912 tim 696 movingZAtoms[j]->addFrc(force);
913 tim 699 }
914 tim 696 }
915 tim 676 }
916    
917 tim 699 //cout << "after substracting z-constraint force from moving molecuels "
918 tim 701 // << "total force is " << calcTotalForce() << endl;
919 tim 699
920 tim 676 }
921    
922 tim 701 /**
923     *
924     *
925     */
926    
927     template<typename T> void ZConstraint<T>::doHarmonic(){
928     double force[3];
929     double harmonicU;
930     double harmonicF;
931     double COM[3];
932     double diff;
933     double totalFZ_local;
934     double totalFZ;
935    
936     force[0] = 0;
937     force[1] = 0;
938     force[2] = 0;
939    
940     totalFZ_local = 0;
941    
942     for(int i = 0; i < zconsMols.size(); i++) {
943    
944     if (states[i] == zcsMoving){
945     zconsMols[i]->getCOM(COM);
946 mmeineke 723 // cout << "Moving Molecule\tindex: " << indexOfZConsMols[i]
947     // << "\tcurrent zpos: " << COM[whichDirection] << endl;
948 tim 726
949     diff = COM[whichDirection] -zPos[i];
950 tim 701
951     harmonicU = 0.5 * kz[i] * diff * diff;
952 tim 726 info->lrPot += harmonicU;
953 tim 701
954     harmonicF = - kz[i] * diff;
955     totalFZ_local += harmonicF;
956    
957     //adjust force
958    
959     Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
960    
961     for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
962 tim 726 //force[whichDirection] = harmonicF / zconsMols[i]->getNAtoms();
963     force[whichDirection] = forcePolicy->getHFOfFixedZMols(zconsMols[i], movingZAtoms[j], harmonicF);
964 tim 701 movingZAtoms[j]->addFrc(force);
965     }
966     }
967    
968     }
969    
970     #ifndef IS_MPI
971     totalFZ = totalFZ_local;
972     #else
973     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
974     #endif
975    
976     force[0]= 0;
977     force[1]= 0;
978     force[2]= 0;
979    
980     //modify the forces of unconstrained molecules
981     for(int i = 0; i < unconsMols.size(); i++){
982    
983     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
984    
985     for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){
986 tim 726 //force[whichDirection] = - totalFZ /totNumOfUnconsAtoms;
987     force[whichDirection] = - forcePolicy->getHFOfUnconsMols(unconsAtoms[j], totalFZ);
988 tim 701 unconsAtoms[j]->addFrc(force);
989     }
990     }
991    
992     }
993    
994     /**
995     *
996     */
997    
998 tim 676 template<typename T> bool ZConstraint<T>::checkZConsState(){
999     double COM[3];
1000     double diff;
1001 tim 658
1002 tim 699 int changed_local;
1003     int changed;
1004 tim 701
1005 tim 699 changed_local = 0;
1006 tim 676
1007     for(int i =0; i < zconsMols.size(); i++){
1008    
1009 tim 658 zconsMols[i]->getCOM(COM);
1010 tim 682 diff = fabs(COM[whichDirection] - zPos[i]);
1011     if ( diff <= zconsTol && states[i] == zcsMoving){
1012 tim 676 states[i] = zcsFixed;
1013 tim 701 changed_local = 1;
1014 tim 676 }
1015 tim 682 else if ( diff > zconsTol && states[i] == zcsFixed){
1016 tim 676 states[i] = zcsMoving;
1017 tim 701 changed_local = 1;
1018 tim 676 }
1019    
1020 tim 658 }
1021    
1022 tim 699 #ifndef IS_MPI
1023     changed =changed_local;
1024     #else
1025     MPI_Allreduce(&changed_local, &changed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1026     #endif
1027 tim 726
1028 mmeineke 711 return (changed > 0);
1029 tim 726
1030 tim 658 }
1031 tim 676
1032     template<typename T> bool ZConstraint<T>::haveFixedZMols(){
1033 tim 699
1034     int havingFixed_local;
1035     int havingFixed;
1036    
1037     havingFixed_local = 0;
1038    
1039 tim 676 for(int i = 0; i < zconsMols.size(); i++)
1040 tim 699 if (states[i] == zcsFixed){
1041     havingFixed_local = 1;
1042 tim 701 break;
1043 tim 699 }
1044 tim 676
1045 tim 699 #ifndef IS_MPI
1046     havingFixed = havingFixed_local;
1047     #else
1048     MPI_Allreduce(&havingFixed_local, &havingFixed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1049     #endif
1050    
1051 tim 726 return (havingFixed > 0);
1052 tim 676 }
1053    
1054    
1055     /**
1056     *
1057     */
1058     template<typename T> bool ZConstraint<T>::haveMovingZMols(){
1059 tim 699
1060     int havingMoving_local;
1061     int havingMoving;
1062    
1063     havingMoving_local = 0;
1064    
1065 tim 676 for(int i = 0; i < zconsMols.size(); i++)
1066 tim 699 if (states[i] == zcsMoving){
1067     havingMoving_local = 1;
1068 tim 701 break;
1069 tim 699 }
1070 tim 676
1071 tim 699 #ifndef IS_MPI
1072     havingMoving = havingMoving_local;
1073     #else
1074     MPI_Allreduce(&havingMoving_local, &havingMoving, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1075     #endif
1076    
1077 tim 726 return (havingMoving > 0);
1078 tim 676
1079 tim 682 }
1080    
1081     /**
1082 tim 701 *
1083     */
1084 tim 682
1085 tim 696 template<typename T> double ZConstraint<T>::calcMovingMolsCOMVel()
1086 tim 693 {
1087     double MVzOfMovingMols_local;
1088     double MVzOfMovingMols;
1089     double totalMassOfMovingZMols_local;
1090     double totalMassOfMovingZMols;
1091     double COMvel[3];
1092    
1093     MVzOfMovingMols_local = 0;
1094     totalMassOfMovingZMols_local = 0;
1095    
1096     for(int i =0; i < unconsMols.size(); i++){
1097     unconsMols[i]->getCOMvel(COMvel);
1098     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
1099     }
1100    
1101     for(int i = 0; i < zconsMols.size(); i++){
1102    
1103     if (states[i] == zcsMoving){
1104     zconsMols[i]->getCOMvel(COMvel);
1105     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
1106 tim 701 totalMassOfMovingZMols_local += massOfZConsMols[i];
1107 tim 693 }
1108 tim 701
1109 tim 693 }
1110    
1111     #ifndef IS_MPI
1112     MVzOfMovingMols = MVzOfMovingMols_local;
1113     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
1114     #else
1115     MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1116     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1117     #endif
1118    
1119     double vzOfMovingMols;
1120     vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
1121    
1122     return vzOfMovingMols;
1123     }
1124    
1125 tim 701 /**
1126     *
1127     */
1128 tim 693
1129 tim 696 template<typename T> double ZConstraint<T>::calcSysCOMVel()
1130 tim 693 {
1131     double COMvel[3];
1132 tim 699 double tempMVz_local;
1133     double tempMVz;
1134     double massOfZCons_local;
1135     double massOfZCons;
1136    
1137    
1138     tempMVz_local = 0;
1139    
1140 tim 693 for(int i =0 ; i < nMols; i++){
1141 tim 696 molecules[i].getCOMvel(COMvel);
1142 tim 701 tempMVz_local += molecules[i].getTotalMass()*COMvel[whichDirection];
1143 tim 693 }
1144 tim 696
1145     massOfZCons_local = 0;
1146 tim 701
1147 tim 696 for(int i = 0; i < massOfZConsMols.size(); i++){
1148     massOfZCons_local += massOfZConsMols[i];
1149     }
1150     #ifndef IS_MPI
1151     massOfZCons = massOfZCons_local;
1152 tim 699 tempMVz = tempMVz_local;
1153 tim 696 #else
1154     MPI_Allreduce(&massOfZCons_local, &massOfZCons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1155 tim 699 MPI_Allreduce(&tempMVz_local, &tempMVz, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1156 tim 696 #endif
1157    
1158     return tempMVz /(totalMassOfUncons + massOfZCons);
1159 tim 693 }
1160 tim 696
1161 tim 701 /**
1162     *
1163     */
1164    
1165 tim 696 template<typename T> double ZConstraint<T>::calcTotalForce(){
1166    
1167     double force[3];
1168     double totalForce_local;
1169     double totalForce;
1170    
1171     totalForce_local = 0;
1172    
1173     for(int i = 0; i < nAtoms; i++){
1174     atoms[i]->getFrc(force);
1175     totalForce_local += force[whichDirection];
1176     }
1177    
1178     #ifndef IS_MPI
1179     totalForce = totalForce_local;
1180     #else
1181     MPI_Allreduce(&totalForce_local, &totalForce, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1182     #endif
1183    
1184     return totalForce;
1185    
1186     }
1187 tim 699
1188     /**
1189     *
1190     */
1191    
1192     template<typename T> void ZConstraint<T>::PolicyByNumber::update(){
1193     //calculate the number of atoms of moving z-constrained molecules
1194     int nMovingZAtoms_local;
1195     int nMovingZAtoms;
1196 tim 701
1197 tim 699 nMovingZAtoms_local = 0;
1198     for(int i = 0; i < (zconsIntegrator->zconsMols).size(); i++)
1199     if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1200 tim 701 nMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getNAtoms();
1201 tim 699
1202     #ifdef IS_MPI
1203     MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
1204     #else
1205     nMovingZAtoms = nMovingZAtoms_local;
1206     #endif
1207     totNumOfMovingAtoms = nMovingZAtoms + zconsIntegrator->totNumOfUnconsAtoms;
1208 mmeineke 711
1209     #ifdef IS_MPI
1210     if(worldRank == 0){
1211     #endif
1212 mmeineke 723 // std::cerr << "\n"
1213     // << "*******************************************\n"
1214     // << " fiished Policy by numbr()\n"
1215     // << "*******************************************\n"
1216     // << "\n";
1217 mmeineke 711 #ifdef IS_MPI
1218     }
1219     #endif
1220 tim 699 }
1221    
1222 tim 701 template<typename T>double ZConstraint<T>::PolicyByNumber::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1223 tim 699 return totalForce / mol->getNAtoms();
1224     }
1225    
1226     template<typename T> double ZConstraint<T>::PolicyByNumber::getZFOfMovingMols(Atom* atom, double totalForce){
1227     return totalForce / totNumOfMovingAtoms;
1228     }
1229    
1230     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1231     return totalForce / mol->getNAtoms();
1232     }
1233    
1234     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfUnconsMols(Atom* atom, double totalForce){
1235     return totalForce / zconsIntegrator->totNumOfUnconsAtoms;
1236     }
1237    
1238     /**
1239     *
1240     */
1241    
1242     template<typename T> void ZConstraint<T>::PolicyByMass::update(){
1243     //calculate the number of atoms of moving z-constrained molecules
1244     double massOfMovingZAtoms_local;
1245     double massOfMovingZAtoms;
1246 tim 701
1247 tim 699 massOfMovingZAtoms_local = 0;
1248     for(int i = 0; i < (zconsIntegrator->zconsMols).size(); i++)
1249     if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1250 tim 701 massOfMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getTotalMass();
1251 tim 699
1252     #ifdef IS_MPI
1253     MPI_Allreduce(&massOfMovingZAtoms_local, &massOfMovingZAtoms, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1254     #else
1255     massOfMovingZAtoms = massOfMovingZAtoms_local;
1256     #endif
1257     totMassOfMovingAtoms = massOfMovingZAtoms_local + zconsIntegrator->totalMassOfUncons;
1258     }
1259    
1260     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1261     return totalForce * atom->getMass() / mol->getTotalMass();
1262     }
1263    
1264     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfMovingMols( Atom* atom, double totalForce){
1265     return totalForce * atom->getMass() / totMassOfMovingAtoms;
1266     }
1267    
1268     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1269     return totalForce * atom->getMass() / mol->getTotalMass();
1270     }
1271    
1272     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfUnconsMols(Atom* atom, double totalForce){
1273     return totalForce * atom->getMass() / zconsIntegrator->totalMassOfUncons;
1274     }
1275