37 #include <basic/options/option_macros.hh>
38 #include <basic/options/keys/in.OptionKeys.gen.hh>
39 #include <basic/options/keys/packing.OptionKeys.gen.hh>
41 #include <basic/Tracer.hh>
52 #include <numeric/random/random.hh>
55 #include <utility/file/file_sys_util.hh>
56 #include <utility/pointer/owning_ptr.hh>
57 #include <utility/tag/Tag.hh>
58 #include <utility/io/ozstream.hh>
59 #include <utility/io/izstream.hh>
62 #include <ObjexxFCL/format.hh>
65 #include <utility/excn/Exceptions.hh>
73 static basic::Tracer
tr(
"protocols.canonical_sampling.HamiltonianExchange" );
74 static numeric::random::RandomGenerator
RG(2592747);
88 namespace canonical_sampling {
103 return "HamiltonianExchange";
110 utility_exit_with_message(
"HamiltonianExchange requires MPI build" );
113 mpi_comm_ = MPI_COMM_NULL;
120 rank_( other.rank_ ),
121 hamiltonians_( other.hamiltonians_ ),
122 exchange_schedules_( other.exchange_schedules_ ),
123 current_exchange_schedule_( other.current_exchange_schedule_ ),
124 exchange_grid_( other.exchange_grid_ ),
125 exchange_grid_dimension_( other.exchange_grid_dimension_ ),
126 successfully_initialized_( false )
129 utility_exit_with_message(
"HamiltonianExchange requires MPI build" );
132 set_mpi_comm( other.mpi_comm() );
137 if ( &other ==
this )
return *
this;
147 set_mpi_comm( other.mpi_comm() );
161 return "HamiltonianExchange";
186 throw utility::excn::EXCN_RosettaScriptsOption(
"Initialization of HamiltonianExchange Module failed! " );
197 using namespace basic::options;
198 using namespace basic::options::OptionKeys;
199 using namespace core;
200 using namespace basic::options;
201 using namespace basic::options::OptionKeys;
202 using namespace core;
216 set_mpi_comm( jd2::current_mpi_comm() );
246 Size const n_dim( coord.size() );
249 for (
Size d=1; d<=n_dim; ++d ) {
250 if ( d == exclude_dim )
continue;
251 key += (coord[ d ] - 1) * stride;
252 stride *= max_coord[d];
266 for (
Size dim=1; (
int)dim<=n_dim; ++dim ) {
267 if ( coord[ dim ] > max_coord[ dim ] ) max_coord[ dim ] = coord[ dim ];
271 for (
Size dim=1; (
int)dim<=n_dim; ++dim ) {
273 typedef std::list< std::pair< core::Size, core::Size > > Level2GridpointList;
274 typedef std::map< core::Size, Level2GridpointList > Groups;
279 groups[ key ].push_back( std::make_pair( coord[ dim ], i ) );
283 for ( Groups::iterator it = groups.begin(); it != groups.end(); ++it ) {
287 for (
Size phase = 1; phase <= 2; ++phase ) {
290 for ( Groups::const_iterator git = groups.begin(); git != groups.end(); ++git ) {
291 Level2GridpointList::const_iterator lit=git->second.begin();
292 if ( phase==2 && git->second.size() > 2 ) ++lit;
293 for ( ; lit != git->second.end(); ++lit ) {
294 Level2GridpointList::const_iterator first_lit = lit;
295 Level2GridpointList::const_iterator second_lit = ++lit;
296 if ( second_lit != git->second.end() ) {
297 std::pair<int, int> elem( first_lit->second, second_lit->second );
298 list.push_back(elem);
310 using namespace ObjexxFCL::fmt;
315 MPI_Allgather( &sendbuf, 1, MPI_INT,
316 recvbuf, 1, MPI_INT, mpi_comm() );
325 runtime_assert( recvbuf[
rank() ] ==
self );
327 for (
Size i=1; i<=ex.size() && other<0; i++ ) {
328 if ( ex[ i ].first ==
self ) other = ex[ i ].second;
329 if ( ex[ i ].second ==
self ) other = ex[ i ].first;
338 if ( recvbuf[ r ]==other )
break;
347 is_master =
rank() < partner;
352 utility_exit_with_message(
"HamiltonianExchange::temperature_move() called without pose... HamEx requires pose \
353 to evaluate alternative energy function prior to switching..." );
359 using namespace ObjexxFCL::fmt;
381 int const mpi_LEVEL_INFORM = 1;
382 int const mpi_SCORE_INFORM = 2;
383 int const mpi_LEVEL_DECISION = 3;
386 int exchange_partner;
397 MPI_Isend( &my_level, 1, MPI_INT, exchange_partner, mpi_LEVEL_INFORM, mpi_comm(), &reqs[0]);
398 MPI_Irecv( &new_level, 1, MPI_INT, exchange_partner, mpi_LEVEL_INFORM, mpi_comm(), &reqs[1]);
399 MPI_Waitall(2, reqs, stats);
402 Real new_score( new_scorefxn( pose ) );
406 scores[ 0 ] = new_score;
409 MPI_Send( &scores, 2, MPI_FLOAT, exchange_partner, mpi_SCORE_INFORM, mpi_comm() );
410 MPI_Recv( &
swap, 1, MPI_INT, exchange_partner, mpi_LEVEL_DECISION, mpi_comm(), &stats[0] );
412 MPI_Recv( &scores, 2, MPI_FLOAT, exchange_partner, mpi_SCORE_INFORM, mpi_comm(), &stats[0] );
423 Real const deltaE1( scores[ 0 ] - score );
424 Real const deltaE2( scores[ 1 ] - new_score );
425 Real const delta( invT1*deltaE1 - invT2*deltaE2 );
426 Real const r(
RG.uniform() );
427 swap = r < std::min( 1.0, std::exp( std::max(-40.0, -delta) ) ) ? 1 : 0;
428 MPI_Send( &swap, 1, MPI_INT, exchange_partner, mpi_LEVEL_DECISION, mpi_comm() );
454 using namespace core::scoring;
474 tr.Debug <<
"patching weight " << score_type_ <<
" with " << op_ << wt_ << std::endl;
476 }
else if ( op_ ==
"=" ) {
479 utility_exit_with_message(
"unrecognized scorefunction patch operation "+op_ );
495 PatchOperationList global_patch_operations;
499 utility::io::izstream in( filename );
501 tr.Error <<
"cannot open file " << filename << std::endl;
510 tr.Info <<
" reading Hamiltonian configuration file " << filename <<
"..." << std::endl;
511 while ( getline( in, line ) ) {
512 std::istringstream tag_stream( line );
515 tr <<
"tag: " << tag << std::endl;
516 if ( tag_stream.good() && tag ==
"GRID_DIM" ) {
518 utility_exit_with_message(
"GRID_DIM statement has to come before any score-function definitions" );
521 if ( tag_stream.fail() ) {
522 utility_exit_with_message(
"require integer after tag GRID_DIM");
524 tr.Info <<
"using " << n_dim <<
" grid-dimensions" << std::endl;
527 if ( tag_stream.good() && tag ==
"GLOBAL_PATCH" ) {
530 if ( tag_stream.fail() ) {
531 utility_exit_with_message(
"GLOBAL_PATCH statement has to be followed by file-name or patch-operation" );
534 if ( tag_stream.fail() ) {
537 std::istringstream line_stream( line );
542 line_stream >> score_type >> operation >> wt;
543 if ( line_stream.fail() ) {
544 utility_exit_with_message(
"Expected score_type, operation and weight after GLOBAL_PATCH or a file-name" );
546 global_patch_operations.push_back(
PatchOperation( score_type, operation, wt ) );
550 if ( tag_stream.good() && tag[0]==
'#' ) {
551 tr.Debug <<
"read comment line: " << line << std::endl;
555 if ( !tag_stream.good() ) {
556 tr.Debug <<
"read empy line: " << line << std::endl;
562 std::istringstream line_stream( line );
567 for (
Size d = 1; d<=n_dim; ++d ) {
568 line_stream >> coord[ d ];
570 if ( !line_stream.good() ) {
571 tr.Error <<
"format error in hamiltonian exchange file : " << filename <<
" at line " << line << std::endl;
572 tr.Error <<
"expected " << n_dim <<
" integer values for the grid-coordinate" << std::endl;
575 line_stream >> temp >> score_name;
576 if ( !line_stream.good() ) {
577 tr.Error <<
"format error in hamiltonian exchange file : " << filename <<
" at line " << line << std::endl;
578 tr.Error <<
"expected " << n_dim <<
" integer values for the grid-coordinate" << std::endl;
581 line_stream >> patch_name;
582 using namespace core::scoring;
584 if ( !line_stream.good() ) {
589 for ( PatchOperationList::const_iterator it = global_patch_operations.begin(); it != global_patch_operations.end(); ++it ) {
592 tr.Debug <<
"line_stream still good after PATCH reading" << std::endl;
593 while ( line_stream.good() ) {
599 if ( tag ==
"ETABLE" ) {
601 score->set_etable( tag );
604 std::istringstream tag_stream( tag );
605 tag_stream >> score_type;
606 line_stream >> operation >> wt;
608 if ( line_stream.fail() ) {
609 tr.Debug <<
"tried to read a X op wt triple and failed.. " << std::endl;
613 patch.
apply( *score );
615 temperatures.push_back( temp );
630 void HamiltonianExchange::set_mpi_comm( MPI_Comm
const& mpi_comm ) {
631 if ( mpi_comm != MPI_COMM_NULL ) {
632 MPI_Comm_dup( mpi_comm, &mpi_comm_ );
633 MPI_Comm_rank( mpi_comm_, &
rank_ );
634 int communicator_size;
635 MPI_Comm_size( mpi_comm_, &communicator_size );
637 std::ostringstream os;
638 os <<
"For HamiltonianExchange the number of exchange cells " <<
n_temp_levels()
639 <<
"\n has to be consistent with the option -run:n_replica "
640 << communicator_size;
641 utility_exit_with_message( os.str() );
644 mpi_comm_ = MPI_COMM_NULL;
650 using namespace ObjexxFCL::fmt;
653 os <<
"////////////////////////////////////////////////////////////////////////////////" << std::endl;
654 os << line_marker <<
A( 47,
"HamiltonianExchange Module" ) << space( 27 ) << line_marker << std::endl;
655 os << line_marker << space( 74 ) << line_marker << std::endl;
657 os << line_marker <<
A( 20,
"Hamiltonian Cells: " ) << I( 5,
n_temp_levels() )
658 <<
A( 40,
"Hamiltonian Grid Dimension: " ) << I( 5,
exchange_grid_dimension_ ) << space( 4 ) << line_marker << std::endl;
659 os << line_marker << repeat( 74,
'-' ) << line_marker << std::endl;
661 os << line_marker <<
A( 20,
"Grid Cell: " );
665 os <<
A( 15,
" Temperature: " ) << F( 5, 3,
temperature( level ) )
669 os << line_marker << repeat( 74,
'-' ) << line_marker << std::endl;
672 os << line_marker << repeat( 74,
'=' ) << line_marker << std::endl;
673 os << line_marker <<
A( 40,
"Exchange Schedules " ) << std::endl;
676 os << line_marker << repeat( 74,
'-' ) << line_marker << std::endl;
677 for ( ExchangeSchedule::const_iterator it = ex.begin(); it != ex.end(); ++it ) {
681 os << line_marker <<
A( 20,
"( ");
682 for (
Size d=1; d<=n_dim; ++d ) {
683 os << I( 2, coord1[ d ] ) << (d != n_dim ?
", " :
" ) " );
685 os <<
A( 10,
" <--> ( ");
686 for (
Size d=1; d<=n_dim; ++d ) {
687 os << I( 2, coord2[ d ] ) << (d != n_dim ?
", " :
" ) " );
689 os << space( 74-( 20+2+4*n_dim+2+10+8+4*n_dim+2 ) ) << line_marker << std::endl;
693 os <<
"////////////////////////////////////////////////////////////////////////////////" << std::endl;