35 #include <basic/options/option_macros.hh>
36 #include <basic/options/keys/in.OptionKeys.gen.hh>
37 #include <basic/options/keys/packing.OptionKeys.gen.hh>
39 #include <basic/Tracer.hh>
48 #include <numeric/random/random.hh>
51 #include <utility/file/file_sys_util.hh>
52 #include <utility/pointer/owning_ptr.hh>
53 #include <utility/tag/Tag.hh>
54 #include <utility/io/ozstream.hh>
55 #include <utility/io/izstream.hh>
56 #include <ObjexxFCL/string.functions.hh>
59 #include <basic/prof.hh>
69 static basic::Tracer
tr(
"protocols.canonical_sampling.ParallelTempering" );
70 static numeric::random::RandomGenerator
RG(3227547);
84 namespace canonical_sampling {
99 return "ParallelTempering";
104 last_energies_( NULL ),
105 rank2tlevel_( NULL ),
106 tlevel2rank_( NULL ),
108 total_mpi_wait_time_(0)
111 utility_exit_with_message(
"ParallelTempering requires MPI build" );
114 mpi_comm_ = MPI_COMM_NULL;
121 exchange_schedules_( other.exchange_schedules_ ),
122 last_exchange_schedule_( other.last_exchange_schedule_ ),
123 last_energies_( NULL ),
124 rank2tlevel_( NULL ),
125 tlevel2rank_( NULL ),
126 start_time_( other.start_time_ ),
127 total_mpi_wait_time_( other.total_mpi_wait_time_ )
130 utility_exit_with_message(
"ParallelTempering requires MPI build" );
133 set_mpi_comm( other.mpi_comm() );
138 if ( &other ==
this )
return *
this;
142 set_mpi_comm( other.mpi_comm() );
161 tr.Trace <<
"ParallelTempering::initialize_simul1... " << std::endl;
163 tr.Trace <<
"ParallelTempering::initialize_simul2... " << std::endl;
165 set_mpi_comm( jd2::current_mpi_comm() );
167 tr.Trace <<
"ParallelTempering::initialize_simul3... " << std::endl;
176 tr.Trace <<
"Initialized ParallelTempering! " << std::endl;
188 tr <<
"Temperature Exchange Frequencies:" << std::endl;
189 std::streamsize oldwidth(
tr.width() );
190 std::streamsize oldprecision(
tr.precision() );
191 std::ios_base::fmtflags oldflags(
tr.flags() );
194 tr.setf(std::ios_base::fixed);
196 std::pair<int, int> elem(i, i+1);
207 tr.precision(oldprecision);
211 core::Real const clock_factor( ( (
double) basic::SHRINK_FACTOR ) / CLOCKS_PER_SEC );
212 clock_t total_time(clock()/basic::SHRINK_FACTOR -
start_time_);
214 tr <<
"Spent " << fraction_waiting*100 <<
"% time waiting for MPI temperature exchange ("
215 <<
total_mpi_wait_time_*clock_factor <<
" seconds out of " << total_time*clock_factor <<
" total)" << std::endl;
219 tr.Trace <<
"ParallelTempering::setup_exchange_schedule for " << nlevels << std::endl;
225 for (
int i=0; i < (
int)nlevels-1; i+=2) {
226 std::pair<int, int> elem(i, i+1);
227 list.push_back(elem);
237 for (
int i=1; i<(
int)nlevels-1; i+=2) {
238 std::pair<int, int> elem(i, i+1);
239 list.push_back(elem);
249 tr.Trace <<
"ParallelTempering::allocate_buffers for " << nlevels << std::endl;
254 for (
Size i=0; i<nlevels; ++i ) {
279 double last_energy = score;
280 clock_t time_before_MPI = clock();
281 MPI_Gather(&last_energy, 1, MPI_DOUBLE,
last_energies_, 1, MPI_DOUBLE, 0, mpi_comm() );
288 MPI_Scatter(
rank2tlevel_, 1, MPI_INT, &new_tlevel, 1, MPI_INT, 0, mpi_comm() );
300 for (
Size i=1; i<=ex.size(); i++ ) {
305 Real const deltaE( energies[rank2]-energies[rank1] );
306 Real const delta( ( invT1 - invT2 ) * deltaE );
310 if (
RG.uniform() < std::min( 1.0, std::exp( std::max(-40.0, -delta) ) ) ) {
331 return "ParallelTempering";
364 using namespace basic::options;
365 using namespace basic::options::OptionKeys;
366 using namespace core;
367 using namespace basic::options;
368 using namespace basic::options::OptionKeys;
369 using namespace core;
374 void ParallelTempering::set_mpi_comm( MPI_Comm
const& mpi_comm ) {
375 if ( mpi_comm != MPI_COMM_NULL ) {
376 tr.Trace <<
"ParallelTempering::Duplicate mpi-communicator" << std::endl;
377 MPI_Comm_dup( mpi_comm, &mpi_comm_ );
378 MPI_Comm_rank( mpi_comm_, &
rank_ );
380 MPI_Comm_size( mpi_comm_, &size );
383 tr.Trace <<
"ParallelTempering::Duplicate mpi-communicator" << std::endl;
384 mpi_comm_ = MPI_COMM_NULL;