--- trunk/OOPSE/libmdtools/ZConstraint.cpp 2003/08/13 19:21:53 693 +++ trunk/OOPSE/libmdtools/ZConstraint.cpp 2003/10/28 16:03:37 829 @@ -1,9 +1,9 @@ #include "Integrator.hpp" #include "simError.h" -#include +#include template ZConstraint::ZConstraint(SimInfo* theInfo, ForceFields* the_ff) - : T(theInfo, the_ff), fz(NULL), - indexOfZConsMols(NULL) + : T(theInfo, the_ff), indexOfZConsMols(NULL), fz(NULL), curZPos(NULL), + fzOut(NULL), curZconsTime(0), forcePolicy(NULL) { //get properties from SimInfo @@ -11,6 +11,7 @@ template ZConstraint::ZConstraint(SimIn ZConsParaData* zConsParaData; DoubleData* sampleTime; DoubleData* tolerance; + StringData* policy; StringData* filename; double COM[3]; @@ -26,6 +27,46 @@ template ZConstraint::ZConstraint(SimIn double halfOfLargestBox = max(info->boxL[0], max(info->boxL[1], info->boxL[2])) /2; zForceConst = Kb * info->target_temp /(halfOfLargestBox * halfOfLargestBox); + //creat force Subtraction policy + data = info->getProperty(ZCONSFORCEPOLICY_ID); + if(!data){ + sprintf( painCave.errMsg, + "ZConstraint Warning: User does not set force Subtraction policy, " + "PolicyByMass is used\n"); + painCave.isFatal = 0; + simError(); + + forcePolicy = (ForceSubtractionPolicy*) new PolicyByMass(this); + } + else{ + policy = dynamic_cast(data); + + if(!policy){ + sprintf( painCave.errMsg, + "ZConstraint Error: Convertion from GenericData to StringData failure, " + "PolicyByMass is used\n"); + painCave.isFatal = 0; + simError(); + + forcePolicy = (ForceSubtractionPolicy*) new PolicyByMass(this); + } + else{ + if(policy->getData() == "BYNUMBER") + forcePolicy = (ForceSubtractionPolicy*) new PolicyByNumber(this); + else if(policy->getData() == "BYMASS") + forcePolicy = (ForceSubtractionPolicy*) new PolicyByMass(this); + else{ + sprintf( painCave.errMsg, + "ZConstraint Warning: unknown force Subtraction policy, " + "PolicyByMass is used\n"); + painCave.isFatal = 0; + simError(); + forcePolicy = (ForceSubtractionPolicy*) new PolicyByMass(this); + } + } + } + + //retrieve sample time of z-contraint data = info->getProperty(ZCONSTIME_ID); @@ -69,7 +110,7 @@ template ZConstraint::ZConstraint(SimIn } else{ - filename = dynamic_cast(data); + filename = dynamic_cast(data); if(!filename){ @@ -83,7 +124,6 @@ template ZConstraint::ZConstraint(SimIn this->zconsOutput = filename->getData(); } - } //retrieve tolerance for z-constraint molecuels @@ -113,7 +153,7 @@ template ZConstraint::ZConstraint(SimIn } } - + //retrieve index of z-constraint molecules data = info->getProperty(ZCONSPARADATA_ID); if(!data) { @@ -154,7 +194,7 @@ template ZConstraint::ZConstraint(SimIn "ZConstraint error: index is out of range\n"); painCave.isFatal = 1; simError(); - } + } maxIndex = (*parameters)[parameters->size() - 1].zconsIndex; @@ -173,52 +213,51 @@ template ZConstraint::ZConstraint(SimIn //if user does not specify the zpos for the zconstraint molecule //its initial z coordinate will be used as default - for(int i = 0; i < parameters->size(); i++){ + for(int i = 0; i < (int)(parameters->size()); i++){ - if(!(*parameters)[i].havingZPos){ - + if(!(*parameters)[i].havingZPos){ #ifndef IS_MPI - for(int j = 0; j < nMols; j++){ - if (molecules[j].getGlobalIndex() == (*parameters)[i].zconsIndex){ - molecules[j].getCOM(COM); - break; - } + for(int j = 0; j < nMols; j++){ + if (molecules[j].getGlobalIndex() == (*parameters)[i].zconsIndex){ + molecules[j].getCOM(COM); + break; } + } #else //query which processor current zconstraint molecule belongs to - int *MolToProcMap; - int whichNode; - double initZPos; - MolToProcMap = mpiSim->getMolToProcMap(); - whichNode = MolToProcMap[(*parameters)[i].zconsIndex]; - - //broadcast the zpos of current z-contraint molecule - //the node which contain this + int *MolToProcMap; + int whichNode; + + MolToProcMap = mpiSim->getMolToProcMap(); + whichNode = MolToProcMap[(*parameters)[i].zconsIndex]; + + //broadcast the zpos of current z-contraint molecule + //the node which contain this - if (worldRank == whichNode ){ - - for(int j = 0; j < nMols; j++) - if (molecules[j].getGlobalIndex() == (*parameters)[i].zconsIndex){ - molecules[j].getCOM(COM); - break; - } - - } + if (worldRank == whichNode ){ + + for(int j = 0; j < nMols; j++) + if (molecules[j].getGlobalIndex() == (*parameters)[i].zconsIndex){ + molecules[j].getCOM(COM); + break; + } + + } - MPI_Bcast(&COM[whichDirection], 1, MPI_DOUBLE_PRECISION, whichNode, MPI_COMM_WORLD); + MPI_Bcast(&COM[whichDirection], 1, MPI_DOUBLE_PRECISION, whichNode, MPI_COMM_WORLD); #endif - (*parameters)[i].zPos = COM[whichDirection]; + (*parameters)[i].zPos = COM[whichDirection]; - sprintf( painCave.errMsg, - "ZConstraint warningr: Does not specify zpos for z-constraint molecule " + sprintf( painCave.errMsg, + "ZConstraint warning: Does not specify zpos for z-constraint molecule " "initial z coornidate will be used \n"); - painCave.isFatal = 0; - simError(); - - } - } - + painCave.isFatal = 0; + simError(); + + } + } + }//end if (!zConsParaData) }//end if (!data) @@ -238,8 +277,10 @@ template ZConstraint::ZConstraint(SimIn massOfZConsMols.push_back(molecules[i].getTotalMass()); zPos.push_back((*parameters)[searchResult].zPos); - kz.push_back((*parameters)[searchResult]. kRatio * zForceConst); +// cout << "index: "<< (*parameters)[searchResult].zconsIndex +// <<"\tzPos = " << (*parameters)[searchResult].zPos << endl; + kz.push_back((*parameters)[searchResult]. kRatio * zForceConst); molecules[i].getCOM(COM); } else @@ -252,9 +293,10 @@ template ZConstraint::ZConstraint(SimIn } fz = new double[zconsMols.size()]; + curZPos = new double[zconsMols.size()]; indexOfZConsMols = new int [zconsMols.size()]; - if(!fz || !indexOfZConsMols){ + if(!fz || !curZPos || !indexOfZConsMols){ sprintf( painCave.errMsg, "Memory allocation failure in class Zconstraint\n"); painCave.isFatal = 1; @@ -262,14 +304,14 @@ template ZConstraint::ZConstraint(SimIn } //determine the states of z-constraint molecules - for(int i = 0; i < zconsMols.size(); i++){ + for(int i = 0; i < (int)(zconsMols.size()); i++){ indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex(); - zconsMols[i]->getCOM(COM); + zconsMols[i]->getCOM(COM); if (fabs(zPos[i] - COM[whichDirection]) < zconsTol) - states.push_back(zcsFixed); - else - states.push_back(zcsMoving); + states.push_back(zcsFixed); + else + states.push_back(zcsMoving); } #endif @@ -278,52 +320,55 @@ template ZConstraint::ZConstraint(SimIn double totalMassOfUncons_local; totalMassOfUncons_local = 0; - for(int i = 0; i < unconsMols.size(); i++) + for(int i = 0; i < (int)(unconsMols.size()); i++) totalMassOfUncons_local += unconsMols[i]->getTotalMass(); #ifndef IS_MPI totalMassOfUncons = totalMassOfUncons_local; #else - MPI_Allreduce(&totalMassOfUncons_local, &totalMassOfUncons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(&totalMassOfUncons_local, &totalMassOfUncons, 1, + MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #endif - //get total number of unconstrained atoms int nUnconsAtoms_local; nUnconsAtoms_local = 0; - for(int i = 0; i < unconsMols.size(); i++) + for(int i = 0; i < (int)(unconsMols.size()); i++) nUnconsAtoms_local += unconsMols[i]->getNAtoms(); #ifndef IS_MPI totNumOfUnconsAtoms = nUnconsAtoms_local; #else - MPI_Allreduce(&nUnconsAtoms_local, &totNumOfUnconsAtoms, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(&nUnconsAtoms_local, &totNumOfUnconsAtoms, 1, + MPI_INT,MPI_SUM, MPI_COMM_WORLD); #endif - // creat zconsWriter - fzOut = new ZConsWriter(zconsOutput.c_str()); - - if(!fzOut){ - sprintf( painCave.errMsg, - "Memory allocation failure in class Zconstraint\n"); - painCave.isFatal = 1; - simError(); - } - + forcePolicy->update(); } template ZConstraint::~ZConstraint() { if(fz) delete[] fz; + + if(curZPos) + delete[] curZPos; if(indexOfZConsMols) delete[] indexOfZConsMols; if(fzOut) delete fzOut; + + if(forcePolicy) + delete forcePolicy; } + +/** + * + */ + #ifdef IS_MPI template void ZConstraint::update() { @@ -348,8 +393,7 @@ template void ZConstraint::update() zconsMols.push_back(&molecules[i]); zPos.push_back((*parameters)[index].zPos); - kz.push_back((*parameters)[index].kRatio * zForceConst); - + kz.push_back((*parameters)[index].kRatio * zForceConst); massOfZConsMols.push_back(molecules[i].getTotalMass()); molecules[i].getCOM(COM); @@ -364,12 +408,12 @@ template void ZConstraint::update() } //determine the states of z-constraint molecules - for(int i = 0; i < zconsMols.size(); i++){ - zconsMols[i]->getCOM(COM); + for(int i = 0; i < (int)(zconsMols.size()); i++){ + zconsMols[i]->getCOM(COM); if (fabs(zPos[i] - COM[whichDirection]) < zconsTol) - states.push_back(zcsFixed); - else - states.push_back(zcsMoving); + states.push_back(zcsFixed); + else + states.push_back(zcsMoving); } @@ -377,41 +421,50 @@ template void ZConstraint::update() // that we want to make the MPI communication simple if(fz) delete[] fz; + + if(curZPos) + delete[] curZPos; if(indexOfZConsMols) delete[] indexOfZConsMols; if (zconsMols.size() > 0){ fz = new double[zconsMols.size()]; + curZPos = new double[zconsMols.size()]; indexOfZConsMols = new int[zconsMols.size()]; - if(!fz || !indexOfZConsMols){ + if(!fz || !curZPos || !indexOfZConsMols){ sprintf( painCave.errMsg, "Memory allocation failure in class Zconstraint\n"); painCave.isFatal = 1; simError(); } - for(int i = 0; i < zconsMols.size(); i++){ + for(int i = 0; i < (int)(zconsMols.size()); i++){ indexOfZConsMols[i] = zconsMols[i]->getGlobalIndex(); } } else{ fz = NULL; + curZPos = NULL; indexOfZConsMols = NULL; } + // + forcePolicy->update(); + } #endif -/** Function Name: isZConstraintMol - ** Parameter - ** Molecule* mol - ** Return value: - ** -1, if the molecule is not z-constraint molecule, - ** other non-negative values, its index in indexOfAllZConsMols vector +/** + * Function Name: isZConstraintMol + * Parameter + * Molecule* mol + * Return value: + * -1, if the molecule is not z-constraint molecule, + * other non-negative values, its index in indexOfAllZConsMols vector */ template int ZConstraint::isZConstraintMol(Molecule* mol) @@ -441,10 +494,22 @@ template void ZConstraint::integrate(){ } template void ZConstraint::integrate(){ + + // creat zconsWriter + fzOut = new ZConsWriter(zconsOutput.c_str(), parameters); + if(!fzOut){ + sprintf( painCave.errMsg, + "Memory allocation failure in class Zconstraint\n"); + painCave.isFatal = 1; + simError(); + } + //zero out the velocities of center of mass of unconstrained molecules //and the velocities of center of mass of every single z-constrained molecueles zeroOutVel(); + + curZconsTime = zconsTime + info->getTime(); T::integrate(); @@ -456,36 +521,77 @@ template void ZConstraint::integrate(){ * * * - */ - - + */ template void ZConstraint::calcForce(int calcPot, int calcStress){ double zsys; + double COM[3]; + double force[3]; + double zSysCOMVel; T::calcForce(calcPot, calcStress); - if (checkZConsState()) - zeroOutVel(); + if (checkZConsState()){ + zeroOutVel(); + forcePolicy->update(); + } zsys = calcZSys(); - cout << "---------------------------------------------------------------------" <getTime() <<"\tcenter of mass at z: " << zsys << endl; - cout << "before calcForce, the COMVel of unconstraint molecules is " << calcCOMVel() <getTime() << endl; + //cout << "center of mass at z: " << zsys << endl; + //cout << "before calcForce, the COMVel of system is " << zSysCOMVel <doZconstraintForce(); - - //use harmonical poteintial to move the molecules to the specified positions if (haveMovingZMols()) this->doHarmonic(); - - fzOut->writeFZ(info->getTime(), zconsMols.size(),indexOfZConsMols, fz); - cout << "after calcForce, the COMVel of unconstraint molecules is " << calcCOMVel() <getTime() >= curZconsTime){ + for(int i = 0; i < (int)(zconsMols.size()); i++){ + zconsMols[i]->getCOM(COM); + curZPos[i] = COM[whichDirection]; + + //if the z-constraint molecule is still moving, just record its force + if(states[i] == zcsMoving){ + fz[i] = 0; + Atom** movingZAtoms; + movingZAtoms = zconsMols[i]->getMyAtoms(); + for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){ + movingZAtoms[j]->getFrc(force); + fz[i] += force[whichDirection]; + } + } + } + fzOut->writeFZ(info->getTime(), zconsMols.size(), indexOfZConsMols, fz, curZPos); + curZconsTime += zconsTime; + } + + zSysCOMVel = calcSysCOMVel(); +#ifdef IS_MPI + if(worldRank == 0){ +#endif + //cout << "after calcForce, the COMVel of system is " << zSysCOMVel < double ZConstraint::calcZSys() { @@ -494,16 +600,11 @@ template double ZConstraint::calcZSys() double totalMass; double totalMZ_local; double totalMZ; - double massOfUncons_local; double massOfCurMol; double COM[3]; totalMass_local = 0; - totalMass = 0; totalMZ_local = 0; - totalMZ = 0; - massOfUncons_local = 0; - for(int i = 0; i < nMols; i++){ massOfCurMol = molecules[i].getTotalMass(); @@ -511,24 +612,19 @@ template double ZConstraint::calcZSys() totalMass_local += massOfCurMol; totalMZ_local += massOfCurMol * COM[whichDirection]; - - if(isZConstraintMol(&molecules[i]) == -1){ - - massOfUncons_local += massOfCurMol; - } - + } + - #ifdef IS_MPI - MPI_Allreduce(&totalMass_local, &totalMass, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(&totalMZ_local, &totalMZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(&massOfUncons_local, &totalMassOfUncons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); -#else + MPI_Allreduce(&totalMass_local, &totalMass, 1, + MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(&totalMZ_local, &totalMZ, 1, + MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + #else totalMass = totalMass_local; totalMZ = totalMZ_local; - totalMassOfUncons = massOfUncons_local; -#endif + #endif double zsys; zsys = totalMZ / totalMass; @@ -547,8 +643,6 @@ template void ZConstraint::thermalize( /** * - * - * */ template void ZConstraint::zeroOutVel(){ @@ -556,43 +650,42 @@ template void ZConstraint::zeroOutVel() Atom** fixedZAtoms; double COMvel[3]; double vel[3]; + double zSysCOMVel; - double tempMass = 0; - double tempMVz =0; - double tempVz = 0; - for(int i = 0; i < nMols; i++){ - molecules[i].getCOMvel(COMvel); - tempMass +=molecules[i].getTotalMass(); - tempMVz += molecules[i].getTotalMass() * COMvel[whichDirection]; - tempVz += COMvel[whichDirection]; - } - cout << "initial velocity of center of mass is " << tempMVz / tempMass << endl; - //zero out the velocities of center of mass of fixed z-constrained molecules - for(int i = 0; i < zconsMols.size(); i++){ + for(int i = 0; i < (int)(zconsMols.size()); i++){ - if (states[i] == zcsFixed){ + if (states[i] == zcsFixed){ - zconsMols[i]->getCOMvel(COMvel); - cout << "before resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl; + zconsMols[i]->getCOMvel(COMvel); + //cout << "before resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl; fixedZAtoms = zconsMols[i]->getMyAtoms(); - + for(int j =0; j < zconsMols[i]->getNAtoms(); j++){ fixedZAtoms[j]->getVel(vel); - vel[whichDirection] -= COMvel[whichDirection]; - fixedZAtoms[j]->setVel(vel); + vel[whichDirection] -= COMvel[whichDirection]; + fixedZAtoms[j]->setVel(vel); } - zconsMols[i]->getCOMvel(COMvel); - cout << "after resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl; + zconsMols[i]->getCOMvel(COMvel); + //cout << "after resetting " << indexOfZConsMols[i] <<"'s vz is " << COMvel[whichDirection] << endl; } - + } - cout << "before resetting the COMVel of unconstraint molecules is " << calcCOMVel() < void ZConstraint::zeroOutVel() MVzOfMovingMols_local = 0; totalMassOfMovingZMols_local = 0; - for(int i =0; i < unconsMols.size(); i++){ + for(int i =0; i < (int)(unconsMols.size()); i++){ unconsMols[i]->getCOMvel(COMvel); MVzOfMovingMols_local += massOfUnconsMols[i] * COMvel[whichDirection]; } - for(int i = 0; i < zconsMols.size(); i++){ + for(int i = 0; i < (int)(zconsMols.size()); i++){ if (states[i] == zcsMoving){ zconsMols[i]->getCOMvel(COMvel); MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection]; - totalMassOfMovingZMols_local += massOfZConsMols[i]; + totalMassOfMovingZMols_local += massOfZConsMols[i]; } - + } #ifndef IS_MPI @@ -629,7 +722,7 @@ template void ZConstraint::zeroOutVel() //modify the velocites of unconstrained molecules Atom** unconsAtoms; - for(int i = 0; i < unconsMols.size(); i++){ + for(int i = 0; i < (int)(unconsMols.size()); i++){ unconsAtoms = unconsMols[i]->getMyAtoms(); for(int j = 0; j < unconsMols[i]->getNAtoms();j++){ @@ -642,48 +735,59 @@ template void ZConstraint::zeroOutVel() //modify the velocities of moving z-constrained molecuels Atom** movingZAtoms; - for(int i = 0; i < zconsMols.size(); i++){ + for(int i = 0; i < (int)(zconsMols.size()); i++){ if (states[i] ==zcsMoving){ movingZAtoms = zconsMols[i]->getMyAtoms(); - for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){ + for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){ movingZAtoms[j]->getVel(vel); vel[whichDirection] -= vzOfMovingMols; - movingZAtoms[j]->setVel(vel); - } - + movingZAtoms[j]->setVel(vel); + } + } } - cout << "after resetting the COMVel of unconstraint molecules is " << calcCOMVel() < void ZConstraint::doZconstraintForce(){ Atom** zconsAtoms; double totalFZ; double totalFZ_local; - double COMvel[3]; double COM[3]; double force[3]; - int nMovingZMols_local; - int nMovingZMols; - - //constrain the molecules which do not reach the specified positions + //constrain the molecules which do not reach the specified positions //Zero Out the force of z-contrained molecules totalFZ_local = 0; //calculate the total z-contrained force of fixed z-contrained molecules - cout << "Fixed Molecules" << endl; - for(int i = 0; i < zconsMols.size(); i++){ - + + //cout << "before zero out z-constraint force on fixed z-constraint molecuels " + // << "total force is " << calcTotalForce() << endl; + + for(int i = 0; i < (int)(zconsMols.size()); i++){ + if (states[i] == zcsFixed){ - + zconsMols[i]->getCOM(COM); zconsAtoms = zconsMols[i]->getMyAtoms(); @@ -691,126 +795,88 @@ template void ZConstraint::doZconstrain for(int j =0; j < zconsMols[i]->getNAtoms(); j++) { zconsAtoms[j]->getFrc(force); fz[i] += force[whichDirection]; - } + } totalFZ_local += fz[i]; - cout << "index: " << indexOfZConsMols[i] <<"\tcurrent zpos: " << COM[whichDirection] << endl; + //cout << "Fixed Molecule\tindex: " << indexOfZConsMols[i] + // <<"\tcurrent zpos: " << COM[whichDirection] + // << "\tcurrent fz: " <getMyAtoms(); - - for(int j = 0; j < unconsMols[i]->getNAtoms(); j++) - unconsAtoms[j]->addFrc(force); - - } - - //modify the forces of moving z-constrained molecules - for(int i = 0; i < zconsMols.size(); i++) { - if (states[i] == zcsMoving){ - - Atom** movingZAtoms = zconsMols[i]->getMyAtoms(); - - for(int j = 0; j < zconsMols[i]->getNAtoms(); j++) - movingZAtoms[j]->addFrc(force); - } - } - + // apply negative to fixed z-constrained molecues; force[0]= 0; force[1]= 0; force[2]= 0; - for(int i = 0; i < zconsMols.size(); i++){ + for(int i = 0; i < (int)(zconsMols.size()); i++){ if (states[i] == zcsFixed){ - + int nAtomOfCurZConsMol = zconsMols[i]->getNAtoms(); zconsAtoms = zconsMols[i]->getMyAtoms(); for(int j =0; j < nAtomOfCurZConsMol; j++) { - force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol; + //force[whichDirection] = -fz[i]/ nAtomOfCurZConsMol; + force[whichDirection] = - forcePolicy->getZFOfFixedZMols(zconsMols[i], zconsAtoms[j], fz[i]); zconsAtoms[j]->addFrc(force); } - + } - + } -} + //cout << "after zero out z-constraint force on fixed z-constraint molecuels " + // << "total force is " << calcTotalForce() << endl; + -template bool ZConstraint::checkZConsState(){ - double COM[3]; - double diff; - - bool changed; - - changed = false; - - for(int i =0; i < zconsMols.size(); i++){ + force[0]= 0; + force[1]= 0; + force[2]= 0; - zconsMols[i]->getCOM(COM); - diff = fabs(COM[whichDirection] - zPos[i]); - if ( diff <= zconsTol && states[i] == zcsMoving){ - states[i] = zcsFixed; - changed = true; + //modify the forces of unconstrained molecules + for(int i = 0; i < (int)(unconsMols.size()); i++){ + + Atom** unconsAtoms = unconsMols[i]->getMyAtoms(); + + for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){ + //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms); + force[whichDirection] = forcePolicy->getZFOfMovingMols(unconsAtoms[j],totalFZ); + unconsAtoms[j]->addFrc(force); + } + + } + + //modify the forces of moving z-constrained molecules + for(int i = 0; i < (int)(zconsMols.size()); i++) { + if (states[i] == zcsMoving){ + + Atom** movingZAtoms = zconsMols[i]->getMyAtoms(); + + for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){ + //force[whichDirection] = totalFZ / (totNumOfUnconsAtoms + nMovingZAtoms); + force[whichDirection] = forcePolicy->getZFOfMovingMols(movingZAtoms[j],totalFZ); + movingZAtoms[j]->addFrc(force); + } } - else if ( diff > zconsTol && states[i] == zcsFixed){ - states[i] = zcsMoving; - changed = true; - } - } +// cout << "after substracting z-constraint force from moving molecuels " +// << "total force is " << calcTotalForce() << endl; - return changed; } -template bool ZConstraint::haveFixedZMols(){ - for(int i = 0; i < zconsMols.size(); i++) - if (states[i] == zcsFixed) - return true; - - return false; -} - - /** - * - */ -template bool ZConstraint::haveMovingZMols(){ - for(int i = 0; i < zconsMols.size(); i++) - if (states[i] == zcsMoving) - return true; - - return false; - -} - -/** * * */ @@ -821,55 +887,165 @@ template void ZConstraint::doHarmonic() double harmonicF; double COM[3]; double diff; + double totalFZ_local; double totalFZ; - + force[0] = 0; force[1] = 0; force[2] = 0; - totalFZ = 0; + totalFZ_local = 0; - cout << "Moving Molecules" << endl; - for(int i = 0; i < zconsMols.size(); i++) { + for(int i = 0; i < (int)(zconsMols.size()); i++) { if (states[i] == zcsMoving){ zconsMols[i]->getCOM(COM); - cout << "index: " << indexOfZConsMols[i] <<"\tcurrent zpos: " << COM[whichDirection] << endl; - - diff = COM[whichDirection] -zPos[i]; - +// cout << "Moving Molecule\tindex: " << indexOfZConsMols[i] +// << "\tcurrent zpos: " << COM[whichDirection] << endl; + + diff = COM[whichDirection] -zPos[i]; + harmonicU = 0.5 * kz[i] * diff * diff; - info->lrPot += harmonicU; + info->lrPot += harmonicU; - harmonicF = - kz[i] * diff / zconsMols[i]->getNAtoms(); - force[whichDirection] = harmonicF; - totalFZ += harmonicF; - + harmonicF = - kz[i] * diff; + totalFZ_local += harmonicF; + + //adjust force + Atom** movingZAtoms = zconsMols[i]->getMyAtoms(); - for(int j = 0; j < zconsMols[i]->getNAtoms(); j++) + for(int j = 0; j < zconsMols[i]->getNAtoms(); j++){ + //force[whichDirection] = harmonicF / zconsMols[i]->getNAtoms(); + force[whichDirection] = forcePolicy->getHFOfFixedZMols(zconsMols[i], movingZAtoms[j], harmonicF); movingZAtoms[j]->addFrc(force); + } } } +#ifndef IS_MPI + totalFZ = totalFZ_local; +#else + MPI_Allreduce(&totalFZ_local, &totalFZ, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); +#endif + + //cout << "before substracting harmonic force from moving molecuels " + // << "total force is " << calcTotalForce() << endl; + force[0]= 0; force[1]= 0; force[2]= 0; - force[whichDirection] = -totalFZ /totNumOfUnconsAtoms; //modify the forces of unconstrained molecules - for(int i = 0; i < unconsMols.size(); i++){ + for(int i = 0; i < (int)(unconsMols.size()); i++){ Atom** unconsAtoms = unconsMols[i]->getMyAtoms(); - for(int j = 0; j < unconsMols[i]->getNAtoms(); j++) + for(int j = 0; j < unconsMols[i]->getNAtoms(); j++){ + //force[whichDirection] = - totalFZ /totNumOfUnconsAtoms; + force[whichDirection] = - forcePolicy->getHFOfUnconsMols(unconsAtoms[j], totalFZ); unconsAtoms[j]->addFrc(force); + } } + //cout << "after substracting harmonic force from moving molecuels " + // << "total force is " << calcTotalForce() << endl; + } -template double ZConstraint::calcCOMVel() +/** + * + */ + +template bool ZConstraint::checkZConsState(){ + double COM[3]; + double diff; + + int changed_local; + int changed; + + changed_local = 0; + + for(int i =0; i < (int)(zconsMols.size()); i++){ + + zconsMols[i]->getCOM(COM); + diff = fabs(COM[whichDirection] - zPos[i]); + if ( diff <= zconsTol && states[i] == zcsMoving){ + states[i] = zcsFixed; + changed_local = 1; + } + else if ( diff > zconsTol && states[i] == zcsFixed){ + states[i] = zcsMoving; + changed_local = 1; + } + + } + +#ifndef IS_MPI + changed =changed_local; +#else + MPI_Allreduce(&changed_local, &changed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD); +#endif + + return (changed > 0); + +} + +template bool ZConstraint::haveFixedZMols(){ + + int havingFixed_local; + int havingFixed; + + havingFixed_local = 0; + + for(int i = 0; i < (int)(zconsMols.size()); i++) + if (states[i] == zcsFixed){ + havingFixed_local = 1; + break; + } + +#ifndef IS_MPI + havingFixed = havingFixed_local; +#else + MPI_Allreduce(&havingFixed_local, &havingFixed, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD); +#endif + + return (havingFixed > 0); +} + + +/** + * + */ +template bool ZConstraint::haveMovingZMols(){ + + int havingMoving_local; + int havingMoving; + + havingMoving_local = 0; + + for(int i = 0; i < (int)(zconsMols.size()); i++) + if (states[i] == zcsMoving){ + havingMoving_local = 1; + break; + } + +#ifndef IS_MPI + havingMoving = havingMoving_local; +#else + MPI_Allreduce(&havingMoving_local, &havingMoving, 1, MPI_INT,MPI_SUM, MPI_COMM_WORLD); +#endif + + return (havingMoving > 0); + +} + +/** + * + */ + +template double ZConstraint::calcMovingMolsCOMVel() { double MVzOfMovingMols_local; double MVzOfMovingMols; @@ -890,9 +1066,9 @@ template double ZConstraint::calcCOMVel if (states[i] == zcsMoving){ zconsMols[i]->getCOMvel(COMvel); MVzOfMovingMols_local += massOfZConsMols[i] * COMvel[whichDirection]; - totalMassOfMovingZMols_local += massOfZConsMols[i]; + totalMassOfMovingZMols_local += massOfZConsMols[i]; } - + } #ifndef IS_MPI @@ -909,24 +1085,142 @@ template double ZConstraint::calcCOMVel return vzOfMovingMols; } +/** + * + */ -template double ZConstraint::calcCOMVel2() +template double ZConstraint::calcSysCOMVel() { double COMvel[3]; - double tempMVz = 0; - int index; - + double tempMVz_local; + double tempMVz; + double massOfZCons_local; + double massOfZCons; + + + tempMVz_local = 0; + for(int i =0 ; i < nMols; i++){ - index = isZConstraintMol(&molecules[i]); - if( index == -1){ - molecules[i].getCOMvel(COMvel); - tempMVz += molecules[i].getTotalMass()*COMvel[whichDirection]; - } - else if(states[i] == zcsMoving){ - zconsMols[index]->getCOMvel(COMvel); - tempMVz += massOfZConsMols[index]*COMvel[whichDirection]; - } + molecules[i].getCOMvel(COMvel); + tempMVz_local += molecules[i].getTotalMass()*COMvel[whichDirection]; } - - return tempMVz /totalMassOfUncons; + + massOfZCons_local = 0; + + for(int i = 0; i < (int)(massOfZConsMols.size()); i++){ + massOfZCons_local += massOfZConsMols[i]; + } +#ifndef IS_MPI + massOfZCons = massOfZCons_local; + tempMVz = tempMVz_local; +#else + MPI_Allreduce(&massOfZCons_local, &massOfZCons, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce(&tempMVz_local, &tempMVz, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); +#endif + + return tempMVz /(totalMassOfUncons + massOfZCons); } + +/** + * + */ + +template double ZConstraint::calcTotalForce(){ + + double force[3]; + double totalForce_local; + double totalForce; + + totalForce_local = 0; + + for(int i = 0; i < nAtoms; i++){ + atoms[i]->getFrc(force); + totalForce_local += force[whichDirection]; + } + +#ifndef IS_MPI + totalForce = totalForce_local; +#else + MPI_Allreduce(&totalForce_local, &totalForce, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); +#endif + + return totalForce; + +} + +/** + * + */ + +template void ZConstraint::PolicyByNumber::update(){ + //calculate the number of atoms of moving z-constrained molecules + int nMovingZAtoms_local; + int nMovingZAtoms; + + nMovingZAtoms_local = 0; + for(int i = 0; i < (int)((zconsIntegrator->zconsMols).size()); i++) + if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving)) + nMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getNAtoms(); + +#ifdef IS_MPI + MPI_Allreduce(&nMovingZAtoms_local, &nMovingZAtoms, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); +#else + nMovingZAtoms = nMovingZAtoms_local; +#endif + totNumOfMovingAtoms = nMovingZAtoms + zconsIntegrator->totNumOfUnconsAtoms; +} + +templatedouble ZConstraint::PolicyByNumber::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){ + return totalForce / mol->getNAtoms(); +} + +template double ZConstraint::PolicyByNumber::getZFOfMovingMols(Atom* atom, double totalForce){ + return totalForce / totNumOfMovingAtoms; +} + +template double ZConstraint::PolicyByNumber::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){ + return totalForce / mol->getNAtoms(); +} + +template double ZConstraint::PolicyByNumber::getHFOfUnconsMols(Atom* atom, double totalForce){ + return totalForce / zconsIntegrator->totNumOfUnconsAtoms; +} + +/** + * + */ + +template void ZConstraint::PolicyByMass::update(){ + //calculate the number of atoms of moving z-constrained molecules + double massOfMovingZAtoms_local; + double massOfMovingZAtoms; + + massOfMovingZAtoms_local = 0; + for(int i = 0; i < (int)((zconsIntegrator->zconsMols).size()); i++) + if((zconsIntegrator->states)[i] == (zconsIntegrator->zcsMoving)) + massOfMovingZAtoms_local += (zconsIntegrator->zconsMols)[i]->getTotalMass(); + +#ifdef IS_MPI + MPI_Allreduce(&massOfMovingZAtoms_local, &massOfMovingZAtoms, 1, MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); +#else + massOfMovingZAtoms = massOfMovingZAtoms_local; +#endif + totMassOfMovingAtoms = massOfMovingZAtoms + zconsIntegrator->totalMassOfUncons; +} + +template double ZConstraint::PolicyByMass::getZFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){ + return totalForce * atom->getMass() / mol->getTotalMass(); +} + +template double ZConstraint::PolicyByMass::getZFOfMovingMols( Atom* atom, double totalForce){ + return totalForce * atom->getMass() / totMassOfMovingAtoms; +} + +template double ZConstraint::PolicyByMass::getHFOfFixedZMols(Molecule* mol, Atom* atom, double totalForce){ + return totalForce * atom->getMass() / mol->getTotalMass(); +} + +template double ZConstraint::PolicyByMass::getHFOfUnconsMols(Atom* atom, double totalForce){ + return totalForce * atom->getMass() / zconsIntegrator->totalMassOfUncons; +} +