/* * Evaluate pressure, and add to accumulator. */ void McStressAutoCorrelation::sample(long iStep) { double pressure; double temperature; McSystem& sys=system(); sys.computeStress(pressure); DArray<double> elements; elements.allocate(9); Tensor total; if (isAtInterval(iStep)){ sys.computeVirialStress(total); temperature = sys.energyEnsemble().temperature(); elements[0] = (total(0,0) - pressure / 3.0) / (10.0 * temperature); elements[1] = (total(0,1) + total(1,0)) / 2.0 / (10.0 * temperature); elements[2] = (total(0,2) + total(2,0)) / 2.0 / (10.0 * temperature); elements[3] = elements[1]; elements[4] = (total(1,1) - pressure / 3.0) / (10.0 * temperature); elements[5] = (total(1,2) + total(2,1)) / 2.0 / (10.0 * temperature); elements[6] = elements[2]; elements[7] = elements[5]; elements[8] = (total(2,2) - pressure / 3.0) / (10.0 * temperature); accumulator_.sample(elements); } }
void RingMaker::readParam(std::istream& in) { //bondPotential_.setBoundary(boundary_); bondPotential_.setNBondType(1); read<Boundary>(in, "boundary", boundary_); readParamComposite(in, bondPotential_); readParamComposite(in, random_); read<int>(in, "nMolecule", nMolecule_); read<int>(in, "nAtomPerMolecule", nAtom_); if (nAtom_ < 2) UTIL_THROW("No. of atoms too small"); v_.allocate(nAtom_); }
/* * Perform replica exchange move. */ bool ReplicaMove::move() { MPI::Request request[4]; MPI::Status status; System::MoleculeIterator molIter; Molecule::AtomIterator atomIter; int iA; int recvPt, sendPt; DArray<int> permutation; permutation.allocate(nProcs_); // Gather all derivatives of the perturbation Hamiltonians and parameters on processor with rank 0 DArray<double> myDerivatives; myDerivatives.allocate(nParameters_); DArray<double> myParameters; myParameters.allocate(nParameters_); for (int i=0; i< nParameters_; i++) { myDerivatives[i] = system().perturbation().derivative(i); myParameters[i] = system().perturbation().parameter(i); } int size = 0; size += memorySize(myDerivatives); size += memorySize(myParameters); if (myId_ != 0) { MemoryOArchive sendCurrent; sendCurrent.allocate(size); sendCurrent << myDerivatives; sendCurrent << myParameters; sendCurrent.send(*communicatorPtr_, 0); } else { DArray< DArray<double> > allDerivatives; DArray< DArray<double> > allParameters; allDerivatives.allocate(nProcs_); allParameters.allocate(nProcs_); allDerivatives[0].allocate(nParameters_); allDerivatives[0] = myDerivatives; allParameters[0].allocate(nParameters_); allParameters[0] = myParameters; for (int i = 1; i<nProcs_; i++) { MemoryIArchive recvPartner; recvPartner.allocate(size); recvPartner.recv(*communicatorPtr_, i); allDerivatives[i].allocate(nParameters_); allParameters[i].allocate(nParameters_); recvPartner >> allDerivatives[i]; recvPartner >> allParameters[i]; } // Now we have the complete matrix U_ij = u_i(x_j), permutate nsampling steps according // to acceptance criterium // start with identity permutation for (int i = 0; i < nProcs_; i++) permutation[i] = i; for (int n =0; n < nSampling_; n++) { swapAttempt_++; // choose a pair i,j, i!= j at random int i = system().simulation().random().uniformInt(0,nProcs_); int j = system().simulation().random().uniformInt(0,nProcs_-1); if (i<=j) j++; // apply acceptance criterium double weight = 0; for (int k = 0; k < nParameters_; k++) { double deltaDerivative = allDerivatives[i][k] - allDerivatives[j][k]; // the permutations operate on the states (the perturbation parameters) weight += (allParameters[permutation[j]][k] - allParameters[permutation[i]][k])*deltaDerivative; } double exponential = exp(-weight); int accept = system().simulation().random(). metropolis(exponential) ? 1 : 0; if (accept) { swapAccept_++; // swap states of pair i,j int tmp = permutation[i]; permutation[i] = permutation[j]; permutation[j] = tmp; } } // send exchange partner information to all other processors for (int i = 0; i < nProcs_; i++) { if (i != 0) communicatorPtr_->Send(&permutation[i], 1, MPI::INT, i, 0); else sendPt = permutation[i]; if (permutation[i] != 0) communicatorPtr_->Send(&i, 1, MPI::INT, permutation[i], 1); else recvPt = i; } } if (myId_ != 0) { // partner id to receive from communicatorPtr_->Recv(&sendPt, 1, MPI::INT, 0, 0); // partner id to send to communicatorPtr_->Recv(&recvPt, 1, MPI::INT, 0, 1); } if (recvPt == myId_ || sendPt == myId_) { // no exchange necessary outputFile_ << sendPt << std::endl; return true; } assert(recvPt != myId_ && sendPt != myId_); Vector myBoundary; myBoundary = system().boundary().lengths(); Vector ptBoundary; // Accomodate new boundary dimensions. request[0] = communicatorPtr_->Irecv(&ptBoundary, 1, MpiTraits<Vector>::type, recvPt, 1); // Send old boundary dimensions. request[1] = communicatorPtr_->Isend(&myBoundary, 1, MpiTraits<Vector>::type, sendPt, 1); request[0].Wait(); request[1].Wait(); system().boundary().setOrthorhombic(ptBoundary); // Pack atomic positions and types. iA = 0; for (int iSpec=0; iSpec < system().simulation().nSpecies(); ++iSpec){ for (system().begin(iSpec, molIter); molIter.notEnd(); ++molIter){ for (molIter->begin(atomIter); atomIter.notEnd(); ++atomIter) { myPositionPtr_[iA] = atomIter->position(); iA++; } } } // Accomodate new configuration. request[2] = communicatorPtr_->Irecv(ptPositionPtr_, iA, MpiTraits<Vector>::type, recvPt, 2); // Send old configuration. request[3] = communicatorPtr_->Isend(myPositionPtr_, iA, MpiTraits<Vector>::type, sendPt, 2); request[2].Wait(); request[3].Wait(); // Adopt the new atomic positions. iA = 0; for (int iSpec=0; iSpec < system().simulation().nSpecies(); ++iSpec){ for (system().begin(iSpec, molIter); molIter.notEnd(); ++molIter){ for (molIter->begin(atomIter); atomIter.notEnd(); ++atomIter){ atomIter->position() = ptPositionPtr_[iA]; ++iA; } } } // Notify component observers. sendRecvPair partners; partners[0] = sendPt; partners[1] = recvPt; Notifier<sendRecvPair>::notifyObservers(partners); // Log information about exchange partner to file outputFile_ << sendPt << std::endl; return true; }