ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-3.0/src/constraints/ZConstraint.cpp
Revision: 1830
Committed: Thu Dec 2 05:17:10 2004 UTC (19 years, 9 months ago) by tim
File size: 34259 byte(s)
Log Message:
change endl to std::endl

File Contents

# User Rev Content
1 tim 1830 #include "integrators/Integrator.hpp"
2    
3     #include "utils/simError.h"
4    
5     #include <math.h>
6    
7    
8    
9     const double INFINITE_TIME = 10e30;
10    
11     template<typename T> ZConstraint<T>::ZConstraint(SimInfo* theInfo,
12    
13     ForceFields* the_ff): T(theInfo, the_ff),
14    
15     fzOut(NULL),
16    
17     curZconsTime(0),
18    
19     forcePolicy(NULL),
20    
21     usingSMD(false),
22    
23     hasZConsGap(false){
24    
25     //get properties from SimInfo
26    
27     GenericData* data;
28    
29     ZConsParaData* zConsParaData;
30    
31     DoubleGenericData* sampleTime;
32    
33     DoubleGenericData* tolerance;
34    
35     DoubleGenericData* gap;
36    
37     DoubleGenericData* fixtime;
38    
39     StringGenericData* policy;
40    
41     StringGenericData* filename;
42    
43     IntGenericData* smdFlag;
44    
45     double COM[3];
46    
47    
48    
49     //by default, the direction of constraint is z
50    
51     // 0 --> x
52    
53     // 1 --> y
54    
55     // 2 --> z
56    
57     whichDirection = 2;
58    
59    
60    
61     //estimate the force constant of harmonical potential
62    
63     double Kb = 1.986E-3 ; //in kcal/K
64    
65    
66    
67     double halfOfLargestBox = max(info->boxL[0], max(info->boxL[1], info->boxL[2])) /
68    
69     2;
70    
71     zForceConst = Kb * info->target_temp / (halfOfLargestBox * halfOfLargestBox);
72    
73    
74    
75     //creat force Subtraction policy
76    
77     data = info->getPropertyByName(ZCONSFORCEPOLICY_ID);
78    
79     if (!data){
80    
81     sprintf(painCave.errMsg,
82    
83     "ZConstraint Warning: User does not set force Subtraction policy, "
84    
85     "PolicyByMass is used\n");
86    
87     painCave.isFatal = 0;
88    
89     simError();
90    
91    
92    
93     forcePolicy = (ForceSubtractionPolicy *) new PolicyByMass(this);
94    
95     }
96    
97     else{
98    
99     policy = dynamic_cast<StringGenericData*>(data);
100    
101    
102    
103     if (!policy){
104    
105     sprintf(painCave.errMsg,
106    
107     "ZConstraint Error: Convertion from GenericData to StringGenericData failure, "
108    
109     "PolicyByMass is used\n");
110    
111     painCave.isFatal = 0;
112    
113     simError();
114    
115    
116    
117     forcePolicy = (ForceSubtractionPolicy *) new PolicyByMass(this);
118    
119     }
120    
121     else{
122    
123     if (policy->getData() == "BYNUMBER")
124    
125     forcePolicy = (ForceSubtractionPolicy *) new PolicyByNumber(this);
126    
127     else if (policy->getData() == "BYMASS")
128    
129     forcePolicy = (ForceSubtractionPolicy *) new PolicyByMass(this);
130    
131     else{
132    
133     sprintf(painCave.errMsg,
134    
135     "ZConstraint Warning: unknown force Subtraction policy, "
136    
137     "PolicyByMass is used\n");
138    
139     painCave.isFatal = 0;
140    
141     simError();
142    
143     forcePolicy = (ForceSubtractionPolicy *) new PolicyByMass(this);
144    
145     }
146    
147     }
148    
149     }
150    
151    
152    
153    
154    
155     //retrieve sample time of z-contraint
156    
157     data = info->getPropertyByName(ZCONSTIME_ID);
158    
159    
160    
161     if (!data){
162    
163     sprintf(painCave.errMsg,
164    
165     "ZConstraint error: If you use an ZConstraint\n"
166    
167     " , you must set sample time.\n");
168    
169     painCave.isFatal = 1;
170    
171     simError();
172    
173     }
174    
175     else{
176    
177     sampleTime = dynamic_cast<DoubleGenericData*>(data);
178    
179    
180    
181     if (!sampleTime){
182    
183     sprintf(painCave.errMsg,
184    
185     "ZConstraint error: Can not get property from SimInfo\n");
186    
187     painCave.isFatal = 1;
188    
189     simError();
190    
191     }
192    
193     else{
194    
195     this->zconsTime = sampleTime->getData();
196    
197     }
198    
199     }
200    
201    
202    
203     //retrieve output filename of z force
204    
205     data = info->getPropertyByName(ZCONSFILENAME_ID);
206    
207     if (!data){
208    
209     sprintf(painCave.errMsg,
210    
211     "ZConstraint error: If you use an ZConstraint\n"
212    
213     " , you must set output filename of z-force.\n");
214    
215     painCave.isFatal = 1;
216    
217     simError();
218    
219     }
220    
221     else{
222    
223     filename = dynamic_cast<StringGenericData*>(data);
224    
225    
226    
227     if (!filename){
228    
229     sprintf(painCave.errMsg,
230    
231     "ZConstraint error: Can not get property from SimInfo\n");
232    
233     painCave.isFatal = 1;
234    
235     simError();
236    
237     }
238    
239     else{
240    
241     this->zconsOutput = filename->getData();
242    
243     }
244    
245     }
246    
247    
248    
249     //retrieve tolerance for z-constraint molecuels
250    
251     data = info->getPropertyByName(ZCONSTOL_ID);
252    
253    
254    
255     if (!data){
256    
257     sprintf(painCave.errMsg, "ZConstraint error: can not get tolerance \n");
258    
259     painCave.isFatal = 1;
260    
261     simError();
262    
263     }
264    
265     else{
266    
267     tolerance = dynamic_cast<DoubleGenericData*>(data);
268    
269    
270    
271     if (!tolerance){
272    
273     sprintf(painCave.errMsg,
274    
275     "ZConstraint error: Can not get property from SimInfo\n");
276    
277     painCave.isFatal = 1;
278    
279     simError();
280    
281     }
282    
283     else{
284    
285     this->zconsTol = tolerance->getData();
286    
287     }
288    
289     }
290    
291    
292    
293     //quick hack here
294    
295     data = info->getPropertyByName(ZCONSGAP_ID);
296    
297    
298    
299     if (data){
300    
301     gap = dynamic_cast<DoubleGenericData*>(data);
302    
303    
304    
305     if (!gap){
306    
307     sprintf(painCave.errMsg,
308    
309     "ZConstraint error: Can not get property from SimInfo\n");
310    
311     painCave.isFatal = 1;
312    
313     simError();
314    
315     }
316    
317     else{
318    
319     this->hasZConsGap = true;
320    
321     this->zconsGap = gap->getData();
322    
323     }
324    
325     }
326    
327    
328    
329    
330    
331    
332    
333     data = info->getPropertyByName(ZCONSFIXTIME_ID);
334    
335    
336    
337     if (data){
338    
339     fixtime = dynamic_cast<DoubleGenericData*>(data);
340    
341     if (!fixtime){
342    
343     sprintf(painCave.errMsg,
344    
345     "ZConstraint error: Can not get zconsFixTime from SimInfo\n");
346    
347     painCave.isFatal = 1;
348    
349     simError();
350    
351     }
352    
353     else{
354    
355     this->zconsFixTime = fixtime->getData();
356    
357     }
358    
359     }
360    
361     else if(hasZConsGap){
362    
363     sprintf(painCave.errMsg,
364    
365     "ZConstraint error: must set fixtime if already set zconsGap\n");
366    
367     painCave.isFatal = 1;
368    
369     simError();
370    
371     }
372    
373    
374    
375    
376    
377    
378    
379     data = info->getPropertyByName(ZCONSUSINGSMD_ID);
380    
381    
382    
383     if (data){
384    
385     smdFlag = dynamic_cast<IntGenericData*>(data);
386    
387    
388    
389     if (!smdFlag){
390    
391     sprintf(painCave.errMsg,
392    
393     "ZConstraint error: Can not get property from SimInfo\n");
394    
395     painCave.isFatal = 1;
396    
397     simError();
398    
399     }
400    
401     else{
402    
403     this->usingSMD= smdFlag->getData() ? true : false;
404    
405     }
406    
407    
408    
409     }
410    
411    
412    
413    
414    
415    
416    
417     //retrieve index of z-constraint molecules
418    
419     data = info->getPropertyByName(ZCONSPARADATA_ID);
420    
421     if (!data){
422    
423     sprintf(painCave.errMsg,
424    
425     "ZConstraint error: If you use an ZConstraint\n"
426    
427     " , you must set index of z-constraint molecules.\n");
428    
429     painCave.isFatal = 1;
430    
431     simError();
432    
433     }
434    
435     else{
436    
437     zConsParaData = dynamic_cast<ZConsParaData*>(data);
438    
439    
440    
441     if (!zConsParaData){
442    
443     sprintf(painCave.errMsg,
444    
445     "ZConstraint error: Can not get parameters of zconstraint method from SimInfo\n");
446    
447     painCave.isFatal = 1;
448    
449     simError();
450    
451     }
452    
453     else{
454    
455     parameters = zConsParaData->getData();
456    
457    
458    
459     //check the range of zconsIndex
460    
461     //and the minimum value of index is the first one (we already sorted the data)
462    
463     //the maximum value of index is the last one
464    
465    
466    
467     int maxIndex;
468    
469     int minIndex;
470    
471     int totalNumMol;
472    
473    
474    
475     minIndex = (*parameters)[0].zconsIndex;
476    
477     if (minIndex < 0){
478    
479     sprintf(painCave.errMsg, "ZConstraint error: index is out of range\n");
480    
481     painCave.isFatal = 1;
482    
483     simError();
484    
485     }
486    
487    
488    
489     maxIndex = (*parameters)[parameters->size() - 1].zconsIndex;
490    
491    
492    
493     #ifndef IS_MPI
494    
495     totalNumMol = nMols;
496    
497     #else
498    
499     totalNumMol = mpiSim->getNMolGlobal();
500    
501     #endif
502    
503    
504    
505     if (maxIndex > totalNumMol - 1){
506    
507     sprintf(painCave.errMsg, "ZConstraint error: index is out of range\n");
508    
509     painCave.isFatal = 1;
510    
511     simError();
512    
513     }
514    
515    
516    
517     //if user does not specify the zpos for the zconstraint molecule
518    
519     //its initial z coordinate will be used as default
520    
521     for (int i = 0; i < (int) (parameters->size()); i++){
522    
523     if (!(*parameters)[i].havingZPos){
524    
525     #ifndef IS_MPI
526    
527     for (int j = 0; j < nMols; j++){
528    
529     if (molecules[j].getGlobalIndex() == (*parameters)[i].zconsIndex){
530    
531     molecules[j].getCOM(COM);
532    
533     break;
534    
535     }
536    
537     }
538    
539     #else
540    
541     //query which processor current zconstraint molecule belongs to
542    
543     int* MolToProcMap;
544    
545     int whichNode;
546    
547    
548    
549     MolToProcMap = mpiSim->getMolToProcMap();
550    
551     whichNode = MolToProcMap[(*parameters)[i].zconsIndex];
552    
553    
554    
555     //broadcast the zpos of current z-contraint molecule
556    
557     //the node which contain this
558    
559    
560    
561     if (worldRank == whichNode){
562    
563     for (int j = 0; j < nMols; j++)
564    
565     if (molecules[j].getGlobalIndex() == (*parameters)[i].zconsIndex){
566    
567     molecules[j].getCOM(COM);
568    
569     break;
570    
571     }
572    
573     }
574    
575    
576    
577     MPI_Bcast(&COM[whichDirection], 1, MPI_DOUBLE, whichNode,
578    
579     MPI_COMM_WORLD);
580    
581     #endif
582    
583    
584    
585     (*parameters)[i].zPos = COM[whichDirection];
586    
587    
588    
589     sprintf(painCave.errMsg,
590    
591     "ZConstraint warning: Does not specify zpos for z-constraint molecule "
592    
593     "initial z coornidate will be used \n");
594    
595     painCave.isFatal = 0;
596    
597     simError();
598    
599     }
600    
601     }
602    
603     }//end if (!zConsParaData)
604    
605    
606    
607     }//end if (!data)
608    
609    
610    
611     //
612    
613     #ifdef IS_MPI
614    
615     update();
616    
617     #else
618    
619     int searchResult;
620    
621    
622    
623     for (int i = 0; i < nMols; i++){
624    
625     searchResult = isZConstraintMol(&molecules[i]);
626    
627    
628    
629     if (searchResult > -1){
630    
631     zconsMols.push_back(&molecules[i]);
632    
633     massOfZConsMols.push_back(molecules[i].getTotalMass());
634    
635    
636    
637     zPos.push_back((*parameters)[searchResult].zPos);
638    
639     kz.push_back((*parameters)[searchResult]. kRatio * zForceConst);
640    
641    
642    
643     if(usingSMD)
644    
645     cantVel.push_back((*parameters)[searchResult].cantVel);
646    
647    
648    
649     }
650    
651     else{
652    
653     unconsMols.push_back(&molecules[i]);
654    
655     massOfUnconsMols.push_back(molecules[i].getTotalMass());
656    
657     }
658    
659     }
660    
661    
662    
663     fz.resize(zconsMols.size());
664    
665     curZPos.resize(zconsMols.size());
666    
667     indexOfZConsMols.resize(zconsMols.size());
668    
669    
670    
671     //determine the states of z-constraint molecules
672    
673     for (size_t i = 0; i < zconsMols.size(); i++){
674    
675     indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex();
676    
677    
678    
679     zconsMols[i]->getCOM(COM);
680    
681    
682    
683     if (fabs(zPos[i] - COM[whichDirection]) < zconsTol){
684    
685     states.push_back(zcsFixed);
686    
687    
688    
689     if (hasZConsGap)
690    
691     endFixTime.push_back(info->getTime() + zconsFixTime);
692    
693     }
694    
695     else{
696    
697     states.push_back(zcsMoving);
698    
699    
700    
701     if (hasZConsGap)
702    
703     endFixTime.push_back(INFINITE_TIME);
704    
705     }
706    
707    
708    
709     if(usingSMD)
710    
711     cantPos.push_back(COM[whichDirection]);
712    
713     }
714    
715    
716    
717     if(usingSMD)
718    
719     prevCantPos = cantPos;
720    
721     #endif
722    
723    
724    
725    
726    
727     //get total masss of unconstraint molecules
728    
729     double totalMassOfUncons_local;
730    
731     totalMassOfUncons_local = 0;
732    
733    
734    
735     for (size_t i = 0; i < unconsMols.size(); i++)
736    
737     totalMassOfUncons_local += unconsMols[i]->getTotalMass();
738    
739    
740    
741     #ifndef IS_MPI
742    
743     totalMassOfUncons = totalMassOfUncons_local;
744    
745     #else
746    
747     MPI_Allreduce(&totalMassOfUncons_local, &totalMassOfUncons, 1, MPI_DOUBLE,
748    
749     MPI_SUM, MPI_COMM_WORLD);
750    
751     #endif
752    
753    
754    
755     //get total number of unconstrained atoms
756    
757     int nUnconsAtoms_local;
758    
759     nUnconsAtoms_local = 0;
760    
761     for (int i = 0; i < (int) (unconsMols.size()); i++)
762    
763     nUnconsAtoms_local += unconsMols[i]->getNAtoms();
764    
765    
766    
767     #ifndef IS_MPI
768    
769     totNumOfUnconsAtoms = nUnconsAtoms_local;
770    
771     #else
772    
773     MPI_Allreduce(&nUnconsAtoms_local, &totNumOfUnconsAtoms, 1, MPI_INT, MPI_SUM,
774    
775     MPI_COMM_WORLD);
776    
777     #endif
778    
779    
780    
781     forcePolicy->update();
782    
783     }
784    
785    
786    
787     template<typename T> ZConstraint<T>::~ZConstraint(){
788    
789    
790    
791     if (fzOut){
792    
793     delete fzOut;
794    
795     }
796    
797    
798    
799     if (forcePolicy){
800    
801     delete forcePolicy;
802    
803     }
804    
805     }
806    
807    
808    
809    
810    
811     /**
812    
813     *
814    
815     */
816    
817    
818    
819     #ifdef IS_MPI
820    
821     template<typename T> void ZConstraint<T>::update(){
822    
823     double COM[3];
824    
825     int index;
826    
827    
828    
829     zconsMols.clear();
830    
831     massOfZConsMols.clear();
832    
833     zPos.clear();
834    
835     kz.clear();
836    
837     cantPos.clear();
838    
839     cantVel.clear();
840    
841    
842    
843     unconsMols.clear();
844    
845     massOfUnconsMols.clear();
846    
847    
848    
849    
850    
851     //creat zconsMol and unconsMol lists
852    
853     for (int i = 0; i < nMols; i++){
854    
855     index = isZConstraintMol(&molecules[i]);
856    
857    
858    
859     if (index > -1){
860    
861     zconsMols.push_back(&molecules[i]);
862    
863     zPos.push_back((*parameters)[index].zPos);
864    
865     kz.push_back((*parameters)[index].kRatio * zForceConst);
866    
867     massOfZConsMols.push_back(molecules[i].getTotalMass());
868    
869    
870    
871     if(usingSMD)
872    
873     cantVel.push_back((*parameters)[index].cantVel);
874    
875    
876    
877     }
878    
879     else{
880    
881     unconsMols.push_back(&molecules[i]);
882    
883     massOfUnconsMols.push_back(molecules[i].getTotalMass());
884    
885     }
886    
887     }
888    
889    
890    
891     fz.resize(zconsMols.size());
892    
893     curZPos.resize(zconsMols.size());
894    
895     indexOfZConsMols.resize(zconsMols.size());
896    
897    
898    
899     for (size_t i = 0; i < zconsMols.size(); i++){
900    
901     indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex();
902    
903     }
904    
905    
906    
907     //determine the states of z-constraint molecules
908    
909     for (int i = 0; i < (int) (zconsMols.size()); i++){
910    
911    
912    
913     zconsMols[i]->getCOM(COM);
914    
915    
916    
917     if (fabs(zPos[i] - COM[whichDirection]) < zconsTol){
918    
919     states.push_back(zcsFixed);
920    
921    
922    
923     if (hasZConsGap)
924    
925     endFixTime.push_back(info->getTime() + zconsFixTime);
926    
927     }
928    
929     else{
930    
931     states.push_back(zcsMoving);
932    
933    
934    
935     if (hasZConsGap)
936    
937     endFixTime.push_back(INFINITE_TIME);
938    
939     }
940    
941    
942    
943     if(usingSMD)
944    
945     cantPos.push_back(COM[whichDirection]);
946    
947     }
948    
949    
950    
951     if(usingSMD)
952    
953     prevCantPos = cantPos;
954    
955    
956    
957     forcePolicy->update();
958    
959     }
960    
961    
962    
963     #endif
964    
965    
966    
967     /**
968    
969     * Function Name: isZConstraintMol
970    
971     * Parameter
972    
973     * Molecule* mol
974    
975     * Return value:
976    
977     * -1, if the molecule is not z-constraint molecule,
978    
979     * other non-negative values, its index in indexOfAllZConsMols vector
980    
981     */
982    
983    
984    
985     template<typename T> int ZConstraint<T>::isZConstraintMol(Molecule* mol){
986    
987     int index;
988    
989     int low;
990    
991     int high;
992    
993     int mid;
994    
995    
996    
997     index = mol->getGlobalIndex();
998    
999    
1000    
1001     low = 0;
1002    
1003     high = parameters->size() - 1;
1004    
1005    
1006    
1007     //Binary Search (we have sorted the array)
1008    
1009     while (low <= high){
1010    
1011     mid = (low + high) / 2;
1012    
1013     if ((*parameters)[mid].zconsIndex == index)
1014    
1015     return mid;
1016    
1017     else if ((*parameters)[mid].zconsIndex > index)
1018    
1019     high = mid - 1;
1020    
1021     else
1022    
1023     low = mid + 1;
1024    
1025     }
1026    
1027    
1028    
1029     return -1;
1030    
1031     }
1032    
1033    
1034    
1035     template<typename T> void ZConstraint<T>::integrate(){
1036    
1037     // creat zconsWriter
1038    
1039     fzOut = new ZConsWriter(zconsOutput.c_str(), parameters);
1040    
1041    
1042    
1043     if (!fzOut){
1044    
1045     sprintf(painCave.errMsg, "Memory allocation failure in class Zconstraint\n");
1046    
1047     painCave.isFatal = 1;
1048    
1049     simError();
1050    
1051     }
1052    
1053    
1054    
1055     //zero out the velocities of center of mass of unconstrained molecules
1056    
1057     //and the velocities of center of mass of every single z-constrained molecueles
1058    
1059     zeroOutVel();
1060    
1061    
1062    
1063     curZconsTime = zconsTime + info->getTime();
1064    
1065    
1066    
1067     T::integrate();
1068    
1069     }
1070    
1071    
1072    
1073     template<typename T> void ZConstraint<T>::calcForce(int calcPot, int calcStress){
1074    
1075     double zsys;
1076    
1077     double COM[3];
1078    
1079     double force[3];
1080    
1081     double zSysCOMVel;
1082    
1083    
1084    
1085     T::calcForce(calcPot, calcStress);
1086    
1087    
1088    
1089    
1090    
1091     if (hasZConsGap){
1092    
1093     updateZPos();
1094    
1095     }
1096    
1097    
1098    
1099     if (checkZConsState()){
1100    
1101     zeroOutVel();
1102    
1103     forcePolicy->update();
1104    
1105     }
1106    
1107    
1108    
1109     zsys = calcZSys();
1110    
1111     zSysCOMVel = calcSysCOMVel();
1112    
1113     #ifdef IS_MPI
1114    
1115     if (worldRank == 0){
1116    
1117     #endif
1118    
1119    
1120    
1121     #ifdef IS_MPI
1122    
1123     }
1124    
1125     #endif
1126    
1127    
1128    
1129     //do zconstraint force;
1130    
1131     if (haveFixedZMols()){
1132    
1133     this->doZconstraintForce();
1134    
1135     }
1136    
1137    
1138    
1139     //use external force to move the molecules to the specified positions
1140    
1141     if (haveMovingZMols()){
1142    
1143     if (usingSMD)
1144    
1145     this->doHarmonic(cantPos);
1146    
1147     else
1148    
1149     this->doHarmonic(zPos);
1150    
1151     }
1152    
1153    
1154    
1155     //write out forces and current positions of z-constraint molecules
1156    
1157     if (info->getTime() >= curZconsTime){
1158    
1159     for (int i = 0; i < (int) (zconsMols.size()); i++){
1160    
1161     zconsMols[i]->getCOM(COM);
1162    
1163     curZPos[i] = COM[whichDirection];
1164    
1165    
1166    
1167     //if the z-constraint molecule is still moving, just record its force
1168    
1169     if (states[i] == zcsMoving){
1170    
1171     fz[i] = 0;
1172    
1173     Atom** movingZAtoms;
1174    
1175     movingZAtoms = zconsMols[i]->getMyAtoms();
1176    
1177     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
1178    
1179     movingZAtoms[j]->getFrc(force);
1180    
1181     fz[i] += force[whichDirection];
1182    
1183     }
1184    
1185     }
1186    
1187     }
1188    
1189     fzOut->writeFZ(info->getTime(), zconsMols.size(), &indexOfZConsMols[0], &fz[0],
1190    
1191     &curZPos[0], &zPos[0]);
1192    
1193     curZconsTime += zconsTime;
1194    
1195     }
1196    
1197    
1198    
1199     zSysCOMVel = calcSysCOMVel();
1200    
1201     #ifdef IS_MPI
1202    
1203     if (worldRank == 0){
1204    
1205     #endif
1206    
1207     #ifdef IS_MPI
1208    
1209     }
1210    
1211     #endif
1212    
1213     }
1214    
1215    
1216    
1217    
1218    
1219     template<typename T> double ZConstraint<T>::calcZSys(){
1220    
1221     //calculate reference z coordinate for z-constraint molecules
1222    
1223     double totalMass_local;
1224    
1225     double totalMass;
1226    
1227     double totalMZ_local;
1228    
1229     double totalMZ;
1230    
1231     double massOfCurMol;
1232    
1233     double COM[3];
1234    
1235    
1236    
1237     totalMass_local = 0;
1238    
1239     totalMZ_local = 0;
1240    
1241    
1242    
1243     for (int i = 0; i < nMols; i++){
1244    
1245     massOfCurMol = molecules[i].getTotalMass();
1246    
1247     molecules[i].getCOM(COM);
1248    
1249    
1250    
1251     totalMass_local += massOfCurMol;
1252    
1253     totalMZ_local += massOfCurMol * COM[whichDirection];
1254    
1255     }
1256    
1257    
1258    
1259    
1260    
1261     #ifdef IS_MPI
1262    
1263     MPI_Allreduce(&totalMass_local, &totalMass, 1, MPI_DOUBLE, MPI_SUM,
1264    
1265     MPI_COMM_WORLD);
1266    
1267     MPI_Allreduce(&totalMZ_local, &totalMZ, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
1268    
1269     #else
1270    
1271     totalMass = totalMass_local;
1272    
1273     totalMZ = totalMZ_local;
1274    
1275     #endif
1276    
1277    
1278    
1279     double zsys;
1280    
1281     zsys = totalMZ / totalMass;
1282    
1283    
1284    
1285     return zsys;
1286    
1287     }
1288    
1289    
1290    
1291     template<typename T> void ZConstraint<T>::thermalize(void){
1292    
1293     T::thermalize();
1294    
1295     zeroOutVel();
1296    
1297     }
1298    
1299    
1300    
1301     template<typename T> void ZConstraint<T>::zeroOutVel(){
1302    
1303     Atom** fixedZAtoms;
1304    
1305     double COMvel[3];
1306    
1307     double vel[3];
1308    
1309     double zSysCOMVel;
1310    
1311    
1312    
1313     //zero out the velocities of center of mass of fixed z-constrained molecules
1314    
1315    
1316    
1317     for (int i = 0; i < (int) (zconsMols.size()); i++){
1318    
1319     if (states[i] == zcsFixed){
1320    
1321     zconsMols[i]->getCOMvel(COMvel);
1322    
1323     //cout << "before resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << std::endl;
1324    
1325    
1326    
1327     fixedZAtoms = zconsMols[i]->getMyAtoms();
1328    
1329    
1330    
1331     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
1332    
1333     vel = fixedZAtoms[j]->getVel();
1334    
1335     vel[whichDirection] -= COMvel[whichDirection];
1336    
1337     fixedZAtoms[j]->setVel(vel);
1338    
1339     }
1340    
1341    
1342    
1343     zconsMols[i]->getCOMvel(COMvel);
1344    
1345     }
1346    
1347     }
1348    
1349    
1350    
1351     zSysCOMVel = calcSysCOMVel();
1352    
1353     #ifdef IS_MPI
1354    
1355     if (worldRank == 0){
1356    
1357     #endif
1358    
1359     #ifdef IS_MPI
1360    
1361     }
1362    
1363     #endif
1364    
1365    
1366    
1367     // calculate the vz of center of mass of unconstrained molecules and moving z-constrained molecules
1368    
1369     double MVzOfMovingMols_local;
1370    
1371     double MVzOfMovingMols;
1372    
1373     double totalMassOfMovingZMols_local;
1374    
1375     double totalMassOfMovingZMols;
1376    
1377    
1378    
1379     MVzOfMovingMols_local = 0;
1380    
1381     totalMassOfMovingZMols_local = 0;
1382    
1383    
1384    
1385     for (int i = 0; i < (int) (unconsMols.size()); i++){
1386    
1387     unconsMols[i]->getCOMvel(COMvel);
1388    
1389     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
1390    
1391     }
1392    
1393    
1394    
1395     for (int i = 0; i < (int) (zconsMols.size()); i++){
1396    
1397     if (states[i] == zcsMoving){
1398    
1399     zconsMols[i]->getCOMvel(COMvel);
1400    
1401     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
1402    
1403     totalMassOfMovingZMols_local += massOfZConsMols[i];
1404    
1405     }
1406    
1407     }
1408    
1409    
1410    
1411     #ifndef IS_MPI
1412    
1413     MVzOfMovingMols = MVzOfMovingMols_local;
1414    
1415     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
1416    
1417     #else
1418    
1419     MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,
1420    
1421     MPI_SUM, MPI_COMM_WORLD);
1422    
1423     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1,
1424    
1425     MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
1426    
1427     #endif
1428    
1429    
1430    
1431     double vzOfMovingMols;
1432    
1433     vzOfMovingMols = MVzOfMovingMols /
1434    
1435     (totalMassOfUncons + totalMassOfMovingZMols);
1436    
1437    
1438    
1439     //modify the velocites of unconstrained molecules
1440    
1441     Atom** unconsAtoms;
1442    
1443     for (int i = 0; i < (int) (unconsMols.size()); i++){
1444    
1445     unconsAtoms = unconsMols[i]->getMyAtoms();
1446    
1447     for (int j = 0; j < unconsMols[i]->getNAtoms(); j++){
1448    
1449     vel = unconsAtoms[j]->getVel();
1450    
1451     vel[whichDirection] -= vzOfMovingMols;
1452    
1453     unconsAtoms[j]->setVel(vel);
1454    
1455     }
1456    
1457     }
1458    
1459    
1460    
1461     //modify the velocities of moving z-constrained molecuels
1462    
1463     Atom** movingZAtoms;
1464    
1465     for (int i = 0; i < (int) (zconsMols.size()); i++){
1466    
1467     if (states[i] == zcsMoving){
1468    
1469     movingZAtoms = zconsMols[i]->getMyAtoms();
1470    
1471     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
1472    
1473     vel = movingZAtoms[j]->getVel();
1474    
1475     vel[whichDirection] -= vzOfMovingMols;
1476    
1477     movingZAtoms[j]->setVel(vel);
1478    
1479     }
1480    
1481     }
1482    
1483     }
1484    
1485    
1486    
1487    
1488    
1489     zSysCOMVel = calcSysCOMVel();
1490    
1491     #ifdef IS_MPI
1492    
1493     if (worldRank == 0){
1494    
1495     #endif
1496    
1497     #ifdef IS_MPI
1498    
1499     }
1500    
1501     #endif
1502    
1503     }
1504    
1505    
1506    
1507    
1508    
1509     template<typename T> void ZConstraint<T>::doZconstraintForce(){
1510    
1511     Atom** zconsAtoms;
1512    
1513     double totalFZ;
1514    
1515     double totalFZ_local;
1516    
1517     double COM[3];
1518    
1519     double force[3];
1520    
1521    
1522    
1523     //constrain the molecules which do not reach the specified positions
1524    
1525    
1526    
1527     //Zero Out the force of z-contrained molecules
1528    
1529     totalFZ_local = 0;
1530    
1531    
1532    
1533     //calculate the total z-contrained force of fixed z-contrained molecules
1534    
1535    
1536    
1537     for (int i = 0; i < (int) (zconsMols.size()); i++){
1538    
1539     if (states[i] == zcsFixed){
1540    
1541     zconsMols[i]->getCOM(COM);
1542    
1543     zconsAtoms = zconsMols[i]->getMyAtoms();
1544    
1545    
1546    
1547     fz[i] = 0;
1548    
1549     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
1550    
1551     zconsAtoms[j]->getFrc(force);
1552    
1553     fz[i] += force[whichDirection];
1554    
1555     }
1556    
1557     totalFZ_local += fz[i];
1558    
1559    
1560    
1561     }
1562    
1563     }
1564    
1565    
1566    
1567     //calculate total z-constraint force
1568    
1569     #ifdef IS_MPI
1570    
1571     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
1572    
1573     #else
1574    
1575     totalFZ = totalFZ_local;
1576    
1577     #endif
1578    
1579    
1580    
1581    
1582    
1583     // apply negative to fixed z-constrained molecues;
1584    
1585     force[0] = 0;
1586    
1587     force[1] = 0;
1588    
1589     force[2] = 0;
1590    
1591    
1592    
1593     for (int i = 0; i < (int) (zconsMols.size()); i++){
1594    
1595     if (states[i] == zcsFixed){
1596    
1597     int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms();
1598    
1599     zconsAtoms = zconsMols[i]->getMyAtoms();
1600    
1601    
1602    
1603     for (int j = 0; j < nAtomOfCurZConsMol; j++){
1604    
1605     //force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol;
1606    
1607     force[whichDirection] = -forcePolicy->getZFOfFixedZMols(zconsMols[i],
1608    
1609     zconsAtoms[j],
1610    
1611     fz[i]);
1612    
1613     zconsAtoms[j]->addFrc(force);
1614    
1615     }
1616    
1617     }
1618    
1619     }
1620    
1621    
1622    
1623     force[0] = 0;
1624    
1625     force[1] = 0;
1626    
1627     force[2] = 0;
1628    
1629    
1630    
1631     //modify the forces of unconstrained molecules
1632    
1633     for (int i = 0; i < (int) (unconsMols.size()); i++){
1634    
1635     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
1636    
1637    
1638    
1639     for (int j = 0; j < unconsMols[i]->getNAtoms(); j++){
1640    
1641     //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
1642    
1643     force[whichDirection] = forcePolicy->getZFOfMovingMols(unconsAtoms[j],
1644    
1645     totalFZ);
1646    
1647     unconsAtoms[j]->addFrc(force);
1648    
1649     }
1650    
1651     }
1652    
1653    
1654    
1655     //modify the forces of moving z-constrained molecules
1656    
1657     for (int i = 0; i < (int) (zconsMols.size()); i++){
1658    
1659     if (states[i] == zcsMoving){
1660    
1661     Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
1662    
1663    
1664    
1665     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
1666    
1667     //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms);
1668    
1669     force[whichDirection] = forcePolicy->getZFOfMovingMols(movingZAtoms[j],
1670    
1671     totalFZ);
1672    
1673     movingZAtoms[j]->addFrc(force);
1674    
1675     }
1676    
1677     }
1678    
1679     }
1680    
1681     }
1682    
1683    
1684    
1685    
1686    
1687     template<typename T> void ZConstraint<T>::doHarmonic(vector<double>& resPos){
1688    
1689     double force[3];
1690    
1691     double harmonicU;
1692    
1693     double harmonicF;
1694    
1695     double COM[3];
1696    
1697     double diff;
1698    
1699     double totalFZ_local;
1700    
1701     double totalFZ;
1702    
1703    
1704    
1705     force[0] = 0;
1706    
1707     force[1] = 0;
1708    
1709     force[2] = 0;
1710    
1711    
1712    
1713     totalFZ_local = 0;
1714    
1715    
1716    
1717     for (int i = 0; i < (int) (zconsMols.size()); i++){
1718    
1719     if (states[i] == zcsMoving){
1720    
1721     zconsMols[i]->getCOM(COM);
1722    
1723    
1724    
1725     diff = COM[whichDirection] - resPos[i];
1726    
1727    
1728    
1729     harmonicU = 0.5 * kz[i] * diff * diff;
1730    
1731     info->lrPot += harmonicU;
1732    
1733    
1734    
1735     harmonicF = -kz[i] * diff;
1736    
1737     totalFZ_local += harmonicF;
1738    
1739    
1740    
1741     //adjust force
1742    
1743    
1744    
1745     Atom** movingZAtoms = zconsMols[i]->getMyAtoms();
1746    
1747    
1748    
1749     for (int j = 0; j < zconsMols[i]->getNAtoms(); j++){
1750    
1751     force[whichDirection] = forcePolicy->getHFOfFixedZMols(zconsMols[i],
1752    
1753     movingZAtoms[j],
1754    
1755     harmonicF);
1756    
1757     movingZAtoms[j]->addFrc(force);
1758    
1759     }
1760    
1761     }
1762    
1763     }
1764    
1765    
1766    
1767     #ifndef IS_MPI
1768    
1769     totalFZ = totalFZ_local;
1770    
1771     #else
1772    
1773     MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
1774    
1775     #endif
1776    
1777    
1778    
1779     force[0] = 0;
1780    
1781     force[1] = 0;
1782    
1783     force[2] = 0;
1784    
1785    
1786    
1787     //modify the forces of unconstrained molecules
1788    
1789     for (int i = 0; i < (int) (unconsMols.size()); i++){
1790    
1791     Atom** unconsAtoms = unconsMols[i]->getMyAtoms();
1792    
1793    
1794    
1795     for (int j = 0; j < unconsMols[i]->getNAtoms(); j++){
1796    
1797     //force[whichDirection] = - totalFZ /totNumOfUnconsAtoms;
1798    
1799     force[whichDirection] = -forcePolicy->getHFOfUnconsMols(unconsAtoms[j],
1800    
1801     totalFZ);
1802    
1803     unconsAtoms[j]->addFrc(force);
1804    
1805     }
1806    
1807     }
1808    
1809    
1810    
1811     }
1812    
1813    
1814    
1815     template<typename T> bool ZConstraint<T>::checkZConsState(){
1816    
1817     double COM[3];
1818    
1819     double diff;
1820    
1821    
1822    
1823     int changed_local;
1824    
1825     int changed;
1826    
1827    
1828    
1829     changed_local = 0;
1830    
1831    
1832    
1833     for (int i = 0; i < (int) (zconsMols.size()); i++){
1834    
1835     zconsMols[i]->getCOM(COM);
1836    
1837     diff = fabs(COM[whichDirection] - zPos[i]);
1838    
1839     if (diff <= zconsTol && states[i] == zcsMoving){
1840    
1841     states[i] = zcsFixed;
1842    
1843     changed_local = 1;
1844    
1845    
1846    
1847     if(usingSMD)
1848    
1849     prevCantPos = cantPos;
1850    
1851    
1852    
1853     if (hasZConsGap)
1854    
1855     endFixTime[i] = info->getTime() + zconsFixTime;
1856    
1857     }
1858    
1859     else if (diff > zconsTol && states[i] == zcsFixed){
1860    
1861     states[i] = zcsMoving;
1862    
1863     changed_local = 1;
1864    
1865    
1866    
1867     if(usingSMD)
1868    
1869     cantPos = prevCantPos;
1870    
1871    
1872    
1873     if (hasZConsGap)
1874    
1875     endFixTime[i] = INFINITE_TIME;
1876    
1877     }
1878    
1879     }
1880    
1881    
1882    
1883     #ifndef IS_MPI
1884    
1885     changed = changed_local;
1886    
1887     #else
1888    
1889     MPI_Allreduce(&changed_local, &changed, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
1890    
1891     #endif
1892    
1893    
1894    
1895     return (changed > 0);
1896    
1897     }
1898    
1899    
1900    
1901     template<typename T> bool ZConstraint<T>::haveFixedZMols(){
1902    
1903     int havingFixed_local;
1904    
1905     int havingFixed;
1906    
1907    
1908    
1909     havingFixed_local = 0;
1910    
1911    
1912    
1913     for (int i = 0; i < (int) (zconsMols.size()); i++)
1914    
1915     if (states[i] == zcsFixed){
1916    
1917     havingFixed_local = 1;
1918    
1919     break;
1920    
1921     }
1922    
1923    
1924    
1925     #ifndef IS_MPI
1926    
1927     havingFixed = havingFixed_local;
1928    
1929     #else
1930    
1931     MPI_Allreduce(&havingFixed_local, &havingFixed, 1, MPI_INT, MPI_SUM,
1932    
1933     MPI_COMM_WORLD);
1934    
1935     #endif
1936    
1937    
1938    
1939     return (havingFixed > 0);
1940    
1941     }
1942    
1943    
1944    
1945    
1946    
1947     template<typename T> bool ZConstraint<T>::haveMovingZMols(){
1948    
1949     int havingMoving_local;
1950    
1951     int havingMoving;
1952    
1953    
1954    
1955     havingMoving_local = 0;
1956    
1957    
1958    
1959     for (int i = 0; i < (int) (zconsMols.size()); i++)
1960    
1961     if (states[i] == zcsMoving){
1962    
1963     havingMoving_local = 1;
1964    
1965     break;
1966    
1967     }
1968    
1969    
1970    
1971     #ifndef IS_MPI
1972    
1973     havingMoving = havingMoving_local;
1974    
1975     #else
1976    
1977     MPI_Allreduce(&havingMoving_local, &havingMoving, 1, MPI_INT, MPI_SUM,
1978    
1979     MPI_COMM_WORLD);
1980    
1981     #endif
1982    
1983    
1984    
1985     return (havingMoving > 0);
1986    
1987     }
1988    
1989    
1990    
1991    
1992    
1993     template<typename T> double ZConstraint<T>::calcMovingMolsCOMVel(){
1994    
1995     double MVzOfMovingMols_local;
1996    
1997     double MVzOfMovingMols;
1998    
1999     double totalMassOfMovingZMols_local;
2000    
2001     double totalMassOfMovingZMols;
2002    
2003     double COMvel[3];
2004    
2005    
2006    
2007     MVzOfMovingMols_local = 0;
2008    
2009     totalMassOfMovingZMols_local = 0;
2010    
2011    
2012    
2013     for (int i = 0; i < unconsMols.size(); i++){
2014    
2015     unconsMols[i]->getCOMvel(COMvel);
2016    
2017     MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection];
2018    
2019     }
2020    
2021    
2022    
2023     for (int i = 0; i < zconsMols.size(); i++){
2024    
2025     if (states[i] == zcsMoving){
2026    
2027     zconsMols[i]->getCOMvel(COMvel);
2028    
2029     MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection];
2030    
2031     totalMassOfMovingZMols_local += massOfZConsMols[i];
2032    
2033     }
2034    
2035     }
2036    
2037    
2038    
2039     #ifndef IS_MPI
2040    
2041     MVzOfMovingMols = MVzOfMovingMols_local;
2042    
2043     totalMassOfMovingZMols = totalMassOfMovingZMols_local;
2044    
2045     #else
2046    
2047     MPI_Allreduce(&MVzOfMovingMols_local, &MVzOfMovingMols, 1, MPI_DOUBLE,
2048    
2049     MPI_SUM, MPI_COMM_WORLD);
2050    
2051     MPI_Allreduce(&totalMassOfMovingZMols_local, &totalMassOfMovingZMols, 1,
2052    
2053     MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
2054    
2055     #endif
2056    
2057    
2058    
2059     double vzOfMovingMols;
2060    
2061     vzOfMovingMols = MVzOfMovingMols /
2062    
2063     (totalMassOfUncons + totalMassOfMovingZMols);
2064    
2065    
2066    
2067     return vzOfMovingMols;
2068    
2069     }
2070    
2071    
2072    
2073     template<typename T> double ZConstraint<T>::calcSysCOMVel(){
2074    
2075     double COMvel[3];
2076    
2077     double tempMVz_local;
2078    
2079     double tempMVz;
2080    
2081     double massOfZCons_local;
2082    
2083     double massOfZCons;
2084    
2085    
2086    
2087    
2088    
2089     tempMVz_local = 0;
2090    
2091    
2092    
2093     for (int i = 0 ; i < nMols; i++){
2094    
2095     molecules[i].getCOMvel(COMvel);
2096    
2097     tempMVz_local += molecules[i].getTotalMass() * COMvel[whichDirection];
2098    
2099     }
2100    
2101    
2102    
2103     massOfZCons_local = 0;
2104    
2105    
2106    
2107     for (int i = 0; i < (int) (massOfZConsMols.size()); i++){
2108    
2109     massOfZCons_local += massOfZConsMols[i];
2110    
2111     }
2112    
2113     #ifndef IS_MPI
2114    
2115     massOfZCons = massOfZCons_local;
2116    
2117     tempMVz = tempMVz_local;
2118    
2119     #else
2120    
2121     MPI_Allreduce(&massOfZCons_local, &massOfZCons, 1, MPI_DOUBLE, MPI_SUM,
2122    
2123     MPI_COMM_WORLD);
2124    
2125     MPI_Allreduce(&tempMVz_local, &tempMVz, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
2126    
2127     #endif
2128    
2129    
2130    
2131     return tempMVz / (totalMassOfUncons + massOfZCons);
2132    
2133     }
2134    
2135    
2136    
2137     template<typename T> double ZConstraint<T>::calcTotalForce(){
2138    
2139     double force[3];
2140    
2141     double totalForce_local;
2142    
2143     double totalForce;
2144    
2145    
2146    
2147     totalForce_local = 0;
2148    
2149    
2150    
2151     for (int i = 0; i < nAtoms; i++){
2152    
2153     atoms[i]->getFrc(force);
2154    
2155     totalForce_local += force[whichDirection];
2156    
2157     }
2158    
2159    
2160    
2161     #ifndef IS_MPI
2162    
2163     totalForce = totalForce_local;
2164    
2165     #else
2166    
2167     MPI_Allreduce(&totalForce_local, &totalForce, 1, MPI_DOUBLE, MPI_SUM,
2168    
2169     MPI_COMM_WORLD);
2170    
2171     #endif
2172    
2173    
2174    
2175     return totalForce;
2176    
2177     }
2178    
2179    
2180    
2181     template<typename T> void ZConstraint<T>::PolicyByNumber::update(){
2182    
2183     //calculate the number of atoms of moving z-constrained molecules
2184    
2185     int nMovingZAtoms_local;
2186    
2187     int nMovingZAtoms;
2188    
2189    
2190    
2191     nMovingZAtoms_local = 0;
2192    
2193     for (int i = 0; i < (int) ((zconsIntegrator->zconsMols).size()); i++)
2194    
2195     if ((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving)){
2196    
2197     nMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getNAtoms();
2198    
2199     }
2200    
2201    
2202    
2203     #ifdef IS_MPI
2204    
2205     MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1, MPI_INT, MPI_SUM,
2206    
2207     MPI_COMM_WORLD);
2208    
2209     #else
2210    
2211     nMovingZAtoms = nMovingZAtoms_local;
2212    
2213     #endif
2214    
2215     totNumOfMovingAtoms = nMovingZAtoms + zconsIntegrator->totNumOfUnconsAtoms;
2216    
2217     }
2218    
2219    
2220    
2221     template<typename T> double ZConstraint<T>::PolicyByNumber::getZFOfFixedZMols(Molecule* mol,
2222    
2223     Atom* atom,
2224    
2225     double totalForce){
2226    
2227     return totalForce / mol->getNAtoms();
2228    
2229     }
2230    
2231    
2232    
2233     template<typename T> double ZConstraint<T>::PolicyByNumber::getZFOfMovingMols(Atom* atom,
2234    
2235     double totalForce){
2236    
2237     return totalForce / totNumOfMovingAtoms;
2238    
2239     }
2240    
2241    
2242    
2243     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfFixedZMols(Molecule* mol,
2244    
2245     Atom* atom,
2246    
2247     double totalForce){
2248    
2249     return totalForce / mol->getNAtoms();
2250    
2251     }
2252    
2253    
2254    
2255     template<typename T> double ZConstraint<T>::PolicyByNumber::getHFOfUnconsMols(Atom* atom,
2256    
2257     double totalForce){
2258    
2259     return totalForce / zconsIntegrator->totNumOfUnconsAtoms;
2260    
2261     }
2262    
2263    
2264    
2265    
2266    
2267     template<typename T> void ZConstraint<T>::PolicyByMass::update(){
2268    
2269     //calculate the number of atoms of moving z-constrained molecules
2270    
2271     double massOfMovingZAtoms_local;
2272    
2273     double massOfMovingZAtoms;
2274    
2275    
2276    
2277     massOfMovingZAtoms_local = 0;
2278    
2279     for (int i = 0; i < (int) ((zconsIntegrator->zconsMols).size()); i++)
2280    
2281     if ((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving)){
2282    
2283     massOfMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getTotalMass();
2284    
2285     }
2286    
2287    
2288    
2289     #ifdef IS_MPI
2290    
2291     MPI_Allreduce(&massOfMovingZAtoms_local, &massOfMovingZAtoms, 1, MPI_DOUBLE,
2292    
2293     MPI_SUM, MPI_COMM_WORLD);
2294    
2295     #else
2296    
2297     massOfMovingZAtoms = massOfMovingZAtoms_local;
2298    
2299     #endif
2300    
2301     totMassOfMovingAtoms = massOfMovingZAtoms +
2302    
2303     zconsIntegrator->totalMassOfUncons;
2304    
2305     }
2306    
2307    
2308    
2309     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfFixedZMols(Molecule* mol,
2310    
2311     Atom* atom,
2312    
2313     double totalForce){
2314    
2315     return totalForce * atom->getMass() / mol->getTotalMass();
2316    
2317     }
2318    
2319    
2320    
2321     template<typename T> double ZConstraint<T>::PolicyByMass::getZFOfMovingMols(Atom* atom,
2322    
2323     double totalForce){
2324    
2325     return totalForce * atom->getMass() / totMassOfMovingAtoms;
2326    
2327     }
2328    
2329    
2330    
2331     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfFixedZMols(Molecule* mol,
2332    
2333     Atom* atom,
2334    
2335     double totalForce){
2336    
2337     return totalForce * atom->getMass() / mol->getTotalMass();
2338    
2339     }
2340    
2341    
2342    
2343     template<typename T> double ZConstraint<T>::PolicyByMass::getHFOfUnconsMols(Atom* atom,
2344    
2345     double totalForce){
2346    
2347     return totalForce * atom->getMass() / zconsIntegrator->totalMassOfUncons;
2348    
2349     }
2350    
2351    
2352    
2353     template<typename T> void ZConstraint<T>::updateZPos(){
2354    
2355     double curTime;
2356    
2357     double COM[3];
2358    
2359    
2360    
2361     curTime = info->getTime();
2362    
2363    
2364    
2365     for (size_t i = 0; i < zconsMols.size(); i++){
2366    
2367    
2368    
2369     if (states[i] == zcsFixed && curTime >= endFixTime[i]){
2370    
2371     zPos[i] += zconsGap;
2372    
2373    
2374    
2375     if (usingSMD){
2376    
2377     zconsMols[i]->getCOM(COM);
2378    
2379     cantPos[i] = COM[whichDirection];
2380    
2381     }
2382    
2383    
2384    
2385     }
2386    
2387    
2388    
2389     }
2390    
2391    
2392    
2393     }
2394    
2395    
2396    
2397     template<typename T> void ZConstraint<T>::updateCantPos(){
2398    
2399     double curTime;
2400    
2401     double dt;
2402    
2403    
2404    
2405     curTime = info->getTime();
2406    
2407     dt = info->dt;
2408    
2409    
2410    
2411     for (size_t i = 0; i < zconsMols.size(); i++){
2412    
2413     if (states[i] == zcsMoving){
2414    
2415     cantPos[i] += cantVel[i] * dt;
2416    
2417     }
2418    
2419     }
2420    
2421    
2422    
2423     }
2424