27 #include <utility/exit.hh>
28 #include <utility/file/file_sys_util.hh>
29 #include <basic/prof.hh>
30 #include <basic/options/keys/cluster.OptionKeys.gen.hh>
31 #include <basic/options/keys/mc.OptionKeys.gen.hh>
32 #include <basic/options/keys/score.OptionKeys.gen.hh>
36 #include <ObjexxFCL/FArray3D.hh>
37 #include <ObjexxFCL/FArray2D.hh>
39 #include <basic/Tracer.hh>
47 #include <utility/vector1.hh>
50 static basic::Tracer
tr(
"MPIHPool_ConvergenceCheck");
53 namespace canonical_sampling{
54 namespace mc_convergence_checks{
62 MPI_Comm protocols::canonical_sampling::mc_convergence_checks::MPIHPool_RMSD::MPI_COMM_POOL;
63 using namespace basic;
69 hlevel_( levels, silent_file ),
71 num_structures_added_(0),
74 new_decoys_out_(
"discovered_decoys.out"),
77 first_time_writing_( true ),
80 current_best_rmsds_(),
82 current_address_str_(
"no_address"),
90 MPIHPool_RMSD::receive_and_output_structures(
94 while( num_structures_to_write > 0 ) {
96 receive_silent_struct_any_source( sfd, ss, buf_.winning_address_, buf_.new_level_begins_ );
97 if( first_time_writing_ ) {
98 first_time_writing_ =
false;
99 write_headers_to_hierarchy( ss );
101 write_decoys_to_hierarchy( sfd, ss, buf_.winning_address_, buf_.new_level_begins_ );
102 num_structures_to_write--;
109 for(
core::Size ii = 1; ii <= new_addr.size(); ii++ ) {
110 if( new_addr[ ii ] == 0 ) {
111 if( new_level_start == 0 ) new_level_start = ii;
112 core::Size next_free_index = hlevel_.pool_size( new_addr, ii - 1 ) + 1;
113 runtime_assert( next_free_index != 0 );
114 new_addr[ ii ] = next_free_index;
117 core::Size id_num = hlevel_.pool_size( new_addr, hlevel_.nlevels() ) + 1;
118 if( new_level_start < new_addr.size() && new_level_start > 0 && id_num != 1 ) {
119 if (
tr.Error.visible() ) {
120 tr.Error <<
"new level start is " << new_level_start <<
" so new branches are created, but pool size is NOT zero! " << hlevel_.pool_size( new_addr, hlevel_.nlevels() ) <<
" for address: ";
121 for(
core::Size ii = 1; ii <= new_addr.size(); ii++ ) {
122 tr.Error << new_addr[ ii ] <<
" ";
124 tr.Error << std::endl;
127 if(
tr.visible() )
tr.Debug <<
"about to check runtime-asserts: " << id_num <<
" " << hlevel_.first_zero_pos( new_addr ) <<
" " << hlevel_.nlevels() << std::endl;
129 runtime_assert( ( id_num == 1 && hlevel_.first_zero_pos( new_addr ) <= hlevel_.nlevels() ) ||
130 ( id_num >= 1 && hlevel_.first_zero_pos( new_addr ) > hlevel_.nlevels() ) );
131 if( tracer_visible_ ) {
132 tr.Debug <<
"pool size is " << id_num <<
" for addr: ";
133 for(
core::Size ii = 1; ii <= hlevel_.nlevels(); ii++ ) {
134 tr.Debug << new_addr[ ii ] <<
" | ";
136 for(
core::Size ii = 1; ii <= hlevel_.nlevels(); ii++ ) {
137 tr.Debug << buf_.candidate_address_[ ii ] <<
" ";
139 tr.Debug << std::endl;
142 assign_tag( new_addr, id_num, new_candidate_tag );
147 MPIHPool_RMSD::evaluate_and_add(
152 using namespace basic;
153 PROF_START( basic::MPIBARRIER_BEGIN );
154 MPI_Barrier( MPI_COMM_POOL );
155 PROF_STOP( basic::MPIBARRIER_BEGIN );
157 PROF_START( basic::MPIH_EVAL_CHECK_PROGRESS );
158 if( tracer_visible_ ) {
159 tr.Debug <<
"now in evaluate and add, number of structures in top-level pool: " << hlevel_.top_level_pool_size() <<
" pool-rank: " << pool_rank_ <<
" pool-size: " << pool_npes_ << std::endl;
166 runtime_assert( pool_npes_ > 0 );
167 buf_.setup( pool_npes_, nresidues_, nlevels_ );
172 core::Size num_nodes_finished = any_node_finished();
173 if( num_nodes_finished > 0 ) {
174 if( pool_npes_ - num_nodes_finished == 0 ) {
175 if( tracer_visible_ ) {
176 tr.Info <<
"no more nodes running trajectories, returning " << std::endl;
177 tr.Info <<
"finishing trajectory" << std::endl;
181 update_comm( pool_npes_ - num_nodes_finished );
183 MPI_Comm_rank( MPI_COMM_POOL, (
int* )( &pool_rank_ ) );
184 MPI_Comm_size( MPI_COMM_POOL, (
int* )( &pool_npes_ ) );
188 PROF_STOP( basic::MPIH_EVAL_CHECK_PROGRESS );
192 best_index = hlevel_.evaluate( pose, best_decoy, current_best_rmsds_, best_address_ );
193 if( tracer_visible_ ) {
194 tr.Debug <<
"finished evaluating, best decoy has the tag: " << best_decoy <<
"\n";
195 for(
core::Size ii = 1; ii <= current_best_rmsds_.size() ; ii++ ) {
196 tr.Debug <<
"level=" << ii <<
" best-rmsd=" << current_best_rmsds_[ ii ] <<
" level-radii=" << level_radii_[ ii ] <<
" best-level-address=" << best_address_[ ii ] << std::endl;
198 tr.Debug <<
"done dumping out information about best-rmsd" << std::endl;
201 hlevel_.debug_print_size_per_level();
202 PROF_START( basic::MPIH_EVAL_COMMUNICATE_NEW );
207 if ( is_new_structure( best_address_, level_radii_, current_best_rmsds_ ) ) {
208 if(
tr.visible() )
tr.Debug <<
"i've found a new structure!" << std::endl;
209 runtime_assert(buf_.coords_.u1() > 0 && buf_.coords_.u2() > 0);
210 runtime_assert(buf_.coords_.u1() > 0 && buf_.coords_.u2() > 0);
211 prepare_send_new_coords(
true );
212 sendcounts = ( 3 * nresidues_ );
214 prepare_send_new_coords(
false );
216 MPI_Allgather( buf_.int_buf1_, nlevels_, MPI_INT, buf_.neighbor_addresses_, nlevels_, MPI_INT, MPI_COMM_POOL );
218 best_rmsd = current_best_rmsds_[ current_best_rmsds_.size() ];
219 double candidate_best_rms = best_rmsd;
221 MPI_Allgather( &candidate_best_rms, 1, MPI_DOUBLE, buf_.candidate_best_rmsds_, 1, MPI_DOUBLE, MPI_COMM_POOL );
222 if( tracer_visible_ ) {
223 tr.Debug <<
"address of all-nbrs: " << (nlevels_ * pool_npes_ )
224 <<
" nlevel: " << nlevels_ <<
" npes " << pool_npes_ << std::endl;
225 for(
core::Size ii = 0; ii < ( nlevels_ * pool_npes_ ); ii++ ) {
226 tr.Debug << buf_.neighbor_addresses_[ ii ] <<
" ";
228 tr.Debug << std::endl;
230 if( tracer_visible_ )
tr.Debug <<
"scan output and setup to receive" << std::endl;
231 scan_output_and_setup_to_receive();
232 if( tracer_visible_ )
tr.Debug <<
"done calling scan output and setup to receive" << std::endl;
233 MPI_Allgatherv( buf_.coords_transfer_buffer_,
236 buf_.coords_receiving_buffer_,
243 PROF_STOP( basic::MPIH_EVAL_COMMUNICATE_NEW );
245 bool i_am_a_winning_rank =
false;
246 buf_.candidate_nbr_index_ = 0;
250 num_structures_added_ = 0;
252 if( buf_.num_new_neighbors_ > 0 ) {
254 PROF_START( basic::MPIH_ADD_FIRST_STRUCTURE );
255 bool has_new_structure = get_next_candidate();
256 runtime_assert( has_new_structure );
257 ++num_structures_added_;
258 new_addr = buf_.candidate_address_;
260 Address unresolved = buf_.candidate_address_;
261 resolve_address_and_assign_tag( new_addr, new_level_start, new_candidate_tag );
264 if( is_my_structure() ) {
265 i_am_a_winning_rank =
true;
266 buf_.winning_address_ = new_addr;
267 buf_.winning_tag_ = new_candidate_tag;
268 buf_.new_level_begins_ = new_level_start;
271 hlevel_.add_new( buf_.candidate_coords_, new_candidate_tag, new_addr );
272 if( tracer_visible_ ) {
273 tr.Debug <<
"adding this structure to hierarchy: ";
274 for(
core::Size ii = 1; ii <= new_addr.size(); ii++ ) {
275 tr.Debug << new_addr[ ii ] <<
" ";
277 tr.Debug <<
" " << new_candidate_tag << std::endl;
280 prev_added_addresses.push_back( unresolved );
283 std::list<PoolData>::iterator itr;
284 hlevel_.level_find( new_addr, hlevel_.nlevels(), itr );
285 prev_added_start_indices.push_back( (*itr).pool_->size() );
287 PROF_STOP( basic::MPIH_ADD_FIRST_STRUCTURE );
289 while( get_next_candidate() ) {
290 PROF_START( basic::MPIH_EVAL_AGAINST_NBR );
292 Address best_addr( hlevel_.nlevels(), 0);
296 bool is_new_structure =
true;
297 for(
core::Size ii = 1; ii <= prev_added_addresses.size(); ii++ ) {
299 bool equal_addresses =
true;
300 for(
core::Size jj = 1; jj <= buf_.candidate_address_.size(); jj++ ) {
301 if( buf_.candidate_address_[ jj ] != (prev_added_addresses[ ii ])[ jj ] ) {
302 equal_addresses =
false;
306 if( equal_addresses ) {
307 Address test_addr = prev_added_addresses[ ii ];
308 hlevel_.evaluate( buf_.candidate_coords_,
314 core::Size last_pos_nonzero = hlevel_.first_zero_pos( test_addr ) - 1;
315 if( candidate_rmsd[ last_pos_nonzero ] < level_radii_[ last_pos_nonzero ] ) {
318 for(
core::Size ii = 1; ii <= candidate_rmsd.size(); ii++ ) {
319 tr.Debug <<
"level-addr=" << test_addr[ ii ] <<
" rms=" << candidate_rmsd[ ii ] <<
" radius=" << level_radii_[ ii ] << std::endl;
321 tr.Debug <<
"hence this structure is deemed a redundant structure, rejecting!" << std::endl;
323 is_new_structure =
false;
330 if( is_new_structure ) {
331 ++num_structures_added_;
333 Address new_addr = buf_.candidate_address_;
335 hlevel_.evaluate( buf_.candidate_coords_,
342 if( hlevel_.address_exists_in_cache( new_addr ) ) {
343 new_candidate_tag =
"";
344 resolve_address_and_assign_tag( new_addr, new_level_start, new_candidate_tag );
345 hlevel_.add_new( buf_.candidate_coords_, new_candidate_tag, new_addr );
347 if( is_my_structure() ) {
348 i_am_a_winning_rank =
true;
349 buf_.winning_address_ = new_addr;
350 buf_.winning_tag_ = new_candidate_tag;
351 buf_.new_level_begins_ = new_level_start;
353 if( tracer_visible_ ) {
354 tr.Debug <<
"adding structure to hierarchy ";
355 for(
core::Size ii = 1; ii <= new_addr.size(); ii++ ) {
356 tr.Debug << new_addr[ ii ] <<
" ";
358 tr.Debug <<
" " << new_candidate_tag << std::endl;
361 core::Size index = find_address( new_addr, prev_added_addresses );
362 if( index > prev_added_addresses.size() ) {
364 prev_added_addresses.push_back( unresolved );
365 std::list<PoolData>::iterator itr;
366 hlevel_.level_find( new_addr, hlevel_.nlevels(), itr );
367 prev_added_start_indices.push_back( (*itr).pool_->size() );
371 PROF_STOP( basic::MPIH_EVAL_AGAINST_NBR );
373 send_receive_and_write_structures( i_am_a_winning_rank, pose );
374 if ( num_structures_added_ > 0 ) {
376 PROF_START( basic::MPIH_UPDATE_EVAL );
381 for(
core::Size ii =1 ; ii <= prev_added_addresses.size(); ii++ ) {
382 Address test_addr = prev_added_addresses[ ii ];
383 core::Size second_update_index = hlevel_.evaluate( buf_.coords_,
384 second_update_best_decoy,
389 if( hlevel_.first_zero_pos( test_addr ) == hlevel_.nlevels() + 1 &&
390 second_update_rmsd[ second_update_rmsd.size() ] < best_rmsd &&
391 second_update_best_decoy.compare(
"") != 0 ) {
392 best_rmsd = second_update_rmsd[ second_update_rmsd.size() ];
393 best_decoy = second_update_best_decoy;
394 best_index = second_update_index;
398 PROF_STOP( basic::MPIH_UPDATE_EVAL );
400 send_receive_and_write_structures(
false, pose );
418 hlevel_.debug_print_size_per_level();
419 PROF_START( basic::MPIBARRIER_END );
420 MPI_Barrier( MPI_COMM_POOL );
421 PROF_STOP( basic::MPIBARRIER_END );
425 MPIHPool_RMSD::send_receive_and_write_structures(
bool i_am_a_winning_rank,
core::pose::Pose const& pose) {
428 bool use_batch_write_out =
false;
429 if( use_batch_write_out ) {
430 if(
tr.visible() )
tr.Debug <<
"attempting to use batch write-out to dump decoys" << std::endl;
432 if( i_am_a_winning_rank ) print = 1;
433 int* have_structure_to_print =
new int[ pool_npes_ ];
434 MPI_Allgather( &print, 1, MPI_INT, have_structure_to_print, 1, MPI_INT, MPI_COMM_POOL );
435 if( i_am_a_winning_rank ) {
439 for(
core::Size ii = 0; ii < pool_npes_; ii++ ) {
440 if(
tr.visible() )
tr.Debug <<
"looking at position " << ii <<
" of " << pool_npes_ << std::endl;
441 if( have_structure_to_print[ ii ] == 1 ) {
442 bool same_unresolved_addr =
true;
443 for(
core::Size jj = 0; jj < hlevel_.nlevels(); jj++ ) {
444 if( best_address_[ jj + 1 ] != buf_.neighbor_addresses_[ (ii * hlevel_.nlevels()) + jj ] ) same_unresolved_addr =
false;
446 if( same_unresolved_addr ) {
449 tr.Debug <<
"my current query address: ";
450 for(
core::Size kk = 1; kk <= best_address_.size(); kk++ ) {
451 tr.Debug << best_address_[ kk ] <<
" ";
453 tr.Debug <<
" compared to nbr rank: " << ii <<
" ";
454 for(
core::Size kk = 0; kk < hlevel_.nlevels(); kk++ ) {
455 tr.Debug << buf_.neighbor_addresses_[ (ii * hlevel_.nlevels()) + kk ] <<
" ";
457 tr.Debug <<
"are the same and will be grouped together for writing to file" << std::endl;
460 if( ii < min_ranking_proc ) min_ranking_proc = ii;
463 if(
tr.visible() )
tr.Debug <<
"no matching addresses, will not group any processes together" << std::endl;
464 have_structure_to_print[ ii ] = 0;
469 if( pool_rank_ == min_ranking_proc ) {
470 if(
tr.visible() )
tr.Debug <<
"I am the min ranking proc: " << pool_rank_ <<
" and i am printing out these rank neighbors: ";
471 for(
core::Size ii = 0; ii < num_nbrs; ii++ ) {
472 if( have_structure_to_print[ ii ] == 1 ) {
474 tr.Debug <<
" nbr rank: " << ii <<
" ";
475 for(
core::Size jj = 0; jj < hlevel_.nlevels(); jj++ ) {
476 tr.Debug << buf_.neighbor_addresses_[ ( ii * hlevel_.nlevels() ) + jj ] <<
" ";
481 if(
tr.visible() )
tr.Debug << std::endl;
484 ss->fill_struct( pose, buf_.winning_tag_ );
485 if( first_time_writing_ ) {
486 first_time_writing_ =
false;
487 write_headers_to_hierarchy( ss );
489 write_decoys_to_hierarchy( sfd, ss, buf_.winning_address_, buf_.new_level_begins_ );
492 receive_and_output_structures( sfd, num_nbrs );
494 }
else if( pool_rank_ != min_ranking_proc ) {
495 if(
tr.visible() )
tr.Debug <<
"sending my structure to min-ranking-proc: " << min_ranking_proc << std::endl;
498 ss->fill_struct( pose, buf_.winning_tag_ );
499 send_silent_struct_to_rank( sfd, ss, buf_.winning_address_, buf_.new_level_begins_ , min_ranking_proc );
504 PROF_START( basic::MPIH_PREPARE_WRITE_STRUCTURES );
505 int num_structures_to_write = 0;
507 if( i_am_a_winning_rank ) {
508 int num_to_print = 1;
509 MPI_Reduce( &num_to_print, &num_structures_to_write, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_POOL );
511 int num_to_print = 0;
512 MPI_Reduce( &num_to_print, &num_structures_to_write, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_POOL );
514 PROF_STOP( basic::MPIH_PREPARE_WRITE_STRUCTURES );
517 if( tracer_visible_ ) {
tr.Debug <<
"expecting to write out " << num_structures_to_write <<
" structures" << std::endl; }
520 PROF_START( basic::MPIH_WRITE_STRUCT );
522 if( i_am_a_winning_rank ) {
525 ss->fill_struct( pose, buf_.winning_tag_ );
526 if( first_time_writing_ ) {
527 first_time_writing_ =
false;
528 write_headers_to_hierarchy( ss );
530 write_decoys_to_hierarchy( sfd, ss, buf_.winning_address_, buf_.new_level_begins_ );
531 num_structures_to_write--;
533 receive_and_output_structures( sfd, num_structures_to_write );
534 PROF_STOP( basic::MPIH_WRITE_STRUCT );
537 PROF_START( basic::MPIH_WRITE_STRUCT );
538 if( i_am_a_winning_rank ) {
542 ss->fill_struct( pose, buf_.winning_tag_ );
543 send_silent_struct_to_rank( sfd, ss, buf_.winning_address_, buf_.new_level_begins_ );
545 PROF_STOP( basic::MPIH_WRITE_STRUCT );
551 MPIHPool_RMSD::buf_to_address(
Address & addr,
int* addr_buf,
core::Size index ) {
552 for(
core::Size ii = 1; ii <= addr.size(); ii++ ) {
553 addr[ ii ] = addr_buf[ index + ii - 1 ];
558 MPIHPool_RMSD::address_to_buf(
Address & addr,
int* addr_buf,
core::Size index ) {
559 for(
core::Size ii = 1; ii <= addr.size(); ii++ ) {
560 addr_buf[ index + ii - 1 ] = addr[ ii ];
565 MPIHPool_RMSD::is_my_structure() {
566 return ( ( buf_.candidate_nbr_index_ - 1 ) == pool_rank_);
571 MPIHPool_RMSD::is_new_structure(
Address & address,
574 for(
core::Size ii = 1; ii <= address.size(); ii++ ) {
575 if( address[ ii ] == 0 ) {
576 if(
tr.visible() )
tr.Debug <<
"address at level " << ii <<
" is 0, so is a new structure " << std::endl;
580 if( rmsds[ rmsds.size() ] > hlevel_.level_radius( hlevel_.nlevels() ) ) {
581 if(
tr.visible() )
tr.Debug <<
"rms at last-level is: " << rmsds[ rmsds.size() ] <<
" which is greater than radius, " << hlevel_.level_radius( hlevel_.nlevels() ) <<
" so is a new structure" << std::endl;
584 if(
tr.visible() )
tr.Debug <<
" structure is not a new structure" << std::endl;
591 for(
core::Size ii = 1; ii <= addr.size(); ii++ ) {
592 if( addr[ ii ] != 0 ) {
593 best_rms = rmsd[ ii ];
600 MPIHPool_RMSD::is_new_structure(
Address & address,
603 for(
core::Size ii = 1; ii <= address.size(); ii++ ) {
604 if( address[ ii ] == 0 ){
609 if( rmsd > radii[ radii.size() ] ) {
618 MPIHPool_RMSD::print_address(
Address & addr ) {
620 for(
core::Size ii = 1; ii <= addr.size(); ii++ ) {
621 tr.Debug << addr[ ii ] <<
" ";
623 tr.Debug << std::endl;
629 PROF_START( basic::HIERARCHY_FIND_ADDRESS );
631 for( index = 1; index <= addr_database.size(); index++ ) {
632 bool found_a_match =
true;
633 for(
core::Size jj = 1; jj <= query.size(); jj++ ) {
634 if( query[ jj ] != ((
Address )addr_database[ index ])[ jj ] ) {
635 found_a_match =
false;
638 if( found_a_match ) {
642 PROF_STOP( basic::HIERARCHY_FIND_ADDRESS );
647 MPIHPool_RMSD::any_node_finished(){
648 buf_.int_buf1_[ 0 ] = current_trajectory_state_;
649 MPI_Allgather( buf_.int_buf1_, 1, MPI_INT, buf_.finished_, 1, MPI_INT, MPI_COMM_POOL );
652 for(
unsigned int ii = 0; ii < pool_npes_; ii++ ) {
653 if( buf_.finished_[ ii ] ==
FINISHED ) {
654 num_nodes_finished++;
656 buf_.int_buf1_[ index_in_prog++ ] = ii;
660 tr.Debug <<
"number of nodes finished this round: " << num_nodes_finished << std::endl;
662 return num_nodes_finished;
666 MPIHPool_RMSD::update_comm(
core::Size newsize ) {
668 tr.Debug <<
"some trajectories finished, creating new comm with " << newsize << std::endl;
670 create_comm( buf_.int_buf1_, newsize );
672 buf_.setup( newsize, nresidues_, nlevels_ );
674 MPI_Comm_rank( MPI_COMM_POOL, (
int* )( &pool_rank_ ) );
675 MPI_Comm_size( MPI_COMM_POOL, (
int* )( &pool_npes_ ) );
676 tr.Info <<
"remaining ranks has pool-size of " << pool_npes_ <<
" and rank: " << pool_rank_ << std::endl;
682 MPIHPool_RMSD::prepare_send_new_coords(
bool send_coords ){
684 runtime_assert( nlevels_ == best_address_.size() );
685 for(
core::Size ii = 1; ii <= best_address_.size(); ii++ ) {
687 buf_.int_buf1_[ ii - 1 ] = best_address_[ ii ];
689 buf_.farray_to_array( 0, buf_.coords_, buf_.coords_transfer_buffer_ );
692 for(
core::Size ii = 0; ii < nlevels_; ii++ ){
693 buf_.int_buf1_[ ii ] = -1;
700 MPIHPool_RMSD::get_next_candidate() {
701 PROF_START( basic::HIERARCHY_GET_NEXT_CANDIDATE );
703 if( buf_.candidate_nbr_index_ < (buf_.is_a_neighbor_).size() ) {
705 for( itr = buf_.candidate_nbr_index_ + 1; itr <= (buf_.is_a_neighbor_).size(); itr++ ) {
706 if( buf_.is_a_neighbor_[ itr ] ) {
707 buf_.array_to_farray( buf_.memory_offset_[ itr - 1 ], buf_.candidate_coords_, buf_.coords_receiving_buffer_ );
708 for(
core::Size ii = 1; ii <= nlevels_; ii++ ) {
709 buf_.candidate_address_[ ii ] = buf_.neighbor_addresses_[ ( ( itr - 1 ) * nlevels_ ) + ( ii - 1 ) ];
711 buf_.candidate_best_rmsd_ = buf_.candidate_best_rmsds_[ itr - 1 ];
712 buf_.candidate_nbr_index_ = itr;
714 tr.Debug <<
"next examining address: ";
715 for(
core::Size ii = 1; ii <= buf_.candidate_address_.size(); ii++ ) {
716 tr.Debug << buf_.candidate_address_[ ii ] <<
" ";
718 tr.Debug << std::endl;
723 PROF_STOP( basic::HIERARCHY_GET_NEXT_CANDIDATE );
724 if( itr > (buf_.is_a_neighbor_).size()) {
return false; }
733 using namespace core::io::silent;
734 using namespace basic;
735 PROF_START( basic::HIERARCHY_RECV_COORDS );
737 std::istringstream os;
741 int* output_info =
new int[ 2 + ss_addr.size() ];
746 string_size = output_info[ 0 ];
747 char *cbuf =
new char[ string_size + 1 ];
748 int sending_rank = stat.MPI_SOURCE;
749 for(
core::Size ii =1; ii <= ss_addr.size(); ii++ ) {
750 ss_addr[ ii ] = output_info[ ii ];
752 new_level_begins = output_info[ ss_addr.size() + 1 ];
754 MPI_Recv( cbuf, string_size, MPI_CHAR, sending_rank,
OUTPUT_TAG, MPI_COMM_POOL, &stat );
755 received_string.assign( cbuf, string_size );
756 os.str( received_string );
759 ss = *(recv_ss.
begin());
761 tr.Debug <<
"just received structure from rank: " << sending_rank
762 <<
" with tag " << ss->decoy_tag() <<
" new_level begins at: " << new_level_begins << std::endl;
765 PROF_STOP( basic::HIERARCHY_RECV_COORDS );
770 using namespace core::io::silent;
771 using namespace basic;
772 PROF_START( basic::HIERARCHY_SEND_COORDS );
774 std::ostringstream os;
776 int* output_info =
new int[ 2 + ss_addr.size() ];
778 int string_size = (os.str()).
size();
779 output_info[ 0 ] = string_size;
780 for(
core::Size ii = 1; ii <= ss_addr.size(); ii++ ) {
781 output_info[ ii ] = ss_addr[ ii ];
784 output_info[ ss_addr.size() + 1 ] = new_level;
785 if (
tr.visible() ) {
786 tr.Debug <<
"sending decoy with tag: " << ss->decoy_tag() <<
" new-level is " << new_level << std::endl;
788 MPI_Send(output_info, ( 2 + ss_addr.size() ), MPI_INT, receiving_rank,
OUTPUT_TAG, MPI_COMM_POOL );
790 MPI_Send(const_cast<char*> (os.str().data()), string_size, MPI_CHAR, receiving_rank,
OUTPUT_TAG, MPI_COMM_POOL);
791 PROF_STOP( basic::HIERARCHY_SEND_COORDS );
796 send_silent_struct_to_rank( send_ss, ss, ss_addr, new_level,
MPI_OUTPUT_RANK );
802 MPIHPool_RMSD::scan_output_and_setup_to_receive(){
803 buf_.num_new_neighbors_ = 0;
804 PROF_START( basic::HIERARCHY_SETUP_TO_RECV );
805 buf_.is_a_neighbor_.resize( pool_npes_,
false );
807 runtime_assert(buf_.is_a_neighbor_.size() == pool_npes_ );
809 Address nbr_address( nlevels_, 0 );
811 for(
unsigned int i = 0; i < pool_npes_; i++ ) {
812 if( buf_.neighbor_addresses_[ (i * nlevels_ ) ] != -1 ) {
813 for(
core::Size ii = 1; ii <= nbr_address.size(); ii++ ) {
814 nbr_address[ ii ] = buf_.neighbor_addresses_[ ( i * nlevels_ ) + ( ii - 1 ) ];
816 if( hlevel_.address_exists_in_cache( nbr_address ) ) {
817 buf_.is_a_neighbor_[ i + 1 ] =
true;
818 buf_.num_new_neighbors_++;
820 buf_.is_a_neighbor_[ i + 1 ] =
false;
823 buf_.is_a_neighbor_[ i + 1 ] =
false;
827 tr.Debug <<
"my current query address: ";
828 for(
core::Size ii = 1; ii <= best_address_.size(); ii++ ) {
829 tr.Debug << best_address_[ ii ] <<
" ";
831 tr.Debug << std::endl;
833 hlevel_.debug_print_size_per_level();
834 tr.Debug <<
"these are the addresses I will be examining: ";
835 for(
core::Size ii = 1; ii <= buf_.is_a_neighbor_.size(); ii++ ) {
836 if( buf_.is_a_neighbor_[ ii ] == 1 ) {
837 for(
core::Size jj = 1; jj <= nbr_address.size(); jj++ ) {
838 tr.Debug << buf_.neighbor_addresses_[ ( (ii-1) * nlevels_ ) + ( jj - 1 ) ] <<
" ";
843 tr.Debug << std::endl;
849 for(
core::Size ii = 0; ii < (pool_npes_ * nlevels_ ); ii+=nlevels_ ) {
850 if ( buf_.neighbor_addresses_[ ii ] > 0 ) {
851 buf_.int_buf1_[ index ] = ( nresidues_ * 3 );
852 buf_.memory_offset_[ index ] = receive_counts;
853 receive_counts += ( nresidues_ * 3 );
855 buf_.int_buf1_[ index ] = 0;
856 buf_.memory_offset_[ index ] = 0;
860 PROF_STOP( basic::HIERARCHY_SETUP_TO_RECV );
864 MPIHPool_RMSD::set_discovered_out(
std::string const& newout){
865 new_decoys_out_ = newout;
869 MPIHPool_RMSD::get_discovered_out(){
870 return new_decoys_out_;
874 MPIHPool_RMSD::set_transition_threshold(
core::Real threshold ){
876 runtime_assert( threshold >= 0 );
880 MPIHPool_RMSD::set_nresidues(
core::Size nres ){
885 MPIHPool_RMSD::get_nresidues(){
891 hlevel_.write_headers_to_hierarchy( ss );
896 using namespace basic;
897 PROF_START( basic::WRITE_DECOYS_TO_HIERARCHY );
899 if( new_level_begins == 0 ) new_level_begins = tmp_addr.size() + 1;
901 tr.Debug <<
"writing decoy to hierarchy: " << ss->decoy_tag() <<
" ";
902 for(
core::Size ii =1; ii <= ss_addr.size(); ii++ ) {
903 tr.Debug << ss_addr[ ii ] <<
" ";
905 tr.Debug <<
" new_level: " << new_level_begins << std::endl;
908 for(
core::Size ii = new_level_begins; ii <= tmp_addr.size(); ii++ ) {
913 std::string file_in_hierarchy = hlevel_.lib_full_path( tmp_addr );
916 utility::file::create_directory_recursive( file.path() );
917 utility::file::create_blank_file( file.name() );
919 os.open( (file.name()).c_str() );
920 ss->print_header( os );
924 tr.Debug << index <<
" writing decoy " << ss->decoy_tag() <<
" to file: " << file_in_hierarchy << std::endl;
927 os.open( (file_in_hierarchy).c_str(), std::ios::app );
930 if( index <= ss_addr.size() ) {
931 tmp_addr[ index ] = ss_addr[ index ];
934 }
while( index++ <= ss_addr.size() );
937 PROF_STOP( basic::WRITE_DECOYS_TO_HIERARCHY );
941 MPIHPool_RMSD::max_cache_size(
core::Size max_cache ) {
942 hlevel_.max_cache_size( max_cache );
946 MPIHPool_RMSD::finalize(){
947 PROF_START( basic::FINALIZE );
948 MPI_Barrier( MPI_COMM_POOL );
949 current_trajectory_state_ =
FINISHED;
950 tr.Info <<
"rank: " << pool_rank_ <<
" calling finalized on trajectory " << std::endl;
951 core::Size num_nodes_finished = any_node_finished();
953 tr.Debug <<
"dumping hierarchy (debug) " << std::endl;
954 hlevel_.debug_print_hierarchy();
956 if( num_nodes_finished > 0 ) {
957 tr.Info <<
"num nodes finished this round: " << num_nodes_finished <<
" of " << pool_npes_ << std::endl;
958 if( ( pool_npes_ - num_nodes_finished ) == 0 ) {
961 update_comm( pool_npes_ - num_nodes_finished );
963 PROF_STOP( basic::FINALIZE );
968 MPIHPool_RMSD::initialize(){
969 using namespace core;
970 using namespace basic::options;
971 using namespace basic::options::OptionKeys;
972 using namespace basic;
974 tr.Info <<
"initializing hierarchical MPI class" << std::endl;
976 clock_t start_setup = clock();
980 PROF_START( basic::CHECK_COMM_SIZE );
981 MPI_Comm_rank( MPI_COMM_WORLD, (
int* )( &rank_ ) );
982 MPI_Comm_size( MPI_COMM_WORLD, (
int* )( &npes_ ) );
983 PROF_STOP( basic::CHECK_COMM_SIZE );
985 PROF_START( basic::INITIALIZE );
991 level_radii_ = option[ cluster::K_radius ]();
992 runtime_assert( level_radii_.size() == nlevels_ );
999 new_size = npes_ - min_client_rank;
1001 utility_exit_with_message(
"cannot use MPIHPool_RMSD without using the MPIFileBufJobDistributor! try again!");
1005 nresidues_ = Pool_RMSD::natom();
1006 current_address_.resize( nlevels_, 0 );
1008 PROF_STOP( basic::INITIALIZE );
1010 tr.Info <<
"initializing comm" << std::endl;
1011 PROF_START( basic::MPICOMMCREATION );
1013 if(
tr.visible() )
tr.Debug <<
"now trying to set up new communicator" << std::endl;
1014 buf_.setup( pool_npes_, nresidues_, nlevels_ );
1015 for(
unsigned int ii = min_client_rank; ii < npes_; ii++){
1016 (buf_.int_buf1_)[ index++ ] = ii;
1017 if(
tr.visible() )
tr.Debug <<
"including " << ii <<
" in the new pool communicator " << std::endl;
1021 MPI_Group pool_group, all;
1024 returnval = MPI_Comm_group( MPI_COMM_WORLD, &all);
1025 if ( returnval != MPI_SUCCESS ) {
1026 utility_exit_with_message(
"failed in creating a new communicator!");
1028 if(
tr.visible() )
tr.Debug <<
"set up MPI_COMM_WORLD group" << std::endl;
1030 returnval = MPI_Group_incl( all, (new_size), buf_.int_buf1_, &pool_group );
1031 if ( returnval != MPI_SUCCESS ) {
1032 utility_exit_with_message(
"failed in creating a new communicator!");
1034 if(
tr.visible() )
tr.Debug <<
"created the pool group" << std::endl;
1036 returnval = MPI_Comm_create( MPI_COMM_WORLD, pool_group, &MPI_COMM_POOL );
1037 if ( returnval != MPI_SUCCESS ) {
1038 utility_exit_with_message(
"failed in creating a new communicator!");
1040 if(
tr.visible() )
tr.Debug <<
"created the MPI_COMM_POOL communicator " << std::endl;
1042 if( rank_ >= min_client_rank ) {
1043 MPI_Comm_rank( MPI_COMM_POOL, (
int* )( &pool_rank_ ) );
1044 MPI_Comm_size( MPI_COMM_POOL, (
int* )( &pool_npes_ ) );
1045 if(
tr.visible() )
tr.Debug <<
"new ranks from MPI_COMM_POOL: " << pool_rank_ <<
" " << pool_npes_ << std::endl;
1048 PROF_STOP( basic::MPICOMMCREATION );
1049 if(
tr.visible() )
tr.Debug <<
"finished initializing, setting up new comm, and ready to go!" << std::endl;
1050 PROF_START( basic::INITIALIZE_HIERARCHY );
1051 tracer_visible_ =
tr.visible();
1053 Address universal_address( nlevels_, 0 );
1054 universal_address[ 1 ] = 1;
1057 tr.Info <<
"checking for hierarchy..." << std::endl;
1058 if(
tr.visible() )
tr.Debug <<
"does pool exist? " << hlevel_.lib_full_path( universal_address ) <<
" : " << hlevel_.pool_exists( universal_address ) << std::endl;
1059 if( !hlevel_.pool_exists( universal_address ) ) {
1060 if( rank_ >= min_client_rank ) {
1061 MPI_Barrier( MPI_COMM_POOL );
1062 tr.Info <<
"hierarchical pool doesn't exist. creating hierarchy " << std::endl;
1064 if( option[ mc::read_structures_into_pool ].user() ) {
1066 utility_exit_with_message(
"you specified a file for option mc::read_structures_into_pool that does not exist! try again!");
1071 bool successfully_read_file =
false;
1074 while( !successfully_read_file && attempt < max_attempts ) {
1075 successfully_read_file = sfd.
read_file( hlevel_.filename() );
1077 if ( successfully_read_file ) {
1079 for(
core::Size ii = 1; ii <= tags.size(); ii++ ) {
1081 ss = sfd[ tags[ ii ] ];
1086 hlevel_.evaluate( (*ss), best_decoy, best_rms, best_addr );
1087 for(
core::Size jj = 1; jj <= best_addr.size(); jj++ ) {
1088 if( best_addr[ jj ] == 0 ) {
1089 if( new_level_starts_at == 0 ) new_level_starts_at = jj;
1090 best_addr[ jj ] = hlevel_.pool_size( best_addr, jj - 1 ) + 1;
1093 if( rank_ == min_client_rank ) {
1094 hlevel_.add_new( (*ss), tags[ ii ], best_addr,
true, 2 );
1096 hlevel_.add_new( (*ss), tags[ ii ], best_addr,
false, 2 );
1100 utility_exit_with_message(
"cannot read silent file. thus cannot create hierarchy! filename: " + hlevel_.filename());
1106 if( rank_ >= min_client_rank ) {
1107 tr.Info <<
"pool already exists!! loading file as top-level" << std::endl;
1108 Pool_RMSD_OP top_level_pool =
new Pool_RMSD( hlevel_.lib_full_path( universal_address ) );
1109 if(
tr.visible() )
tr.Debug <<
"finished reading pool from file: " << hlevel_.lib_full_path( universal_address ) << std::endl;
1110 hlevel_.fill_top_level( top_level_pool );
1112 if( rank_ >= min_client_rank ) {
1113 MPI_Barrier( MPI_COMM_POOL );
1116 tr.Info <<
"this rank: " << pool_rank_ <<
" starting out with " << hlevel_.top_level_pool_size() <<
" structures in the top-most-level of hierarchy" << std::endl;
1117 if(
tr.visible() ) {
1118 hlevel_.debug_print_size_per_level();
1119 tr.Debug <<
"END PRINTING SIZE PER LEVEL FOR INITIATION" << std::endl;
1121 clock_t finish_setup = clock();
1122 double time_to_setup = ( double(finish_setup) - double(start_setup) ) / CLOCKS_PER_SEC;
1123 tr <<
"time to setup " << pool_npes_ <<
" nodes: " << time_to_setup << std::endl;
1124 PROF_STOP( basic::INITIALIZE_HIERARCHY );
1128 MPIHPool_RMSD::is_in_neighborhood(
Address & q_address,
Address & ref_address ) {
1130 runtime_assert( q_address.size() == ref_address.size() );
1132 for(
core::Size ii = 1; ii <= ref_address.size(); ii++ ) {
1133 if( q_address[ ii ] != 0 && ref_address[ ii ] != 0 &&
1134 q_address[ ii ] != ref_address[ ii ] ) {
1144 std::ostringstream q;
1147 for(
core::Size ii = 1; ii <= address_buf.size(); ii++) {
1148 q << address_buf[ ii ];
1149 address_tag += q.str() +
".";
1159 core::Size prefix_pos = address_tag.find(
'.',0);
1160 address_tag.erase(0,prefix_pos);
1162 while( counted_levels < nlevels_ ) {
1163 newpos = address_tag.find(
'.', pos+1 );
1164 if( newpos == address_tag.length() ) {
1168 subtag = address_tag.substr( pos + 1, (newpos-pos - 1) );
1171 core::Size first_nonzero_pos = subtag.find_first_not_of(
'0',0);
1172 if (first_nonzero_pos > 0 ) {
1173 subtag.erase(0,first_nonzero_pos);
1175 address_buf[ index + counted_levels ] = atoi(subtag.c_str());
1178 while( counted_levels < nlevels_ ){
1179 address_buf[ index + counted_levels ] = 0;
1187 std::ostringstream q;
1188 for(
core::Size ii = 1; ii <= address_tag.size(); ii++ ) {
1189 if( address_tag[ ii ] == 0 ) {
1191 q << hlevel_.pool_size( address_tag, (prev_level) ) + 1 <<
".";
1192 if(
tr.visible() )
tr.Debug <<
" at level " << ii <<
" assigning " << ( hlevel_.pool_size( address_tag, ii - 1 ) + 1 ) << std::endl;
1194 q << address_tag[ ii ] <<
".";
1198 newtag =
"new." + q.str();
1209 std::ostringstream q;
1210 q << assigned_id_num;
1211 newtag =
"new." + address_tag +
"." + q.str();
1216 void MPIHPool_RMSD::create_comm(
int* ranks_to_include,
int new_size ){
1218 MPI_Group new_pool_group, old_pool_group;
1219 MPI_Comm dup_pool_comm;
1220 PROF_START( basic::MPICOMMCREATION );
1221 MPI_Comm_dup( MPI_COMM_POOL, &dup_pool_comm );
1222 returnval = MPI_Comm_group( dup_pool_comm, &old_pool_group );
1223 assert(returnval == MPI_SUCCESS );
1225 returnval = MPI_Group_incl( old_pool_group, new_size, ranks_to_include, &new_pool_group );
1226 assert(returnval == MPI_SUCCESS );
1228 returnval = MPI_Comm_create( dup_pool_comm, new_pool_group, &MPI_COMM_POOL );
1229 assert(returnval == MPI_SUCCESS );
1230 PROF_STOP( basic::MPICOMMCREATION );