/* * Empty implementation, to be filled by derived classes. */ bool ReplicaMove::move() { MPI::Request request[8]; MPI::Status status; double ptParam, myWeight, ptWeight; int isLeft, iAccept, myPort, ptPort; System::MoleculeIterator molIter; Molecule::AtomIterator atomPtr; int iA; // Default value for idle processor isLeft = -1; iAccept = 0; // Idenfity active processor and its parter ID; left one has smaller ID. if ((myId_ + xFlag_)%2 == 0 && myId_ < nProcs_-1) { isLeft = 1; ptId_ = myId_ + 1; } else if ((myId_ + xFlag_)%2 == 1 && myId_ > 0) { isLeft = 0; ptId_ = myId_ - 1; } // Start to talk with partner if (isLeft == 1 || isLeft == 0) { // Set the port value for message tag myPort = myId_%2; ptPort = ptId_%2; // Update accumulator repxAttempt_[isLeft] += 1; // Exchange coupling parameters with partner request[0] = communicatorPtr_->Irecv(&ptParam, 1, MPI::DOUBLE, ptId_, TagParam[ptPort]); request[1] = communicatorPtr_->Isend(&myParam_, 1, MPI::DOUBLE, ptId_, TagParam[myPort]); // Synchronizing request[0].Wait(); request[1].Wait(); // Evaluating energy change. myWeight = system().perturbation().difference(ptParam); // Collect tempering weights and make decision if (isLeft == 1) { // Receive energy difference from the right box request[2] = communicatorPtr_->Irecv(&ptWeight, 1, MPI::DOUBLE, ptId_, TagDecision[ptPort]); request[2].Wait(); // Metropolis test iAccept = system().simulation().random(). metropolis(exp(-myWeight - ptWeight)) ? 1 : 0; // Output the two weights and the metropolis of their summation. // energyFile_ << setw(10) << myWeight << setw(10) // << ptWeight << setw(2) << iAccept << std::endl; // Send decision to the right box request[3] = communicatorPtr_->Isend(&iAccept, 1, MPI::INT, ptId_, TagDecision[myPort]); request[3].Wait(); } else { // Send energy difference to the left box request[2] = communicatorPtr_->Isend(&myWeight, 1, MPI::DOUBLE, ptId_, TagDecision[myPort]); request[2].Wait(); // Receive decision from the left box request[3] = communicatorPtr_->Irecv(&iAccept, 1, MPI::INT, ptId_, TagDecision[ptPort]); request[3].Wait(); } // Exchange particle configurations if the move is accepted if (iAccept == 1) { // Update accumulator repxAccept_[isLeft] += 1; // Pack atomic positions and types. iA = 0; for (int iSpec=0; iSpec < system().simulation().nSpecies(); ++iSpec){ for (system().begin(iSpec, molIter); !molIter.isEnd(); ++molIter){ for (molIter->begin(atomPtr); !atomPtr.isEnd(); ++atomPtr) { myPositionPtr_[iA] = atomPtr->position(); iA++; } } } // Accomodate new configuration. request[4] = communicatorPtr_->Irecv(ptPositionPtr_, iA, MpiTraits<Vector>::type, ptId_, TagConfig[ptPort]); // Send old configuration. request[5] = communicatorPtr_->Isend(myPositionPtr_, iA, MpiTraits<Vector>::type, ptId_, TagConfig[myPort]); request[4].Wait(); request[5].Wait(); // Adopt the new atomic positions. iA = 0; for (int iSpec=0; iSpec < system().simulation().nSpecies(); ++iSpec){ for (system().begin(iSpec, molIter); !molIter.isEnd(); ++molIter){ for (molIter->begin(atomPtr); !atomPtr.isEnd(); ++atomPtr) { atomPtr->position() = ptPositionPtr_[iA]; ++iA; } } } // Notify component observers. //notifyObservers(ptId_); Notifier<int>::notifyObservers(ptId_); } else { } } // Output results needed to build exchange profile. outputFile_ << ((isLeft != -1 && iAccept == 1) ? ptId_ : myId_) << std::endl; // Flip the value of xFlag_ before exit. xFlag_ = (xFlag_ == 0 ? 1 : 0); return (iAccept == 1 ? true : false); }