ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 763
Committed: Mon Sep 15 16:52:02 2003 UTC (20 years, 9 months ago) by tim
File size: 31320 byte(s)
Log Message:
add conserved quantity to statWriter
fix bug of vector wrapping at NPTi

File Contents

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