47 #include "IterationPack_Algorithm.hpp"
48 #include "StopWatchPack_stopwatch.hpp"
49 #include "Teuchos_Assert.hpp"
65 void sig_handler_interrupt_algorithm(
int signum )
67 IterationPack::Algorithm::interrupt();
78 T my_max(
const T& v1,
const T& v2 ) {
return v1 > v2 ? v1 : v2; }
84 enum EInterruptStatus { NOT_INTERRUPTED=0, STOP_END_STEP=1, STOP_END_ITER=2, ABORT_PROGRAM=3 };
86 int static_mpi_initialized =
false;
87 int static_num_running_algorithms = 0;
88 int static_num_proc = 0;
89 int static_proc_rank = 0;
90 bool static_interrupt_called =
false;
91 bool static_processed_user_interrupt =
false;
92 EInterruptStatus static_interrupt_status = NOT_INTERRUPTED;
93 bool static_interrupt_terminate_return =
false;
100 namespace IterationPack {
105 :running_state_(NOT_RUNNING), max_iter_(100)
106 ,max_run_time_(std::numeric_limits<double>::max())
107 ,next_step_name_(0), do_step_next_called_(false), reconfigured_(false)
108 ,time_stats_computed_(false)
112 static_proc_rank = 0;
117 if(!static_mpi_initialized) {
118 int mpi_initialized =
false;
119 MPI_Initialized(&mpi_initialized);
120 if(!mpi_initialized) {
122 char arg_str[] =
"dummy_prg";
123 char *arg_str_ptr = arg_str;
124 char **argv = &arg_str_ptr;
125 MPI_Init( &argc, &argv );
127 static_mpi_initialized =
true;
130 MPI_Comm_size( MPI_COMM_WORLD, &static_num_proc );
131 MPI_Comm_rank( MPI_COMM_WORLD, &static_proc_rank );
132 #ifdef ITERATION_PACK_ALGORITHM_SHOW_MPI_DEBUG_INFO
133 std::cerr <<
"\np=" << static_proc_rank <<
": Algorithm::Algorithm() being called (num_proc = "<<static_num_proc<<
") ... \n";
147 {
return max_iter_; }
155 {
return max_run_time_; }
161 {
return steps_.size(); }
165 steps_t::const_iterator itr = step_itr(step_name);
166 return itr == steps_.end() ? DOES_NOT_EXIST : std::distance( steps_.begin(), itr ) + 1;
170 {
return steps_[validate(step_poss) - 1].name; }
173 {
return steps_[validate(step_poss) - 1].step_ptr; }
176 {
return steps_[validate(step_poss) - 1].step_ptr; }
181 {
return assoc_steps_[validate(step_poss) - 1][type].size(); }
184 ,
const std::string& assoc_step_name)
const
187 const assoc_steps_ele_list_t &assoc_list = assoc_steps_[validate(step_poss) - 1][type];
188 assoc_steps_ele_list_t::const_iterator itr = assoc_step_itr(assoc_list,assoc_step_name);
189 return itr == assoc_list.end() ? DOES_NOT_EXIST : std::distance( assoc_list.begin() , itr ) + 1;
195 const assoc_steps_ele_list_t &assoc_list= assoc_steps_[validate(step_poss) - 1][type];
196 validate(assoc_list,assoc_step_poss);
197 assoc_steps_ele_list_t::const_iterator itr = assoc_list.begin();
198 std::advance( itr, assoc_step_poss - 1 );
205 assoc_steps_ele_list_t &assoc_list= assoc_steps_[validate(step_poss) - 1][type];
206 validate(assoc_list,assoc_step_poss);
207 assoc_steps_ele_list_t::iterator itr = assoc_list.begin();
208 std::advance( itr, assoc_step_poss - 1 );
209 return (*itr).step_ptr;
215 const assoc_steps_ele_list_t &assoc_list= assoc_steps_[validate(step_poss) - 1][type];
216 validate(assoc_list,assoc_step_poss);
217 assoc_steps_ele_list_t::const_iterator itr = assoc_list.begin();
218 std::advance( itr, assoc_step_poss - 1 );
219 return (*itr).step_ptr;
226 validate_not_in_state(RUNNING);
228 step.
get() == NULL, std::invalid_argument
229 ,
"Algorithm::insert_step(...) : A step with the name = \'" << step_name
230 <<
"\' being inserted into the position = " << step_poss
231 <<
" has step.get() == NULL!" );
233 steps_t::iterator itr;
234 if( steps_.end() != ( itr = step_itr(step_name) ) )
237 ,
"Algorithm::insert_step(...) : A step with the name = " << step_name
238 <<
" already exists at step_poss = " << std::distance(steps_.begin(),itr) + 1 );
240 itr = steps_.begin();
241 std::advance ( itr , validate(step_poss,+1) - 1 );
242 steps_.insert( itr , steps_ele_t(step,step_name) );
244 assoc_steps_t::iterator a_itr = assoc_steps_.begin();
245 std::advance ( a_itr , step_poss - 1 );
246 assoc_steps_.insert( a_itr , assoc_steps_ele_t() );
251 validate_not_in_state(RUNNING);
253 validate_not_curr_step(validate(step_poss));
254 validate_not_next_step(steps_[step_poss - 1].name);
256 steps_[step_poss - 1].name = new_name;
261 validate_not_in_state(RUNNING);
262 if(
running_state() == RUNNING_BEING_CONFIGURED) validate_not_curr_step(validate(step_poss));
263 steps_[step_poss - 1].step_ptr = step;
268 validate_not_in_state(RUNNING);
270 validate_not_curr_step(validate(step_poss));
271 validate_not_next_step(steps_[step_poss - 1].name);
274 steps_t::iterator itr = steps_.begin();
275 std::advance ( itr , validate(step_poss) - 1 );
278 assoc_steps_t::iterator a_itr = assoc_steps_.begin();
279 std::advance ( a_itr , step_poss - 1 );
280 assoc_steps_.erase( a_itr );
286 ,
const std::string& assoc_step_name,
const step_ptr_t& assoc_step)
288 validate_not_in_state(RUNNING);
290 assoc_step.
get() == NULL, std::invalid_argument
291 ,
"Algorithm::insert_assoc_step(...) : A step with the name = \'" << assoc_step_name
292 <<
"\' being inserted into the position = " << step_poss
293 <<
"." << ( type == PRE_STEP
296 <<
" has assoc_step.get() == NULL!" );
297 if(
running_state() == RUNNING_BEING_CONFIGURED) validate_not_curr_step(validate(step_poss));
299 assoc_steps_ele_list_t &assoc_list = assoc_steps_[step_poss - 1][type];
300 validate(assoc_list,assoc_step_poss,+1);
301 assoc_steps_ele_list_t::iterator itr = assoc_list.begin();
302 char assoc_type_name[2][10] = {
"PRE_STEP" ,
"POST_STEP" };
303 if( assoc_list.end() != ( itr = assoc_step_itr(assoc_list,assoc_step_name) ) )
306 ,
"Algorithm::insert_assoc_step(...) : An associated step of type = "
307 << assoc_type_name[type]
308 <<
" with the name = " << assoc_step_name
309 <<
" already exists at step_poss = " << step_poss
310 <<
" and assoc_step_poss = " << std::distance(assoc_list.begin(),itr) + 1 );
312 itr = assoc_list.begin();
313 std::advance( itr, assoc_step_poss - 1 );
314 assoc_list.insert( itr , assoc_steps_ele_list_ele_t(assoc_step,assoc_step_name) );
319 validate_not_in_state(RUNNING);
320 if(
running_state() == RUNNING_BEING_CONFIGURED) validate_not_curr_step(validate(step_poss));
322 assoc_steps_ele_list_t &assos_list = assoc_steps_[step_poss - 1][type];
323 validate(assos_list,assoc_step_poss);
324 assoc_steps_ele_list_t::iterator itr = assos_list.begin();
325 std::advance( itr, assoc_step_poss - 1 );
326 assos_list.erase( itr );
333 validate_in_state(RUNNING);
334 saved_next_step_name_ = *next_step_name_;
335 saved_curr_step_name_ = steps_[curr_step_poss_ - 1].name;
336 change_running_state(RUNNING_BEING_CONFIGURED);
341 validate_in_state(RUNNING_BEING_CONFIGURED);
344 steps_t::iterator itr = step_itr(saved_next_step_name_);
346 next_step_poss_ = std::distance( steps_.begin() , itr ) + 1;
347 next_step_name_ = &(*itr).name;
350 itr = step_itr(saved_curr_step_name_);
352 curr_step_poss_ = std::distance( steps_.begin() , itr ) + 1;
357 change_running_state(RUNNING);
358 reconfigured_ =
true;
365 validate_in_state(RUNNING);
366 steps_t::iterator itr = step_itr_and_assert(step_name);
367 next_step_poss_ = std::distance( steps_.begin() , itr ) + 1;
368 next_step_name_ = &(*itr).name;
369 do_step_next_called_ =
true;
374 validate_in_state(RUNNING);
375 const steps_ele_t &ele = steps_[validate(step_poss) - 1];
376 next_step_poss_ = step_poss;
377 next_step_name_ = &ele.name;
378 do_step_next_called_ =
true;
383 validate_in_state(RUNNING);
384 return *next_step_name_;
389 validate_in_state(RUNNING);
390 return next_step_poss_;
395 validate_in_state(RUNNING);
396 return imp_do_step( std::distance( steps_.begin() , step_itr_and_assert(step_name) ) + 1 );
401 validate_in_state(RUNNING);
402 return imp_do_step(step_poss);
407 validate_in_state(RUNNING);
408 terminate_status_ = success ? STATUS_TERMINATE_TRUE : STATUS_TERMINATE_FALSE;
417 validate_in_state(NOT_RUNNING);
423 terminate_status_ = STATUS_KEEP_RUNNING;
424 change_running_state(RUNNING);
427 next_step_poss_ = validate(step_poss);
428 next_step_name_ = &steps_[step_poss - 1].name;
431 step_times_.resize( algo_timing_ ? (
num_steps()+1) * (
max_iter()+1+NUM_STEP_TIME_STATS) : 0 );
437 std::fill_n( step_times_.begin(), step_times_.size(), 0.0 );
438 time_stats_computed_ =
false;
440 stopwatch step_timer;
441 stopwatch overall_timer;
445 overall_timer.start();
448 curr_step_poss_ = next_step_poss_;
461 keep_on = imp_do_step(curr_step_poss_);
464 const double time = my_max(step_timer.stop(),-1e-50);
466 step_times_[
state().
k()-first_k_+(curr_step_poss_-1)*(
max_iter()+1+NUM_STEP_TIME_STATS)] = time;
472 if(terminate_status_ != STATUS_KEEP_RUNNING) {
473 EAlgoReturn algo_return;
474 if( static_interrupt_status == STOP_END_STEP ) {
475 algo_return = ( terminate_status_ == STATUS_TERMINATE_TRUE
476 ? INTERRUPTED_TERMINATE_TRUE
477 : INTERRUPTED_TERMINATE_FALSE );
478 static_interrupt_status = NOT_INTERRUPTED;
481 algo_return = ( terminate_status_ == STATUS_TERMINATE_TRUE
485 return finalize_algorithm(algo_return);
492 if( curr_step_poss_ == static_cast<poss_type>(
num_steps()) ) {
503 return finalize_algorithm(MAX_ITER_EXCEEDED);
508 return finalize_algorithm(MAX_RUN_TIME_EXCEEDED);
512 if( static_interrupt_status == STOP_END_ITER ) {
513 static_interrupt_status = NOT_INTERRUPTED;
514 const EAlgoReturn algo_return = ( static_interrupt_terminate_return
515 ? INTERRUPTED_TERMINATE_TRUE
516 : INTERRUPTED_TERMINATE_FALSE );
517 return finalize_algorithm(algo_return);
525 next_step_name_ = &steps_[0].name;
532 next_step_name_ = &steps_[next_step_poss_ - 1].name;
543 if(!do_step_next_called_)
546 ,
"EAlgoReturn Algorithm::do_algorithm(...) :"
547 " A step object returned false from its do_step(...) operation"
548 " without calling do_step_next(...) to request jump to a specific"
550 do_step_next_called_ =
false;
559 finalize_algorithm(TERMINATE_FALSE);
572 out <<
"\n*** Algorithm Steps ***\n\n";
573 imp_print_algorithm(out,
false);
579 out <<
"\n*** Iteration Quantities ***\n\n";
582 out <<
"\n*** Algorithm Description ***\n\n";
583 imp_print_algorithm(out,
true);
590 validate_not_in_state(RUNNING);
603 validate_not_in_state(RUNNING);
605 if( step_times_.size() == 0 ) {
606 out <<
"No step timing was performed\n";
613 const int m =
state().
k() - first_k_ + 1;
615 const int mmm = mm + NUM_STEP_TIME_STATS;
618 out <<
"\n\n**************************************\n"
619 <<
"*** Algorithm step CPU times (sec) ***\n";
622 out <<
"\nStep names"
624 {
for(
int i = 1; i <= n; ++i ) {
627 out << n+1 <<
") Iteration total\n";
630 out << std::right << std::setprecision(prec);
633 out << setw(w) <<
"" <<
" steps 1..." << n+1 <<
" ->\n\n";
636 out << setw(w) <<
" iter k";
637 {
for(
int i = 1; i <= n+1; ++i ) {
641 out << setw(w) <<
"--------";
642 {
for(
int i = 1; i <= n+1; ++i ) {
643 out << setw(w) <<
"--------";
647 {
for(
int k = 0; k < m; ++k ) {
648 out << setw(w) << first_k_ + k;
649 {
for(
int i = 0; i < n+1; ++i ) {
650 out << setw(w) << step_times_[k+i*mmm];
658 compute_final_time_stats();
662 out << setw(w) <<
"--------";
663 {
for(
int i = 1; i <= n+1; ++i ) {
664 out << setw(w) <<
"--------";
669 out << setw(w) <<
"total(sec)";
670 {
for(
int i = 0; i < n+1; ++i ) {
671 const double *step_i_times = &step_times_[i*mmm];
672 out << setw(w) << step_i_times[ mm + TIME_STAT_TOTALS_OFFSET ];
677 out << setw(w) <<
"av(sec)/k";
678 {
for(
int i = 0; i < n+1; ++i ) {
679 const double *step_i_times = &step_times_[i*mmm];
680 out << setw(w) << step_i_times[ mm + TIME_STAT_AV_OFFSET ];
685 out << setw(w) <<
"min(sec)";
686 {
for(
int i = 0; i < n+1; ++i ) {
687 const double *step_i_times = &step_times_[i*mmm];
688 out << setw(w) << step_i_times[ mm + TIME_STAT_MIN_OFFSET ];
693 out << setw(w) <<
"max(sec)";
694 {
for(
int i = 0; i < n+1; ++i ) {
695 const double *step_i_times = &step_times_[i*mmm];
696 out << setw(w) << step_i_times[ mm + TIME_STAT_MAX_OFFSET ];
701 out << setw(w) <<
"% total";
702 {
for(
int i = 0; i < n+1; ++i ) {
703 const double *step_i_times = &step_times_[i*mmm];
704 out << setw(w) << step_i_times[ mm + TIME_STAT_PERCENT_OFFSET ] * 100.0;
710 out <<
"------------------------------" << endl
711 <<
"total CPU time = " << total_time_ <<
" sec\n";;
718 step_times_.size() == 0, std::logic_error
719 ,
"Algorithm::get_step_times_k(...) : times requested, but no times calculated!"
722 offset > 0, std::invalid_argument
723 ,
"Algorithm::get_step_times_k(...) : Can\'t get times for an iteratin that has not occured yet!."
729 const int mmm = mm + NUM_STEP_TIME_STATS;
731 const int k =
state().
k() + offset;
732 {
for (
int step = 0; step < n+1; ++step) {
733 step_times[step] = step_times_[step*mmm + k];
742 compute_final_time_stats();
747 const int mmm = mm + NUM_STEP_TIME_STATS;
749 double* step_i_times = &
const_cast<step_times_t&
>(step_times_)[step*mmm];
751 *total = step_i_times[mm + TIME_STAT_TOTALS_OFFSET];
754 *average = step_i_times[mm + TIME_STAT_AV_OFFSET];
757 *min = step_i_times[mm + TIME_STAT_MIN_OFFSET];
760 *max = step_i_times[mm + TIME_STAT_MAX_OFFSET];
763 *percent = step_i_times[mm + TIME_STAT_PERCENT_OFFSET];
767 EAlgoReturn Algorithm::finalize_algorithm( EAlgoReturn algo_return )
769 change_running_state(NOT_RUNNING);
775 void Algorithm::compute_final_time_stats()
const
777 if (!time_stats_computed_) {
778 time_stats_computed_ =
true;
781 const int m =
state().
k() - first_k_ + 1;
783 const int mmm = mm + NUM_STEP_TIME_STATS;
786 double &_total_time =
const_cast<double&
>(total_time_);
789 {
for(
int i = 0; i < n+1; ++i ) {
790 double *step_i_times = &
const_cast<step_times_t&
>(step_times_)[i*mmm];
793 step_time = std::accumulate( step_i_times, step_i_times + m, (
double)0.0 );
795 _total_time += step_time;
796 step_i_times[ mm + TIME_STAT_TOTALS_OFFSET ] = step_time;
798 step_i_times[ mm + TIME_STAT_AV_OFFSET ] = step_time / m;
800 step_i_times[ mm + TIME_STAT_MIN_OFFSET ]= *std::min_element( step_i_times, step_i_times + m );
802 step_i_times[ mm + TIME_STAT_MAX_OFFSET ]= *std::max_element( step_i_times, step_i_times + m );
805 {
for(
int i = 0; i < n+1; ++i ) {
806 double *step_i_times = &
const_cast<step_times_t&
>(step_times_)[i*mmm];
808 step_i_times[ mm + TIME_STAT_PERCENT_OFFSET ]
809 = step_i_times[ mm + TIME_STAT_TOTALS_OFFSET ] / total_time_;
816 void Algorithm::change_running_state(ERunningState _running_state)
818 if(
running_state() != RUNNING && _running_state == RUNNING ) {
819 if( static_num_running_algorithms == 0 ) {
821 signal( SIGINT, &sig_handler_interrupt_algorithm );
822 static_interrupt_called =
false;
823 static_processed_user_interrupt =
false;
825 ++static_num_running_algorithms;
827 else if(
running_state() != NOT_RUNNING && _running_state == NOT_RUNNING ) {
828 --static_num_running_algorithms;
829 if( static_num_running_algorithms == 0 ) {
831 signal( SIGINT, SIG_DFL );
832 static_interrupt_called =
false;
833 static_processed_user_interrupt =
false;
836 running_state_ = _running_state;
839 void Algorithm::validate_in_state(ERunningState _running_state)
const {
840 const char running_state_name[3][25] = {
"NOT_RUNNING" ,
"RUNNING",
"RUNNING_BEING_CONFIGURED" };
843 true, InvalidRunningState
844 ,
"Algorithm::validate_in_state(...) : The condition running_state() == "
845 << running_state_name[
running_state()] <<
" has been violated with "
846 <<
" running_state = " << running_state_name[_running_state] );
849 void Algorithm::validate_not_in_state(ERunningState _running_state)
const {
850 const char running_state_name[3][25] = {
"NOT_RUNNING" ,
"RUNNING",
"RUNNING_BEING_CONFIGURED" };
853 true, InvalidRunningState
854 ,
"Algorithm::validate_not_in_state(...) : The condition running_state() != "
855 << running_state_name[
running_state()] <<
" has been violated" );
858 void Algorithm::validate_not_curr_step(poss_type step_poss)
const {
859 if(step_poss == curr_step_poss_)
861 true, InvalidConfigChange
862 ,
"Algorithm::validate_not_curr_step(step_poss="<<step_poss<<
") : "
863 "Error, You can not modify the step being currently executed" );
866 void Algorithm::validate_not_next_step(
const std::string& step_name)
const {
867 if( step_name == saved_next_step_name_ )
869 true, InvalidConfigChange,
870 "Algorithm::validate_not_next_step(step_name): "
871 "Error, You can not modify name or remove the step given by "
872 "step_name = what_is_next_name() = " << step_name );
875 Algorithm::steps_t::iterator Algorithm::step_itr_and_assert(
const std::string& step_name)
877 steps_t::iterator itr = step_itr(step_name);
878 if(itr == steps_.end())
881 ,
"Algorithm::step_itr(...) : A step with the name "
882 << step_name <<
" does not exist." );
886 Algorithm::steps_t::const_iterator Algorithm::step_itr_and_assert(
const std::string& step_name)
const
888 steps_t::const_iterator itr = step_itr(step_name);
889 if(itr == steps_.end())
892 ,
"Algorithm::step_itr(...) : A step with the name "
893 << step_name <<
" does not exist." );
897 bool Algorithm::imp_do_step(poss_type step_poss) {
898 curr_step_poss_ = step_poss;
900 if( !imp_do_assoc_steps(PRE_STEP) )
return false;
902 if( !steps_[curr_step_poss_-1].step_ptr->do_step(*
this, curr_step_poss_, DO_MAIN_STEP, 0) )
return false;
904 if( !imp_do_assoc_steps(POST_STEP) )
return false;
906 if( static_interrupt_status == NOT_INTERRUPTED )
907 look_for_interrupt();
908 if( static_interrupt_status == STOP_END_STEP ) {
909 terminate( static_interrupt_terminate_return );
915 bool Algorithm::imp_do_assoc_steps(EAssocStepType type) {
916 assoc_steps_ele_list_t *assoc_list = &assoc_steps_[curr_step_poss_ - 1][type];
917 assoc_steps_ele_list_t::iterator itr = assoc_list->begin();
918 int n = assoc_list->size();
919 for(
int i = 1; i <= n; ++itr, ++i) {
926 assoc_list = &assoc_steps_[curr_step_poss_ - 1][type];
927 itr = assoc_list->begin();
928 std::advance( itr, i - 1 );
929 reconfigured_ =
false;
932 if( !(*(*itr).step_ptr).do_step(*
this, curr_step_poss_, do_step_type(type), i) )
return false;
937 void Algorithm::imp_inform_steps(inform_func_ptr_t inform_func_ptr)
939 steps_t::const_iterator s_itr = steps_.begin();
940 assoc_steps_t::const_iterator a_itr = assoc_steps_.begin();
942 for(; step_i <= static_cast<poss_type>(
num_steps()); ++step_i, ++s_itr, ++a_itr) {
944 const assoc_steps_ele_list_t &pre_steps = (*a_itr)[PRE_STEP];
945 assoc_steps_ele_list_t::const_iterator pre_step_itr = pre_steps.begin();
946 for(
int pre_step_i = - pre_steps.size(); pre_step_i < 0; ++pre_step_i, ++pre_step_itr) {
947 ((&*(*pre_step_itr).step_ptr)->*inform_func_ptr)(
948 *
this, step_i, DO_PRE_STEP, pre_steps.size()+pre_step_i+1
952 ((&*(*s_itr).step_ptr)->*inform_func_ptr)( *
this, step_i, DO_MAIN_STEP, 0 );
954 const assoc_steps_ele_list_t &post_steps = (*a_itr)[POST_STEP];
955 assoc_steps_ele_list_t::const_iterator post_step_itr = post_steps.begin();
956 for(
int post_step_i = 1; post_step_i <= static_cast<int>(post_steps.size()); ++post_step_i, ++post_step_itr) {
957 ((&*(*post_step_itr).step_ptr)->*inform_func_ptr)(
958 *
this, step_i, DO_POST_STEP, post_step_i
964 void Algorithm::imp_print_algorithm(std::ostream& out,
bool print_steps)
const
967 const std::string leading_str =
" ";
969 steps_t::const_iterator s_itr = steps_.begin();
970 assoc_steps_t::const_iterator a_itr = assoc_steps_.begin();
972 for(; step_i <= static_cast<poss_type>(
num_steps()); ++step_i, ++s_itr, ++a_itr) {
974 const assoc_steps_ele_list_t &pre_steps = (*a_itr)[PRE_STEP];
975 assoc_steps_ele_list_t::const_iterator pre_step_itr = pre_steps.begin();
976 for(
int pre_step_i = - pre_steps.size(); pre_step_i < 0; ++pre_step_i, ++pre_step_itr) {
977 out << step_i <<
"." << pre_step_i <<
". \""
978 << (*pre_step_itr).name <<
"\"\n"
979 << leading_str <<
"(" <<
typeName(*(*pre_step_itr).step_ptr) <<
")\n";
981 (*(*pre_step_itr).step_ptr).print_step( *
this, step_i, DO_PRE_STEP
982 , pre_steps.size()+pre_step_i+1, out, leading_str );
987 out << step_i <<
". \"" << (*s_itr).name
989 << leading_str <<
"(" <<
typeName(*(*s_itr).step_ptr) <<
")\n";
991 (*(*s_itr).step_ptr).print_step( *
this, step_i, DO_MAIN_STEP, 0, out, leading_str );
995 const assoc_steps_ele_list_t &post_steps = (*a_itr)[POST_STEP];
996 assoc_steps_ele_list_t::const_iterator post_step_itr = post_steps.begin();
997 for(
int post_step_i = 1; post_step_i <= static_cast<poss_type>(post_steps.size()); ++post_step_i, ++post_step_itr) {
998 out << step_i <<
"." << post_step_i <<
". \""
999 << (*post_step_itr).name <<
"\"\n"
1000 << leading_str <<
"(" <<
typeName(*(*post_step_itr).step_ptr) <<
")\n";
1002 (*(*post_step_itr).step_ptr).print_step( *
this, step_i, DO_POST_STEP, post_step_i
1003 , out, leading_str );
1010 << step_i <<
". \"Major Loop\" :\n"
1011 <<
" if k >= max_iter then\n"
1012 <<
" terminate the algorithm\n"
1013 <<
" elseif run_time() >= max_run_time then\n"
1014 <<
" terminate the algorithm\n"
1028 step_poss < 1 || steps_.size() + past_end < step_poss, DoesNotExist
1029 ,
"Algorithm::validate(step_poss) : The step_poss = " << step_poss
1030 <<
" is not in range of 1 to " << steps_.size() + past_end );
1035 , poss_type assoc_step_poss,
int past_end)
const
1038 assoc_step_poss < 1 || assoc_list.size() + past_end < assoc_step_poss, DoesNotExist
1039 ,
"Algorithm::validate(assoc_list,assoc_step_poss) : The assoc_step_poss = "
1040 << assoc_step_poss <<
" is not in range of 1 to " << assoc_list.size() + past_end );
1041 return assoc_step_poss;
1044 void Algorithm::look_for_interrupt()
1049 if( static_interrupt_called && !static_processed_user_interrupt && static_proc_rank == 0 ) {
1051 static_interrupt_called =
false;
1055 enum EResponse { R_ABORT_NOW, R_CONTINUE, R_STOP_END_STEP, R_STOP_END_ITER };
1056 EResponse response = R_ABORT_NOW;
1057 const int max_tries = 3;
1058 bool valid_response =
false;
1059 for(
int tries = 0; !valid_response && tries < max_tries; ++tries ) {
1061 <<
"\nIterationPack::Algorithm: Received signal SIGINT."
1062 <<
"\nJust completed current step curr_step_name = \""
1063 <<
get_step_name(curr_step_poss_) <<
"\", curr_step_poss = "
1064 << curr_step_poss_ <<
" of steps [1..." <<
num_steps() <<
"]."
1065 <<
"\nDo you want to:\n"
1066 <<
" (a) Abort the program immediately?\n"
1067 <<
" (c) Continue with the algorithm?\n"
1068 <<
" (s) Gracefully terminate the algorithm at the end of this step?\n"
1069 <<
" (i) Gracefully terminate the algorithm at the end of this iteration?\n"
1070 <<
"Answer a, c, s or i ? ";
1071 char abort_mode =
'a';
1072 std::cin >> abort_mode;
1073 if( abort_mode ==
'a' ) {
1074 response = R_ABORT_NOW;
1075 valid_response =
true;
1077 else if( abort_mode ==
'c' ) {
1078 response = R_CONTINUE;
1079 valid_response =
true;
1081 else if( abort_mode ==
's' || abort_mode ==
'i' ) {
1082 if( abort_mode ==
's')
1083 response = R_STOP_END_STEP;
1085 response = R_STOP_END_ITER;
1087 <<
"\nTerminate the algorithm with true (t) or false (f) ? ";
1088 std::cin >> abort_mode;
1089 if( abort_mode ==
't' ) {
1090 static_interrupt_terminate_return =
true;
1091 valid_response =
true;
1093 else if( abort_mode ==
'f' ) {
1094 static_interrupt_terminate_return =
false;
1095 valid_response =
true;
1098 std::cerr <<
"Invalid response! Expecting \'t\' or \'f\'\n";
1102 std::cerr <<
"\nInvalid response! Expecting \'a\', \'c\', \'s\' or \'i\'\n";
1104 std::cerr << std::endl;
1106 if(!valid_response) {
1107 std::cerr <<
"Three strikes, you are out!\n";
1114 static_interrupt_status = ABORT_PROGRAM;
1118 static_interrupt_status = NOT_INTERRUPTED;
1121 case R_STOP_END_STEP: {
1122 static_interrupt_status = STOP_END_STEP;
1125 case R_STOP_END_ITER: {
1126 static_interrupt_status = STOP_END_ITER;
1133 static_processed_user_interrupt =
true;
1135 else if( interrupt_file_name().length() && !static_processed_user_interrupt && static_proc_rank == 0 ) {
1141 std::ifstream interrupt_file(interrupt_file_name().c_str());
1142 if(interrupt_file) {
1144 <<
"\nIterationPack::Algorithm: Found the interrupt file \""<<interrupt_file_name()<<
"\"!"
1145 <<
"\nJust completed current step curr_step_name = \""
1146 <<
get_step_name(curr_step_poss_) <<
"\", curr_step_poss = "
1147 << curr_step_poss_ <<
" of steps [1..." <<
num_steps() <<
"].\n";
1148 char abort_mode = 0;
1149 interrupt_file >> abort_mode;
1150 std::cerr <<
"Read a value of abort_mode = \'"<<abort_mode<<
"\': ";
1151 if( abort_mode ==
'a' ) {
1152 std::cerr <<
"Will abort the program immediatly!\n";
1153 static_interrupt_status = ABORT_PROGRAM;
1155 else if( abort_mode ==
's' || abort_mode ==
'i' ) {
1156 if( abort_mode ==
's') {
1157 std::cerr <<
"Will abort the program gracefully at the end of this step!\n";
1158 static_interrupt_status = STOP_END_STEP;
1161 std::cerr <<
"Will abort the program gracefully at the end of this iteration!\n";
1162 static_interrupt_status = STOP_END_ITER;
1165 interrupt_file.eof(), std::logic_error,
1166 "IterationPack::Algorithm: Error, expected input for terminate_bool option from the "
1167 "file \""<<interrupt_file_name()<<
"\"!"
1169 char terminate_bool = 0;
1170 interrupt_file >> terminate_bool;
1171 std::cerr <<
"Read a value of terminate_bool = \'"<<terminate_bool<<
"\': ";
1172 if( terminate_bool ==
't' ) {
1173 std::cerr <<
"Will return a success flag!\n";
1174 static_interrupt_terminate_return =
true;
1176 else if( terminate_bool ==
'f' ) {
1177 std::cerr <<
"Will return a failure flag!\n";
1178 static_interrupt_terminate_return =
false;
1182 true, std::logic_error
1183 ,
"Error, the value of terminate_bool = \'"<<terminate_bool<<
"\' is not "
1184 "valid! Valid values include only \'t\' or \'f\'\n"
1190 true, std::logic_error
1191 ,
"Error, the value of abort_mode = \'"<<abort_mode<<
"\' is not "
1192 "valid! Valid values include only \'a\', \'s\' or \'i\'\n"
1195 std::cerr << std::endl;
1196 static_processed_user_interrupt =
true;
1204 const bool query_for_interrupt =
true;
1205 if( static_num_proc > 1 && query_for_interrupt ) {
1211 int sendbuf[2] = { 0, 0 };
1212 int recvbuf[2] = { 0, 0 };
1213 if(static_proc_rank == 0) {
1214 sendbuf[0] = (int)static_interrupt_status;
1215 sendbuf[1] = static_interrupt_terminate_return ? 1 : 0;
1218 #ifdef ITERATION_PACK_ALGORITHM_SHOW_MPI_DEBUG_INFO
1219 std::cerr <<
"\np="<<static_proc_rank<<
": IterationPack::Algorithm::interrupt(): Calling MPI_Allreduce(...) ...\n";
1229 #ifdef ITERATION_PACK_ALGORITHM_SHOW_MPI_DEBUG_INFO
1231 <<
"\np="<<static_proc_rank<<
": IterationPack::Algorithm::interrupt(): After MPI_Allreduce(...)"
1232 <<
"\np="<<static_proc_rank<<
": recvbuf[0] = " << recvbuf[0] <<
", recvbuf[1] = " << recvbuf[1] << std::endl;
1235 switch( (EInterruptStatus)recvbuf[0] ) {
1236 case NOT_INTERRUPTED:
1237 static_interrupt_status = NOT_INTERRUPTED;
1240 static_interrupt_status = STOP_END_STEP;
1243 static_interrupt_status = STOP_END_ITER;
1246 static_interrupt_status = ABORT_PROGRAM;
1250 <<
"p=" << static_proc_rank <<
": Algorithm::look_for_interrupt(): Error, the globally reduced value of "
1251 "recvbuf[0] = " << recvbuf[0] <<
" is not valid!";
1255 static_interrupt_terminate_return = ( recvbuf[1] == 0 ?
false : true );
1260 if( static_interrupt_status == ABORT_PROGRAM ) {
1261 if( static_proc_rank == 0 ) {
1262 std::cerr <<
"\nAborting the program now!\n";
1271 void Algorithm::interrupt()
1288 static_processed_user_interrupt =
false;
1289 #ifdef ITERATION_PACK_ALGORITHM_SHOW_MPI_DEBUG_INFO
1290 std::cerr <<
"\np="<<static_proc_rank<<
": IterationPack::Algorithm::interrupt() called!\n";
1295 if( static_num_proc == 0 ) {
1296 if( static_proc_rank == 0 )
1298 <<
"\nIterationPack::Algorithm::interrupt(): Received signal SIGINT but an Algorithm "
1299 <<
"object has not been allocated yet and no algorithm is running.\n"
1300 <<
"\nAborting the program now!\n";
1307 const bool query_for_interrupt =
true;
1308 if( !query_for_interrupt && static_num_proc > 1 ) {
1309 if( static_proc_rank == 0 ) {
1311 <<
"\nIterationPack::Algorithm::interrupt(): Received signal SIGINT but num_proc = "
1312 << static_num_proc <<
" > 1 and query_for_interrupt = false so:\n"
1313 <<
"\nAborting the program now!\n";
1321 if( static_proc_rank == 0 ) {
1323 <<
"\nIterationPack::Algorithm::interrupt(): Received signal SIGINT. "
1324 <<
"Wait for the end of the current step and respond to an interactive query, "
1325 <<
"kill the process by sending another signal (i.e. SIGKILL).\n";
1327 static_interrupt_called =
true;
virtual EAlgoReturn do_algorithm(poss_type step_poss=1)
Called by clients to begin an algorithm.
virtual void initialize()
Reinitialize the track object right before it is used.
Algorithm()
Constructs an algorithm with no steps and a default of max_iter() == 100.
virtual poss_type get_step_poss(const std::string &step_name) const
Return the possition in the major loop of a named step.
ERunningState running_state() const
Return the current running state of this algorithm object.
virtual void print_steps(std::ostream &out) const
Print out just a listing of the steps, their positions in the algorithm and the subclasses.
virtual void begin_config_update()
Changes from running_state() == RUNNING to running_state() == RUNNING_BEING_CONFIGURED.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual void insert_assoc_step(poss_type step_poss, EAssocStepType type, poss_type assoc_step_poss, const std::string &assoc_step_name, const step_ptr_t &assoc_step)
Insert an pre or post step into for the main step step_poss into the possition assoc_step_poss.
Thrown if an invalid control protocal is used.
virtual bool algo_timing() const
void get_step_times_k(int offset, double step_times[]) const
Returns the step_times for iteration offset.
virtual const std::string & what_is_next_step_name() const
Returns the name of the next step this will call the next time it calls a step.
void get_final_step_stats(size_t step, double *total, double *average, double *min, double *max, double *percent) const
Returns the final statistics for a given step Do not call when algorithm is running.
virtual void insert_step(poss_type step_poss, const std::string &step_name, const step_ptr_t &step)
Insert a step object with the name step_name into the possition step_poss.
virtual int num_steps() const
Return the number of main steps.
virtual void change_step_name(poss_type step_poss, const std::string &new_name)
Change the name of an existing step.
virtual void output_final(const Algorithm &algo, EAlgoReturn algo_return) const
Output information about a just completed algorithm.
virtual void dump_iter_quant(std::ostream &out) const
iteration quantity information dumping.
virtual void print_algorithm(std::ostream &out) const
Print out the entire algorithm by calling print_step(...) on the step objects.
virtual bool do_step(const std::string &step_name)
Calls do_step() on all of the pre step objects the step object and the post step objects in order for...
virtual void terminate(bool success)
Called by step objects to terminate the algorithm.
virtual void replace_step(poss_type step_poss, const step_ptr_t &step)
Replace the step object of an existing step.
virtual void initialize_step(Algorithm &algo, poss_type step_poss, EDoStepType type, poss_type assoc_step_poss)
Called by Algorithm just before the algorithm is run.
virtual void do_step_next(const std::string &step_name)
Called by step objects to set the step (given its name) that this will envoke the next time this call...
virtual poss_type what_is_next_step_poss() const
Returns the possition of the next step this will call the next time it calls a step.
virtual poss_type get_assoc_step_poss(poss_type step_poss, EAssocStepType type, const std::string &assoc_step_name) const
Return the possition of the pre or post step for the main step_poss.
AlgorithmTracker & track()
virtual int num_assoc_steps(poss_type step_poss, EAssocStepType type) const
Return the number of pre or post steps for the main step step_poss.
virtual step_ptr_t & get_assoc_step(poss_type step_poss, EAssocStepType type, poss_type assoc_step_poss)
Return the RCP<...> object for the associated step object at step_poss and assoc_step_poss.
virtual step_ptr_t & get_step(poss_type step_poss)
Return the RCP<...> object for the step object at step_poss.
virtual void inform_updated(Algorithm &algo, poss_type step_poss, EDoStepType type, poss_type assoc_step_poss)
Called by Algorithm to inform when a runtime configuration change is finihed.
virtual void end_config_update()
Changes from running_state() == RUNNING_BEING_CONFIGURED to running_state() == RUNNING.
virtual const std::string & get_step_name(poss_type step_poss) const
Return the name of a step given its possition.
virtual double max_run_time() const
virtual void output_iteration(const Algorithm &algo) const
Output information about an iteration just completed.
virtual void finalize_step(Algorithm &algo, poss_type step_poss, EDoStepType type, poss_type assoc_step_poss)
Called by Algorithm just after an algorithm is terminiated.
virtual void remove_assoc_step(poss_type step_poss, EAssocStepType type, poss_type assoc_step_poss)
Remove an pre or post step for the main step step_poss in the possition assoc_step_poss.
virtual void print_algorithm_times(std::ostream &out) const
Outputs table of times for each step, cummulative times and other statistics.
virtual const std::string & get_assoc_step_name(poss_type step_poss, EAssocStepType type, poss_type assoc_step_poss) const
Return the name of the pre or post step at step_poss and at assoc_step_poss.
virtual void remove_step(poss_type step_poss)
Remove an existing step object and all of its pre and post steps.
Thrown if name already exists.
virtual size_t max_iter() const
virtual void set_algo_timing(bool algo_timing)
Causes algorithm to be timed.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
virtual void next_iteration(bool incr_k=true)
iteration quantity forwarding.
std::string typeName(const T &t)