ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 736
Committed: Thu Aug 28 21:09:47 2003 UTC (20 years, 10 months ago) by tim
File size: 31721 byte(s)
Log Message:
Added: check uniqueness of molIndex

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 tim 736 "PolicyByMass is used\n");
62 tim 699 painCave.isFatal = 0;
63     simError();
64 tim 736 forcePolicy = (ForceSubstractionPolicy*) 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    
334 tim 676 //get total number of unconstrained atoms
335     int nUnconsAtoms_local;
336     nUnconsAtoms_local = 0;
337     for(int i = 0; i < unconsMols.size(); i++)
338     nUnconsAtoms_local += unconsMols[i]->getNAtoms();
339    
340     #ifndef IS_MPI
341     totNumOfUnconsAtoms = nUnconsAtoms_local;
342     #else
343 tim 701 MPI_Allreduce(&nUnconsAtoms_local, &totNumOfUnconsAtoms, 1,
344     MPI_INT,MPI_SUM, MPI_COMM_WORLD);
345 tim 693 #endif
346 tim 676
347 tim 693 // creat zconsWriter
348 tim 699 fzOut = new ZConsWriter(zconsOutput.c_str(), parameters);
349 tim 658
350     if(!fzOut){
351     sprintf( painCave.errMsg,
352     "Memory allocation failure in class Zconstraint\n");
353     painCave.isFatal = 1;
354     simError();
355     }
356 tim 699
357     forcePolicy->update();
358 tim 658 }
359    
360     template<typename T> ZConstraint<T>::~ZConstraint()
361     {
362     if(fz)
363     delete[] fz;
364 tim 699
365     if(curZPos)
366     delete[] curZPos;
367 tim 658
368     if(indexOfZConsMols)
369     delete[] indexOfZConsMols;
370    
371     if(fzOut)
372     delete fzOut;
373 tim 701
374 tim 699 if(forcePolicy)
375     delete forcePolicy;
376 tim 658 }
377    
378 tim 701
379     /**
380     *
381     */
382    
383 tim 658 #ifdef IS_MPI
384     template<typename T> void ZConstraint<T>::update()
385     {
386     double COM[3];
387     int index;
388    
389     zconsMols.clear();
390     massOfZConsMols.clear();
391 tim 682 zPos.clear();
392     kz.clear();
393 tim 658
394     unconsMols.clear();
395     massOfUnconsMols.clear();
396    
397    
398     //creat zconsMol and unconsMol lists
399     for(int i = 0; i < nMols; i++){
400    
401     index = isZConstraintMol(&molecules[i]);
402    
403     if(index > -1){
404    
405     zconsMols.push_back(&molecules[i]);
406 tim 682 zPos.push_back((*parameters)[index].zPos);
407 tim 701 kz.push_back((*parameters)[index].kRatio * zForceConst);
408    
409 tim 658 massOfZConsMols.push_back(molecules[i].getTotalMass());
410    
411     molecules[i].getCOM(COM);
412     }
413     else
414     {
415    
416     unconsMols.push_back(&molecules[i]);
417     massOfUnconsMols.push_back(molecules[i].getTotalMass());
418    
419     }
420     }
421 tim 693
422     //determine the states of z-constraint molecules
423     for(int i = 0; i < zconsMols.size(); i++){
424 tim 701 zconsMols[i]->getCOM(COM);
425 tim 693 if (fabs(zPos[i] - COM[whichDirection]) < zconsTol)
426 tim 701 states.push_back(zcsFixed);
427     else
428     states.push_back(zcsMoving);
429 tim 693 }
430    
431 tim 658
432     //The reason to declare fz and indexOfZconsMols as pointer to array is
433     // that we want to make the MPI communication simple
434     if(fz)
435     delete[] fz;
436 tim 701
437 tim 699 if(curZPos)
438     delete[] curZPos;
439 tim 658
440     if(indexOfZConsMols)
441     delete[] indexOfZConsMols;
442    
443     if (zconsMols.size() > 0){
444     fz = new double[zconsMols.size()];
445 tim 701 curZPos = new double[zconsMols.size()];
446 tim 658 indexOfZConsMols = new int[zconsMols.size()];
447    
448 tim 699 if(!fz || !curZPos || !indexOfZConsMols){
449 tim 658 sprintf( painCave.errMsg,
450     "Memory allocation failure in class Zconstraint\n");
451     painCave.isFatal = 1;
452     simError();
453     }
454    
455     for(int i = 0; i < zconsMols.size(); i++){
456     indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex();
457     }
458    
459     }
460     else{
461     fz = NULL;
462 tim 701 curZPos = NULL;
463 tim 658 indexOfZConsMols = NULL;
464     }
465 tim 701
466 tim 699 //
467     forcePolicy->update();
468 tim 658
469     }
470    
471     #endif
472    
473 tim 701 /**
474     * Function Name: isZConstraintMol
475     * Parameter
476     * Molecule* mol
477     * Return value:
478     * -1, if the molecule is not z-constraint molecule,
479     * other non-negative values, its index in indexOfAllZConsMols vector
480 tim 658 */
481    
482     template<typename T> int ZConstraint<T>::isZConstraintMol(Molecule* mol)
483     {
484     int index;
485     int low;
486     int high;
487     int mid;
488    
489     index = mol->getGlobalIndex();
490    
491     low = 0;
492 tim 682 high = parameters->size() - 1;
493 tim 658
494     //Binary Search (we have sorted the array)
495     while(low <= high){
496     mid = (low + high) /2;
497 tim 682 if ((*parameters)[mid].zconsIndex == index)
498 tim 658 return mid;
499 tim 682 else if ((*parameters)[mid].zconsIndex > index )
500 tim 658 high = mid -1;
501     else
502     low = mid + 1;
503     }
504    
505     return -1;
506     }
507    
508 tim 676 template<typename T> void ZConstraint<T>::integrate(){
509 tim 658
510 tim 676 //zero out the velocities of center of mass of unconstrained molecules
511     //and the velocities of center of mass of every single z-constrained molecueles
512     zeroOutVel();
513 mmeineke 711
514     curZconsTime = zconsTime + info->getTime();
515 tim 676
516     T::integrate();
517    
518 tim 658 }
519 tim 676
520 tim 658
521 tim 676 /**
522     *
523     *
524     *
525     *
526 tim 696 */
527 tim 676 template<typename T> void ZConstraint<T>::calcForce(int calcPot, int calcStress){
528 tim 693 double zsys;
529 tim 699 double COM[3];
530     double force[3];
531 tim 702 double zSysCOMVel;
532 tim 676
533     T::calcForce(calcPot, calcStress);
534    
535 tim 699 if (checkZConsState()){
536 mmeineke 711
537     #ifdef IS_MPI
538     if(worldRank == 0){
539     #endif
540 mmeineke 723 // std::cerr << "\n"
541     // << "*******************************************\n"
542     // << " about to call zeroOutVel()\n"
543     // << "*******************************************\n"
544     // << "\n";
545 mmeineke 711 #ifdef IS_MPI
546     }
547     #endif
548 tim 696 zeroOutVel();
549 mmeineke 711
550     #ifdef IS_MPI
551     if(worldRank == 0){
552     #endif
553 mmeineke 723 // std::cerr << "\n"
554     // << "*******************************************\n"
555     // << " finished zeroOutVel()\n"
556     // << "*******************************************\n"
557     // << "\n";
558 mmeineke 711 #ifdef IS_MPI
559     }
560     #endif
561    
562     forcePolicy->update();
563 tim 699 }
564 mmeineke 711
565 tim 693 zsys = calcZSys();
566 tim 702 zSysCOMVel = calcSysCOMVel();
567     #ifdef IS_MPI
568     if(worldRank == 0){
569     #endif
570 mmeineke 723 // cout << "---------------------------------------------------------------------" <<endl;
571     // cout << "current time: " << info->getTime() << endl;
572     // cout << "center of mass at z: " << zsys << endl;
573     // cout << "before calcForce, the COMVel of system is " << zSysCOMVel <<endl;
574 tim 676
575 tim 702 #ifdef IS_MPI
576     }
577     #endif
578 tim 696
579 tim 676 //do zconstraint force;
580     if (haveFixedZMols())
581     this->doZconstraintForce();
582 tim 733
583 tim 676 //use harmonical poteintial to move the molecules to the specified positions
584     if (haveMovingZMols())
585 tim 693 this->doHarmonic();
586 tim 696
587 tim 699 //write out forces and current positions of z-constraint molecules
588 tim 701 if(info->getTime() >= curZconsTime){
589     for(int i = 0; i < zconsMols.size(); i++){
590 tim 699 zconsMols[i]->getCOM(COM);
591 tim 701 curZPos[i] = COM[whichDirection];
592 tim 699
593 tim 701 //if the z-constraint molecule is still moving, just record its force
594     if(states[i] == zcsMoving){
595 tim 699 fz[i] = 0;
596 tim 701 Atom** movingZAtoms;
597     movingZAtoms = zconsMols[i]->getMyAtoms();
598     for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
599 tim 699 movingZAtoms[j]->getFrc(force);
600     fz[i] += force[whichDirection];
601 tim 701 }
602     }
603     }
604 tim 699 fzOut->writeFZ(info->getTime(), zconsMols.size(), indexOfZConsMols, fz, curZPos);
605 tim 701 curZconsTime += zconsTime;
606 tim 699 }
607 tim 702
608     zSysCOMVel = calcSysCOMVel();
609     #ifdef IS_MPI
610     if(worldRank == 0){
611     #endif
612 mmeineke 723 // cout << "after calcForce, the COMVel of system is " << zSysCOMVel <<endl;
613 tim 702 #ifdef IS_MPI
614     }
615     #endif
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 tim 701 //constrain the molecules which do not reach the specified positions
806 tim 676
807     //Zero Out the force of z-contrained molecules
808     totalFZ_local = 0;
809    
810     //calculate the total z-contrained force of fixed z-contrained molecules
811 tim 699
812 tim 676 for(int i = 0; i < zconsMols.size(); i++){
813 tim 701
814 tim 676 if (states[i] == zcsFixed){
815 tim 701
816 tim 676 zconsMols[i]->getCOM(COM);
817     zconsAtoms = zconsMols[i]->getMyAtoms();
818    
819     fz[i] = 0;
820     for(int j =0; j < zconsMols[i]->getNAtoms(); j++) {
821     zconsAtoms[j]->getFrc(force);
822     fz[i] += force[whichDirection];
823 tim 701 }
824 tim 676 totalFZ_local += fz[i];
825    
826 tim 726 //cout << "Fixed Molecule\tindex: " << indexOfZConsMols[i]
827     // <<"\tcurrent zpos: " << COM[whichDirection]
828     // << "\tcurrent fz: " <<fz[i] << endl;
829 tim 676
830 tim 726
831 tim 676 }
832 tim 701
833 tim 676 }
834 tim 699
835     //calculate total z-constraint force
836     #ifdef IS_MPI
837     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
838     #else
839     totalFZ = totalFZ_local;
840     #endif
841    
842 tim 701
843 tim 696 // apply negative to fixed z-constrained molecues;
844     force[0]= 0;
845     force[1]= 0;
846     force[2]= 0;
847 tim 676
848 tim 696 for(int i = 0; i < zconsMols.size(); i++){
849    
850     if (states[i] == zcsFixed){
851 tim 701
852 tim 696 int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms();
853     zconsAtoms = zconsMols[i]->getMyAtoms();
854    
855     for(int j =0; j < nAtomOfCurZConsMol; j++) {
856 tim 726 //force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol;
857     force[whichDirection] = - forcePolicy->getZFOfFixedZMols(zconsMols[i], zconsAtoms[j], fz[i]);
858 tim 696 zconsAtoms[j]->addFrc(force);
859     }
860 tim 701
861 tim 696 }
862 tim 701
863 tim 696 }
864    
865 mmeineke 711 // cout << "after zero out z-constraint force on fixed z-constraint molecuels "
866     // << "total force is " << calcTotalForce() << endl;
867 tim 699
868 tim 676 force[0]= 0;
869     force[1]= 0;
870     force[2]= 0;
871    
872 tim 693 //modify the forces of unconstrained molecules
873 tim 676 for(int i = 0; i < unconsMols.size(); i++){
874    
875     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
876    
877 tim 699 for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){
878 tim 726 //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
879     force[whichDirection] = forcePolicy->getZFOfMovingMols(unconsAtoms[j],totalFZ);
880 tim 676 unconsAtoms[j]->addFrc(force);
881 tim 699 }
882 tim 676
883     }
884    
885 tim 693 //modify the forces of moving z-constrained molecules
886 tim 676 for(int i = 0; i < zconsMols.size(); i++) {
887 tim 696 if (states[i] == zcsMoving){
888 tim 701
889 tim 696 Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
890 tim 676
891 tim 699 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
892 tim 726 //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
893     force[whichDirection] = forcePolicy->getZFOfMovingMols(movingZAtoms[j],totalFZ);
894 tim 696 movingZAtoms[j]->addFrc(force);
895 tim 699 }
896 tim 696 }
897 tim 676 }
898    
899 tim 699 //cout << "after substracting z-constraint force from moving molecuels "
900 tim 701 // << "total force is " << calcTotalForce() << endl;
901 tim 699
902 tim 676 }
903    
904 tim 701 /**
905     *
906     *
907     */
908    
909     template<typename T> void ZConstraint<T>::doHarmonic(){
910     double force[3];
911     double harmonicU;
912     double harmonicF;
913     double COM[3];
914     double diff;
915     double totalFZ_local;
916     double totalFZ;
917    
918     force[0] = 0;
919     force[1] = 0;
920     force[2] = 0;
921    
922     totalFZ_local = 0;
923    
924     for(int i = 0; i < zconsMols.size(); i++) {
925    
926     if (states[i] == zcsMoving){
927     zconsMols[i]->getCOM(COM);
928 mmeineke 723 // cout << "Moving Molecule\tindex: " << indexOfZConsMols[i]
929     // << "\tcurrent zpos: " << COM[whichDirection] << endl;
930 tim 726
931     diff = COM[whichDirection] -zPos[i];
932 tim 701
933     harmonicU = 0.5 * kz[i] * diff * diff;
934 tim 726 info->lrPot += harmonicU;
935 tim 701
936     harmonicF = - kz[i] * diff;
937     totalFZ_local += harmonicF;
938    
939     //adjust force
940    
941     Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
942    
943     for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
944 tim 726 //force[whichDirection] = harmonicF / zconsMols[i]->getNAtoms();
945     force[whichDirection] = forcePolicy->getHFOfFixedZMols(zconsMols[i], movingZAtoms[j], harmonicF);
946 tim 701 movingZAtoms[j]->addFrc(force);
947     }
948     }
949    
950     }
951    
952     #ifndef IS_MPI
953     totalFZ = totalFZ_local;
954     #else
955     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
956     #endif
957    
958     force[0]= 0;
959     force[1]= 0;
960     force[2]= 0;
961    
962     //modify the forces of unconstrained molecules
963     for(int i = 0; i < unconsMols.size(); i++){
964    
965     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
966    
967     for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){
968 tim 726 //force[whichDirection] = - totalFZ /totNumOfUnconsAtoms;
969     force[whichDirection] = - forcePolicy->getHFOfUnconsMols(unconsAtoms[j], totalFZ);
970 tim 701 unconsAtoms[j]->addFrc(force);
971     }
972     }
973    
974     }
975    
976     /**
977     *
978     */
979    
980 tim 676 template<typename T> bool ZConstraint<T>::checkZConsState(){
981     double COM[3];
982     double diff;
983 tim 658
984 tim 699 int changed_local;
985     int changed;
986 tim 701
987 tim 699 changed_local = 0;
988 tim 676
989     for(int i =0; i < zconsMols.size(); i++){
990    
991 tim 658 zconsMols[i]->getCOM(COM);
992 tim 682 diff = fabs(COM[whichDirection] - zPos[i]);
993     if ( diff <= zconsTol && states[i] == zcsMoving){
994 tim 676 states[i] = zcsFixed;
995 tim 701 changed_local = 1;
996 tim 676 }
997 tim 682 else if ( diff > zconsTol && states[i] == zcsFixed){
998 tim 676 states[i] = zcsMoving;
999 tim 701 changed_local = 1;
1000 tim 676 }
1001    
1002 tim 658 }
1003    
1004 tim 699 #ifndef IS_MPI
1005     changed =changed_local;
1006     #else
1007     MPI_Allreduce(&changed_local, &changed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1008     #endif
1009 tim 726
1010 mmeineke 711 return (changed > 0);
1011 tim 726
1012 tim 658 }
1013 tim 676
1014     template<typename T> bool ZConstraint<T>::haveFixedZMols(){
1015 tim 699
1016     int havingFixed_local;
1017     int havingFixed;
1018    
1019     havingFixed_local = 0;
1020    
1021 tim 676 for(int i = 0; i < zconsMols.size(); i++)
1022 tim 699 if (states[i] == zcsFixed){
1023     havingFixed_local = 1;
1024 tim 701 break;
1025 tim 699 }
1026 tim 676
1027 tim 699 #ifndef IS_MPI
1028     havingFixed = havingFixed_local;
1029     #else
1030     MPI_Allreduce(&havingFixed_local, &havingFixed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1031     #endif
1032    
1033 tim 726 return (havingFixed > 0);
1034 tim 676 }
1035    
1036    
1037     /**
1038     *
1039     */
1040     template<typename T> bool ZConstraint<T>::haveMovingZMols(){
1041 tim 699
1042     int havingMoving_local;
1043     int havingMoving;
1044    
1045     havingMoving_local = 0;
1046    
1047 tim 676 for(int i = 0; i < zconsMols.size(); i++)
1048 tim 699 if (states[i] == zcsMoving){
1049     havingMoving_local = 1;
1050 tim 701 break;
1051 tim 699 }
1052 tim 676
1053 tim 699 #ifndef IS_MPI
1054     havingMoving = havingMoving_local;
1055     #else
1056     MPI_Allreduce(&havingMoving_local, &havingMoving, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1057     #endif
1058    
1059 tim 726 return (havingMoving > 0);
1060 tim 676
1061 tim 682 }
1062    
1063     /**
1064 tim 701 *
1065     */
1066 tim 682
1067 tim 696 template<typename T> double ZConstraint<T>::calcMovingMolsCOMVel()
1068 tim 693 {
1069     double MVzOfMovingMols_local;
1070     double MVzOfMovingMols;
1071     double totalMassOfMovingZMols_local;
1072     double totalMassOfMovingZMols;
1073     double COMvel[3];
1074    
1075     MVzOfMovingMols_local = 0;
1076     totalMassOfMovingZMols_local = 0;
1077    
1078     for(int i =0; i < unconsMols.size(); i++){
1079     unconsMols[i]->getCOMvel(COMvel);
1080     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
1081     }
1082    
1083     for(int i = 0; i < zconsMols.size(); i++){
1084    
1085     if (states[i] == zcsMoving){
1086     zconsMols[i]->getCOMvel(COMvel);
1087     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
1088 tim 701 totalMassOfMovingZMols_local += massOfZConsMols[i];
1089 tim 693 }
1090 tim 701
1091 tim 693 }
1092    
1093     #ifndef IS_MPI
1094     MVzOfMovingMols = MVzOfMovingMols_local;
1095     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
1096     #else
1097     MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1098     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1099     #endif
1100    
1101     double vzOfMovingMols;
1102     vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
1103    
1104     return vzOfMovingMols;
1105     }
1106    
1107 tim 701 /**
1108     *
1109     */
1110 tim 693
1111 tim 696 template<typename T> double ZConstraint<T>::calcSysCOMVel()
1112 tim 693 {
1113     double COMvel[3];
1114 tim 699 double tempMVz_local;
1115     double tempMVz;
1116     double massOfZCons_local;
1117     double massOfZCons;
1118    
1119    
1120     tempMVz_local = 0;
1121    
1122 tim 693 for(int i =0 ; i < nMols; i++){
1123 tim 696 molecules[i].getCOMvel(COMvel);
1124 tim 701 tempMVz_local += molecules[i].getTotalMass()*COMvel[whichDirection];
1125 tim 693 }
1126 tim 696
1127     massOfZCons_local = 0;
1128 tim 701
1129 tim 696 for(int i = 0; i < massOfZConsMols.size(); i++){
1130     massOfZCons_local += massOfZConsMols[i];
1131     }
1132     #ifndef IS_MPI
1133     massOfZCons = massOfZCons_local;
1134 tim 699 tempMVz = tempMVz_local;
1135 tim 696 #else
1136     MPI_Allreduce(&massOfZCons_local, &massOfZCons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1137 tim 699 MPI_Allreduce(&tempMVz_local, &tempMVz, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1138 tim 696 #endif
1139    
1140     return tempMVz /(totalMassOfUncons + massOfZCons);
1141 tim 693 }
1142 tim 696
1143 tim 701 /**
1144     *
1145     */
1146    
1147 tim 696 template<typename T> double ZConstraint<T>::calcTotalForce(){
1148    
1149     double force[3];
1150     double totalForce_local;
1151     double totalForce;
1152    
1153     totalForce_local = 0;
1154    
1155     for(int i = 0; i < nAtoms; i++){
1156     atoms[i]->getFrc(force);
1157     totalForce_local += force[whichDirection];
1158     }
1159    
1160     #ifndef IS_MPI
1161     totalForce = totalForce_local;
1162     #else
1163     MPI_Allreduce(&totalForce_local, &totalForce, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1164     #endif
1165    
1166     return totalForce;
1167    
1168     }
1169 tim 699
1170     /**
1171     *
1172     */
1173    
1174     template<typename T> void ZConstraint<T>::PolicyByNumber::update(){
1175     //calculate the number of atoms of moving z-constrained molecules
1176     int nMovingZAtoms_local;
1177     int nMovingZAtoms;
1178 tim 701
1179 tim 699 nMovingZAtoms_local = 0;
1180     for(int i = 0; i < (zconsIntegrator->zconsMols).size(); i++)
1181     if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1182 tim 701 nMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getNAtoms();
1183 tim 699
1184     #ifdef IS_MPI
1185     MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
1186     #else
1187     nMovingZAtoms = nMovingZAtoms_local;
1188     #endif
1189     totNumOfMovingAtoms = nMovingZAtoms + zconsIntegrator->totNumOfUnconsAtoms;
1190 mmeineke 711
1191     #ifdef IS_MPI
1192     if(worldRank == 0){
1193     #endif
1194 mmeineke 723 // std::cerr << "\n"
1195     // << "*******************************************\n"
1196     // << " fiished Policy by numbr()\n"
1197     // << "*******************************************\n"
1198     // << "\n";
1199 mmeineke 711 #ifdef IS_MPI
1200     }
1201     #endif
1202 tim 699 }
1203    
1204 tim 701 template<typename T>double ZConstraint<T>::PolicyByNumber::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1205 tim 699 return totalForce / mol->getNAtoms();
1206     }
1207    
1208     template<typename T> double ZConstraint<T>::PolicyByNumber::getZFOfMovingMols(Atom* atom, double totalForce){
1209     return totalForce / totNumOfMovingAtoms;
1210     }
1211    
1212     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1213     return totalForce / mol->getNAtoms();
1214     }
1215    
1216     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfUnconsMols(Atom* atom, double totalForce){
1217     return totalForce / zconsIntegrator->totNumOfUnconsAtoms;
1218     }
1219    
1220     /**
1221     *
1222     */
1223    
1224     template<typename T> void ZConstraint<T>::PolicyByMass::update(){
1225     //calculate the number of atoms of moving z-constrained molecules
1226     double massOfMovingZAtoms_local;
1227     double massOfMovingZAtoms;
1228 tim 701
1229 tim 699 massOfMovingZAtoms_local = 0;
1230     for(int i = 0; i < (zconsIntegrator->zconsMols).size(); i++)
1231     if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1232 tim 701 massOfMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getTotalMass();
1233 tim 699
1234     #ifdef IS_MPI
1235     MPI_Allreduce(&massOfMovingZAtoms_local, &massOfMovingZAtoms, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1236     #else
1237     massOfMovingZAtoms = massOfMovingZAtoms_local;
1238     #endif
1239     totMassOfMovingAtoms = massOfMovingZAtoms_local + zconsIntegrator->totalMassOfUncons;
1240     }
1241    
1242     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1243     return totalForce * atom->getMass() / mol->getTotalMass();
1244     }
1245    
1246     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfMovingMols( Atom* atom, double totalForce){
1247     return totalForce * atom->getMass() / totMassOfMovingAtoms;
1248     }
1249    
1250     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1251     return totalForce * atom->getMass() / mol->getTotalMass();
1252     }
1253    
1254     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfUnconsMols(Atom* atom, double totalForce){
1255     return totalForce * atom->getMass() / zconsIntegrator->totalMassOfUncons;
1256     }
1257