ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 829
Committed: Tue Oct 28 16:03:37 2003 UTC (20 years, 8 months ago) by gezelter
File size: 31426 byte(s)
Log Message:
replace c++ header stuff with more portable c header stuff
Also, mod file fixes and portability changes
Some fortran changes will need to be reversed.

File Contents

# User Rev Content
1 tim 658 #include "Integrator.hpp"
2     #include "simError.h"
3 gezelter 829 #include <math.h>
4 tim 658 template<typename T> ZConstraint<T>::ZConstraint(SimInfo* theInfo, ForceFields* the_ff)
5 mmeineke 787 : T(theInfo, the_ff), indexOfZConsMols(NULL), fz(NULL), curZPos(NULL),
6     fzOut(NULL), curZconsTime(0), forcePolicy(NULL)
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 mmeineke 787 for(int i = 0; i < (int)(parameters->size()); i++){
217 tim 682
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 mmeineke 787
231 tim 701 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 mmeineke 787 for(int i = 0; i < (int)(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 mmeineke 787 for(int i = 0; i < (int)(unconsMols.size()); i++)
324 tim 693 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 mmeineke 787 for(int i = 0; i < (int)(unconsMols.size()); i++)
337 tim 676 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 mmeineke 787 for(int i = 0; i < (int)(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 mmeineke 787 for(int i = 0; i < (int)(zconsMols.size()); i++){
444 tim 658 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 mmeineke 787 for(int i = 0; i < (int)(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 mmeineke 787 for(int i = 0; i < (int)(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 mmeineke 787 for(int i =0; i < (int)(unconsMols.size()); i++){
699 tim 676 unconsMols[i]->getCOMvel(COMvel);
700     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
701     }
702    
703 mmeineke 787 for(int i = 0; i < (int)(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 mmeineke 787 for(int i = 0; i < (int)(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 mmeineke 787 for(int i = 0; i < (int)(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 COM[3];
775     double force[3];
776    
777 tim 701 //constrain the molecules which do not reach the specified positions
778 tim 676
779     //Zero Out the force of z-contrained molecules
780     totalFZ_local = 0;
781    
782     //calculate the total z-contrained force of fixed z-contrained molecules
783 tim 738
784     //cout << "before zero out z-constraint force on fixed z-constraint molecuels "
785     // << "total force is " << calcTotalForce() << endl;
786 tim 699
787 mmeineke 787 for(int i = 0; i < (int)(zconsMols.size()); i++){
788 tim 701
789 tim 676 if (states[i] == zcsFixed){
790 tim 701
791 tim 676 zconsMols[i]->getCOM(COM);
792     zconsAtoms = zconsMols[i]->getMyAtoms();
793    
794     fz[i] = 0;
795     for(int j =0; j < zconsMols[i]->getNAtoms(); j++) {
796     zconsAtoms[j]->getFrc(force);
797     fz[i] += force[whichDirection];
798 tim 701 }
799 tim 676 totalFZ_local += fz[i];
800    
801 tim 726 //cout << "Fixed Molecule\tindex: " << indexOfZConsMols[i]
802     // <<"\tcurrent zpos: " << COM[whichDirection]
803 tim 738 // << "\tcurrent fz: " <<fz[i] << endl;
804 tim 676
805 tim 726
806 tim 676 }
807 tim 701
808 tim 676 }
809 tim 699
810     //calculate total z-constraint force
811     #ifdef IS_MPI
812     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
813     #else
814     totalFZ = totalFZ_local;
815     #endif
816    
817 tim 701
818 tim 696 // apply negative to fixed z-constrained molecues;
819     force[0]= 0;
820     force[1]= 0;
821     force[2]= 0;
822 tim 676
823 mmeineke 787 for(int i = 0; i < (int)(zconsMols.size()); i++){
824 tim 696
825     if (states[i] == zcsFixed){
826 tim 701
827 tim 696 int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms();
828     zconsAtoms = zconsMols[i]->getMyAtoms();
829    
830     for(int j =0; j < nAtomOfCurZConsMol; j++) {
831 tim 726 //force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol;
832     force[whichDirection] = - forcePolicy->getZFOfFixedZMols(zconsMols[i], zconsAtoms[j], fz[i]);
833 tim 696 zconsAtoms[j]->addFrc(force);
834     }
835 tim 701
836 tim 696 }
837 tim 701
838 tim 696 }
839    
840 tim 738 //cout << "after zero out z-constraint force on fixed z-constraint molecuels "
841     // << "total force is " << calcTotalForce() << endl;
842    
843 tim 699
844 tim 676 force[0]= 0;
845     force[1]= 0;
846     force[2]= 0;
847    
848 tim 693 //modify the forces of unconstrained molecules
849 mmeineke 787 for(int i = 0; i < (int)(unconsMols.size()); i++){
850 tim 676
851     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
852    
853 tim 699 for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){
854 tim 726 //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
855     force[whichDirection] = forcePolicy->getZFOfMovingMols(unconsAtoms[j],totalFZ);
856 tim 676 unconsAtoms[j]->addFrc(force);
857 tim 699 }
858 tim 676
859     }
860    
861 tim 693 //modify the forces of moving z-constrained molecules
862 mmeineke 787 for(int i = 0; i < (int)(zconsMols.size()); i++) {
863 tim 696 if (states[i] == zcsMoving){
864 tim 701
865 tim 696 Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
866 tim 676
867 tim 699 for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
868 tim 726 //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
869     force[whichDirection] = forcePolicy->getZFOfMovingMols(movingZAtoms[j],totalFZ);
870 tim 696 movingZAtoms[j]->addFrc(force);
871 tim 699 }
872 tim 696 }
873 tim 676 }
874 tim 738 // cout << "after substracting z-constraint force from moving molecuels "
875     // << "total force is " << calcTotalForce() << endl;
876 tim 676
877     }
878    
879 tim 701 /**
880     *
881     *
882     */
883    
884     template<typename T> void ZConstraint<T>::doHarmonic(){
885     double force[3];
886     double harmonicU;
887     double harmonicF;
888     double COM[3];
889     double diff;
890     double totalFZ_local;
891     double totalFZ;
892    
893     force[0] = 0;
894     force[1] = 0;
895     force[2] = 0;
896    
897     totalFZ_local = 0;
898    
899 mmeineke 787 for(int i = 0; i < (int)(zconsMols.size()); i++) {
900 tim 701
901     if (states[i] == zcsMoving){
902     zconsMols[i]->getCOM(COM);
903 mmeineke 723 // cout << "Moving Molecule\tindex: " << indexOfZConsMols[i]
904     // << "\tcurrent zpos: " << COM[whichDirection] << endl;
905 tim 726
906     diff = COM[whichDirection] -zPos[i];
907 tim 701
908     harmonicU = 0.5 * kz[i] * diff * diff;
909 tim 726 info->lrPot += harmonicU;
910 tim 701
911     harmonicF = - kz[i] * diff;
912     totalFZ_local += harmonicF;
913    
914     //adjust force
915    
916     Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
917    
918     for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){
919 tim 726 //force[whichDirection] = harmonicF / zconsMols[i]->getNAtoms();
920     force[whichDirection] = forcePolicy->getHFOfFixedZMols(zconsMols[i], movingZAtoms[j], harmonicF);
921 tim 701 movingZAtoms[j]->addFrc(force);
922     }
923     }
924    
925     }
926    
927     #ifndef IS_MPI
928     totalFZ = totalFZ_local;
929     #else
930     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
931     #endif
932    
933 tim 763 //cout << "before substracting harmonic force from moving molecuels "
934     // << "total force is " << calcTotalForce() << endl;
935 tim 738
936 tim 701 force[0]= 0;
937     force[1]= 0;
938     force[2]= 0;
939    
940     //modify the forces of unconstrained molecules
941 mmeineke 787 for(int i = 0; i < (int)(unconsMols.size()); i++){
942 tim 701
943     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
944    
945     for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){
946 tim 726 //force[whichDirection] = - totalFZ /totNumOfUnconsAtoms;
947     force[whichDirection] = - forcePolicy->getHFOfUnconsMols(unconsAtoms[j], totalFZ);
948 tim 701 unconsAtoms[j]->addFrc(force);
949     }
950     }
951    
952 tim 763 //cout << "after substracting harmonic force from moving molecuels "
953     // << "total force is " << calcTotalForce() << endl;
954 tim 738
955 tim 701 }
956    
957     /**
958     *
959     */
960    
961 tim 676 template<typename T> bool ZConstraint<T>::checkZConsState(){
962     double COM[3];
963     double diff;
964 tim 658
965 tim 699 int changed_local;
966     int changed;
967 tim 701
968 tim 699 changed_local = 0;
969 tim 676
970 mmeineke 787 for(int i =0; i < (int)(zconsMols.size()); i++){
971 tim 676
972 tim 658 zconsMols[i]->getCOM(COM);
973 tim 682 diff = fabs(COM[whichDirection] - zPos[i]);
974     if ( diff <= zconsTol && states[i] == zcsMoving){
975 tim 676 states[i] = zcsFixed;
976 tim 701 changed_local = 1;
977 tim 676 }
978 tim 682 else if ( diff > zconsTol && states[i] == zcsFixed){
979 tim 676 states[i] = zcsMoving;
980 tim 701 changed_local = 1;
981 tim 676 }
982    
983 tim 658 }
984    
985 tim 699 #ifndef IS_MPI
986     changed =changed_local;
987     #else
988     MPI_Allreduce(&changed_local, &changed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
989     #endif
990 tim 726
991 mmeineke 711 return (changed > 0);
992 tim 726
993 tim 658 }
994 tim 676
995     template<typename T> bool ZConstraint<T>::haveFixedZMols(){
996 tim 699
997     int havingFixed_local;
998     int havingFixed;
999    
1000     havingFixed_local = 0;
1001    
1002 mmeineke 787 for(int i = 0; i < (int)(zconsMols.size()); i++)
1003 tim 699 if (states[i] == zcsFixed){
1004     havingFixed_local = 1;
1005 tim 701 break;
1006 tim 699 }
1007 tim 676
1008 tim 699 #ifndef IS_MPI
1009     havingFixed = havingFixed_local;
1010     #else
1011     MPI_Allreduce(&havingFixed_local, &havingFixed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1012     #endif
1013    
1014 tim 726 return (havingFixed > 0);
1015 tim 676 }
1016    
1017    
1018     /**
1019     *
1020     */
1021     template<typename T> bool ZConstraint<T>::haveMovingZMols(){
1022 tim 699
1023     int havingMoving_local;
1024     int havingMoving;
1025    
1026     havingMoving_local = 0;
1027    
1028 mmeineke 787 for(int i = 0; i < (int)(zconsMols.size()); i++)
1029 tim 699 if (states[i] == zcsMoving){
1030     havingMoving_local = 1;
1031 tim 701 break;
1032 tim 699 }
1033 tim 676
1034 tim 699 #ifndef IS_MPI
1035     havingMoving = havingMoving_local;
1036     #else
1037     MPI_Allreduce(&havingMoving_local, &havingMoving, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
1038     #endif
1039    
1040 tim 726 return (havingMoving > 0);
1041 tim 676
1042 tim 682 }
1043    
1044     /**
1045 tim 701 *
1046     */
1047 tim 682
1048 tim 696 template<typename T> double ZConstraint<T>::calcMovingMolsCOMVel()
1049 tim 693 {
1050     double MVzOfMovingMols_local;
1051     double MVzOfMovingMols;
1052     double totalMassOfMovingZMols_local;
1053     double totalMassOfMovingZMols;
1054     double COMvel[3];
1055    
1056     MVzOfMovingMols_local = 0;
1057     totalMassOfMovingZMols_local = 0;
1058    
1059     for(int i =0; i < unconsMols.size(); i++){
1060     unconsMols[i]->getCOMvel(COMvel);
1061     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
1062     }
1063    
1064     for(int i = 0; i < zconsMols.size(); i++){
1065    
1066     if (states[i] == zcsMoving){
1067     zconsMols[i]->getCOMvel(COMvel);
1068     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
1069 tim 701 totalMassOfMovingZMols_local += massOfZConsMols[i];
1070 tim 693 }
1071 tim 701
1072 tim 693 }
1073    
1074     #ifndef IS_MPI
1075     MVzOfMovingMols = MVzOfMovingMols_local;
1076     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
1077     #else
1078     MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1079     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1080     #endif
1081    
1082     double vzOfMovingMols;
1083     vzOfMovingMols = MVzOfMovingMols / (totalMassOfUncons + totalMassOfMovingZMols);
1084    
1085     return vzOfMovingMols;
1086     }
1087    
1088 tim 701 /**
1089     *
1090     */
1091 tim 693
1092 tim 696 template<typename T> double ZConstraint<T>::calcSysCOMVel()
1093 tim 693 {
1094     double COMvel[3];
1095 tim 699 double tempMVz_local;
1096     double tempMVz;
1097     double massOfZCons_local;
1098     double massOfZCons;
1099    
1100    
1101     tempMVz_local = 0;
1102    
1103 tim 693 for(int i =0 ; i < nMols; i++){
1104 tim 696 molecules[i].getCOMvel(COMvel);
1105 tim 701 tempMVz_local += molecules[i].getTotalMass()*COMvel[whichDirection];
1106 tim 693 }
1107 tim 696
1108     massOfZCons_local = 0;
1109 tim 701
1110 mmeineke 787 for(int i = 0; i < (int)(massOfZConsMols.size()); i++){
1111 tim 696 massOfZCons_local += massOfZConsMols[i];
1112     }
1113     #ifndef IS_MPI
1114     massOfZCons = massOfZCons_local;
1115 tim 699 tempMVz = tempMVz_local;
1116 tim 696 #else
1117     MPI_Allreduce(&massOfZCons_local, &massOfZCons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1118 tim 699 MPI_Allreduce(&tempMVz_local, &tempMVz, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1119 tim 696 #endif
1120    
1121     return tempMVz /(totalMassOfUncons + massOfZCons);
1122 tim 693 }
1123 tim 696
1124 tim 701 /**
1125     *
1126     */
1127    
1128 tim 696 template<typename T> double ZConstraint<T>::calcTotalForce(){
1129    
1130     double force[3];
1131     double totalForce_local;
1132     double totalForce;
1133    
1134     totalForce_local = 0;
1135    
1136     for(int i = 0; i < nAtoms; i++){
1137     atoms[i]->getFrc(force);
1138     totalForce_local += force[whichDirection];
1139     }
1140    
1141     #ifndef IS_MPI
1142     totalForce = totalForce_local;
1143     #else
1144     MPI_Allreduce(&totalForce_local, &totalForce, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1145     #endif
1146    
1147     return totalForce;
1148    
1149     }
1150 tim 699
1151     /**
1152     *
1153     */
1154    
1155     template<typename T> void ZConstraint<T>::PolicyByNumber::update(){
1156     //calculate the number of atoms of moving z-constrained molecules
1157     int nMovingZAtoms_local;
1158     int nMovingZAtoms;
1159 tim 701
1160 tim 699 nMovingZAtoms_local = 0;
1161 mmeineke 787 for(int i = 0; i < (int)((zconsIntegrator->zconsMols).size()); i++)
1162 tim 699 if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1163 tim 701 nMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getNAtoms();
1164 tim 699
1165     #ifdef IS_MPI
1166     MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
1167     #else
1168     nMovingZAtoms = nMovingZAtoms_local;
1169     #endif
1170     totNumOfMovingAtoms = nMovingZAtoms + zconsIntegrator->totNumOfUnconsAtoms;
1171     }
1172    
1173 tim 701 template<typename T>double ZConstraint<T>::PolicyByNumber::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1174 tim 699 return totalForce / mol->getNAtoms();
1175     }
1176    
1177     template<typename T> double ZConstraint<T>::PolicyByNumber::getZFOfMovingMols(Atom* atom, double totalForce){
1178     return totalForce / totNumOfMovingAtoms;
1179     }
1180    
1181     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1182     return totalForce / mol->getNAtoms();
1183     }
1184    
1185     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfUnconsMols(Atom* atom, double totalForce){
1186     return totalForce / zconsIntegrator->totNumOfUnconsAtoms;
1187     }
1188    
1189     /**
1190     *
1191     */
1192    
1193     template<typename T> void ZConstraint<T>::PolicyByMass::update(){
1194     //calculate the number of atoms of moving z-constrained molecules
1195     double massOfMovingZAtoms_local;
1196     double massOfMovingZAtoms;
1197 tim 701
1198 tim 699 massOfMovingZAtoms_local = 0;
1199 mmeineke 787 for(int i = 0; i < (int)((zconsIntegrator->zconsMols).size()); i++)
1200 tim 699 if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving))
1201 tim 701 massOfMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getTotalMass();
1202 tim 699
1203     #ifdef IS_MPI
1204     MPI_Allreduce(&massOfMovingZAtoms_local, &massOfMovingZAtoms, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
1205     #else
1206     massOfMovingZAtoms = massOfMovingZAtoms_local;
1207     #endif
1208 tim 738 totMassOfMovingAtoms = massOfMovingZAtoms + zconsIntegrator->totalMassOfUncons;
1209 tim 699 }
1210    
1211     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1212     return totalForce * atom->getMass() / mol->getTotalMass();
1213     }
1214    
1215     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfMovingMols( Atom* atom, double totalForce){
1216     return totalForce * atom->getMass() / totMassOfMovingAtoms;
1217     }
1218    
1219     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){
1220     return totalForce * atom->getMass() / mol->getTotalMass();
1221     }
1222    
1223     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfUnconsMols(Atom* atom, double totalForce){
1224     return totalForce * atom->getMass() / zconsIntegrator->totalMassOfUncons;
1225     }
1226