ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/ZConstraint.cpp
Revision: 701
Committed: Wed Aug 20 14:34:04 2003 UTC (20 years, 10 months ago) by tim
File size: 31464 byte(s)
Log Message:
reformmating ZConstraint and fixe bug of error msg printing

File Contents

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