1 /*
2  *  simulation_manager.cpp
3  *
4  *  This file is part of NEST.
5  *
6  *  Copyright (C) 2004 The NEST Initiative
7  *
8  *  NEST is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  NEST is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #include "simulation_manager.h"
24 
25 // C includes:
26 #include <sys/time.h>
27 
28 // C++ includes:
29 #include <limits>
30 #include <vector>
31 
32 // Includes from libnestutil:
33 #include "compose.hpp"
34 #include "numerics.h"
35 
36 // Includes from nestkernel:
37 #include "connection_manager_impl.h"
38 #include "event_delivery_manager.h"
39 #include "kernel_manager.h"
40 
41 // Includes from sli:
42 #include "dictutils.h"
43 
SimulationManager()44 nest::SimulationManager::SimulationManager()
45   : clock_( Time::tic( 0L ) )
46   , slice_( 0L )
47   , to_do_( 0L )
48   , to_do_total_( 0L )
49   , from_step_( 0L )
50   , to_step_( 0L ) // consistent with to_do_ == 0
51   , t_real_( 0L )
52   , prepared_( false )
53   , simulating_( false )
54   , simulated_( false )
55   , inconsistent_state_( false )
56   , print_time_( false )
57   , use_wfr_( true )
58   , wfr_comm_interval_( 1.0 )
59   , wfr_tol_( 0.0001 )
60   , wfr_max_iterations_( 15 )
61   , wfr_interpolation_order_( 3 )
62   , update_time_limit_( std::numeric_limits< double >::infinity() )
63   , min_update_time_( std::numeric_limits< double >::infinity() )
64   , max_update_time_( -std::numeric_limits< double >::infinity() )
65 {
66 }
67 
68 void
initialize()69 nest::SimulationManager::initialize()
70 {
71   // set resolution, ensure clock is calibrated to new resolution
72   Time::reset_resolution();
73   clock_.calibrate();
74 
75   prepared_ = false;
76   simulating_ = false;
77   simulated_ = false;
78   inconsistent_state_ = false;
79 
80   reset_timers_for_preparation();
81   reset_timers_for_dynamics();
82 }
83 
84 void
finalize()85 nest::SimulationManager::finalize()
86 {
87   nest::Time::reset_to_defaults();
88 
89   clock_.set_to_zero(); // ensures consistent state
90   to_do_ = 0;
91   slice_ = 0;
92   from_step_ = 0;
93   to_step_ = 0; // consistent with to_do_ = 0
94 }
95 
96 void
reset_timers_for_preparation()97 nest::SimulationManager::reset_timers_for_preparation()
98 {
99   sw_communicate_prepare_.reset();
100 #ifdef TIMER_DETAILED
101   sw_gather_target_data_.reset();
102 #endif
103 }
104 
105 void
reset_timers_for_dynamics()106 nest::SimulationManager::reset_timers_for_dynamics()
107 {
108   sw_simulate_.reset();
109 #ifdef TIMER_DETAILED
110   sw_gather_spike_data_.reset();
111   sw_update_.reset();
112 #endif
113 }
114 
115 void
set_status(const DictionaryDatum & d)116 nest::SimulationManager::set_status( const DictionaryDatum& d )
117 {
118   // Create an instance of time converter here to capture the current
119   // representation of time objects: TICS_PER_MS and TICS_PER_STEP
120   // will be stored in time_converter.
121   // This object can then be used to convert times in steps
122   // (e.g. Connection::delay_) or tics to the new representation.
123   // We pass this object to ConnectionManager::calibrate to update
124   // all time objects in the connection system to the new representation.
125   // MH 08-04-14
126   TimeConverter time_converter;
127 
128   double time;
129   if ( updateValue< double >( d, names::biological_time, time ) )
130   {
131     if ( time != 0.0 )
132     {
133       throw BadProperty( "The simulation time can only be set to 0.0." );
134     }
135 
136     if ( clock_ > TimeZero )
137     {
138       // reset only if time has passed
139       LOG( M_WARNING,
140         "SimulationManager::set_status",
141         "Simulation time reset to t=0.0. Resetting the simulation time is not "
142         "fully supported in NEST at present. Some spikes may be lost, and "
143         "stimulation devices may behave unexpectedly. PLEASE REVIEW YOUR "
144         "SIMULATION OUTPUT CAREFULLY!" );
145 
146       clock_ = Time::step( 0 );
147       from_step_ = 0;
148       slice_ = 0;
149       // clear all old spikes
150       kernel().event_delivery_manager.configure_spike_data_buffers();
151     }
152   }
153 
154   updateValue< bool >( d, names::print_time, print_time_ );
155 
156   // tics_per_ms and resolution must come after local_num_thread /
157   // total_num_threads because they might reset the network and the time
158   // representation
159   double tics_per_ms = 0.0;
160   bool tics_per_ms_updated = updateValue< double >( d, names::tics_per_ms, tics_per_ms );
161   double resd = 0.0;
162   bool res_updated = updateValue< double >( d, names::resolution, resd );
163 
164   if ( tics_per_ms_updated or res_updated )
165   {
166     if ( kernel().node_manager.size() > 0 )
167     {
168       LOG( M_ERROR,
169         "SimulationManager::set_status",
170         "Cannot change time representation after nodes have been created. "
171         "Please call ResetKernel first." );
172       throw KernelException();
173     }
174     else if ( has_been_simulated() ) // someone may have simulated empty network
175     {
176       LOG( M_ERROR,
177         "SimulationManager::set_status",
178         "Cannot change time representation after the network has been "
179         "simulated. Please call ResetKernel first." );
180       throw KernelException();
181     }
182     else if ( kernel().connection_manager.get_num_connections() != 0 )
183     {
184       LOG( M_ERROR,
185         "SimulationManager::set_status",
186         "Cannot change time representation after connections have been "
187         "created. Please call ResetKernel first." );
188       throw KernelException();
189     }
190     else if ( kernel().model_manager.has_user_models() or kernel().model_manager.has_user_prototypes() )
191     {
192       LOG( M_ERROR,
193         "SimulationManager::set_status",
194         "Cannot change time representation when user models have been "
195         "created. Please call ResetKernel first." );
196       throw KernelException();
197     }
198     else if ( kernel().model_manager.are_model_defaults_modified() )
199     {
200       LOG( M_ERROR,
201         "SimulationManager::set_status",
202         "Cannot change time representation after model defaults have "
203         "been modified. Please call ResetKernel first." );
204       throw KernelException();
205     }
206     else if ( res_updated and tics_per_ms_updated ) // only allow TICS_PER_MS to
207                                                     // be changed together with
208                                                     // resolution
209     {
210       if ( resd < 1.0 / tics_per_ms )
211       {
212         LOG( M_ERROR,
213           "SimulationManager::set_status",
214           "Resolution must be greater than or equal to one tic. Value "
215           "unchanged." );
216         throw KernelException();
217       }
218       else if ( not is_integer( resd * tics_per_ms ) )
219       {
220         LOG( M_ERROR,
221           "SimulationManager::set_status",
222           "Resolution must be a multiple of the tic length. Value unchanged." );
223         throw KernelException();
224       }
225       else
226       {
227         nest::Time::set_resolution( tics_per_ms, resd );
228         // adjust to new resolution
229         clock_.calibrate();
230         // adjust delays in the connection system to new resolution
231         kernel().connection_manager.calibrate( time_converter );
232         kernel().model_manager.calibrate( time_converter );
233         LOG( M_INFO, "SimulationManager::set_status", "tics per ms and resolution changed." );
234 
235         // make sure that wfr communication interval is always greater or equal
236         // to resolution if no wfr is used explicitly set wfr_comm_interval
237         // to resolution because communication in every step is needed
238         if ( wfr_comm_interval_ < Time::get_resolution().get_ms() or not use_wfr_ )
239         {
240           wfr_comm_interval_ = Time::get_resolution().get_ms();
241         }
242       }
243     }
244     else if ( res_updated ) // only resolution changed
245     {
246       if ( resd < Time::get_ms_per_tic() )
247       {
248         LOG( M_ERROR,
249           "SimulationManager::set_status",
250           "Resolution must be greater than or equal to one tic. Value "
251           "unchanged." );
252         throw KernelException();
253       }
254       else if ( not is_integer( resd / Time::get_ms_per_tic() ) )
255       {
256         LOG( M_ERROR,
257           "SimulationManager::set_status",
258           "Resolution must be a multiple of the tic length. Value unchanged." );
259         throw KernelException();
260       }
261       else
262       {
263         Time::set_resolution( resd );
264         clock_.calibrate(); // adjust to new resolution
265         // adjust delays in the connection system to new resolution
266         kernel().connection_manager.calibrate( time_converter );
267         kernel().model_manager.calibrate( time_converter );
268         LOG( M_INFO, "SimulationManager::set_status", "Temporal resolution changed." );
269 
270         // make sure that wfr communication interval is always greater or equal
271         // to resolution if no wfr is used explicitly set wfr_comm_interval
272         // to resolution because communication in every step is needed
273         if ( wfr_comm_interval_ < Time::get_resolution().get_ms() or not use_wfr_ )
274         {
275           wfr_comm_interval_ = Time::get_resolution().get_ms();
276         }
277       }
278     }
279     else
280     {
281       LOG( M_ERROR,
282         "SimulationManager::set_status",
283         "change of tics_per_step requires simultaneous specification of "
284         "resolution." );
285       throw KernelException();
286     }
287   }
288 
289   // The decision whether the waveform relaxation is used
290   // must be set before nodes are created.
291   // Important: wfr_comm_interval_ may change depending on use_wfr_
292   bool wfr;
293   if ( updateValue< bool >( d, names::use_wfr, wfr ) )
294   {
295     if ( kernel().node_manager.size() > 0 )
296     {
297       LOG( M_ERROR,
298         "SimulationManager::set_status",
299         "Cannot enable/disable usage of waveform relaxation after nodes have "
300         "been created. Please call ResetKernel first." );
301       throw KernelException();
302     }
303     else
304     {
305       use_wfr_ = wfr;
306       // if no wfr is used explicitly set wfr_comm_interval to resolution
307       // because communication in every step is needed
308       if ( not use_wfr_ )
309       {
310         wfr_comm_interval_ = Time::get_resolution().get_ms();
311       }
312     }
313   }
314 
315   // wfr_comm_interval_ can only be changed if use_wfr_ is true and before
316   // connections are created. If use_wfr_ is false wfr_comm_interval_ is set to
317   // the resolution whenever the resolution changes.
318   double wfr_interval;
319   if ( updateValue< double >( d, names::wfr_comm_interval, wfr_interval ) )
320   {
321     if ( not use_wfr_ )
322     {
323       LOG( M_ERROR,
324         "SimulationManager::set_status",
325         "Cannot set waveform communication interval when usage of waveform "
326         "relaxation is disabled. Set use_wfr to true first." );
327       throw KernelException();
328     }
329     else if ( kernel().connection_manager.get_num_connections() != 0 )
330     {
331       LOG( M_ERROR,
332         "SimulationManager::set_status",
333         "Cannot change waveform communication interval after connections have "
334         "been created. Please call ResetKernel first." );
335       throw KernelException();
336     }
337     else if ( wfr_interval < Time::get_resolution().get_ms() )
338     {
339       LOG( M_ERROR,
340         "SimulationManager::set_status",
341         "Communication interval of the waveform relaxation must be greater or "
342         "equal to the resolution of the simulation." );
343       throw KernelException();
344     }
345     else
346     {
347       LOG( M_INFO, "SimulationManager::set_status", "Waveform communication interval changed successfully. " );
348       wfr_comm_interval_ = wfr_interval;
349     }
350   }
351 
352   // set the convergence tolerance for the waveform relaxation method
353   double tol;
354   if ( updateValue< double >( d, names::wfr_tol, tol ) )
355   {
356     if ( tol < 0.0 )
357     {
358       LOG( M_ERROR, "SimulationManager::set_status", "Tolerance must be zero or positive" );
359       throw KernelException();
360     }
361     else
362     {
363       wfr_tol_ = tol;
364     }
365   }
366 
367   // set the maximal number of iterations for the waveform relaxation method
368   long max_iter;
369   if ( updateValue< long >( d, names::wfr_max_iterations, max_iter ) )
370   {
371     if ( max_iter <= 0 )
372     {
373       LOG( M_ERROR,
374         "SimulationManager::set_status",
375         "Maximal number of iterations  for the waveform relaxation must be "
376         "positive. To disable waveform relaxation set use_wfr instead." );
377       throw KernelException();
378     }
379     else
380     {
381       wfr_max_iterations_ = max_iter;
382     }
383   }
384 
385   // set the interpolation order for the waveform relaxation method
386   long interp_order;
387   if ( updateValue< long >( d, names::wfr_interpolation_order, interp_order ) )
388   {
389     if ( ( interp_order < 0 ) or ( interp_order == 2 ) or ( interp_order > 3 ) )
390     {
391       LOG( M_ERROR, "SimulationManager::set_status", "Interpolation order must be 0, 1, or 3." );
392       throw KernelException();
393     }
394     else
395     {
396       wfr_interpolation_order_ = interp_order;
397     }
398   }
399 
400   // update time limit
401   double t_new = 0.0;
402   if ( updateValue< double >( d, names::update_time_limit, t_new ) )
403   {
404     if ( t_new <= 0 )
405     {
406       LOG( M_ERROR, "SimulationManager::set_status", "update_time_limit > 0 required." );
407       throw KernelException();
408     }
409 
410     update_time_limit_ = t_new;
411   }
412 }
413 
414 void
get_status(DictionaryDatum & d)415 nest::SimulationManager::get_status( DictionaryDatum& d )
416 {
417   def< double >( d, names::ms_per_tic, Time::get_ms_per_tic() );
418   def< double >( d, names::tics_per_ms, Time::get_tics_per_ms() );
419   def< long >( d, names::tics_per_step, Time::get_tics_per_step() );
420   def< double >( d, names::resolution, Time::get_resolution().get_ms() );
421 
422   def< double >( d, names::T_min, Time::min().get_ms() );
423   def< double >( d, names::T_max, Time::max().get_ms() );
424 
425   def< double >( d, names::biological_time, get_time().get_ms() );
426   def< long >( d, names::to_do, to_do_ );
427   def< bool >( d, names::print_time, print_time_ );
428 
429   def< bool >( d, names::use_wfr, use_wfr_ );
430   def< double >( d, names::wfr_comm_interval, wfr_comm_interval_ );
431   def< double >( d, names::wfr_tol, wfr_tol_ );
432   def< long >( d, names::wfr_max_iterations, wfr_max_iterations_ );
433   def< long >( d, names::wfr_interpolation_order, wfr_interpolation_order_ );
434 
435   def< double >( d, names::update_time_limit, update_time_limit_ );
436   def< double >( d, names::min_update_time, min_update_time_ );
437   def< double >( d, names::max_update_time, max_update_time_ );
438 
439   def< double >( d, names::time_simulate, sw_simulate_.elapsed() );
440   def< double >( d, names::time_communicate_prepare, sw_communicate_prepare_.elapsed() );
441 #ifdef TIMER_DETAILED
442   def< double >( d, names::time_gather_spike_data, sw_gather_spike_data_.elapsed() );
443   def< double >( d, names::time_update, sw_update_.elapsed() );
444   def< double >( d, names::time_gather_target_data, sw_gather_target_data_.elapsed() );
445 #endif
446 }
447 
448 void
prepare()449 nest::SimulationManager::prepare()
450 {
451   assert( kernel().is_initialized() );
452 
453   if ( prepared_ )
454   {
455     std::string msg = "Prepare called twice.";
456     LOG( M_ERROR, "SimulationManager::prepare", msg );
457     throw KernelException();
458   }
459 
460   if ( inconsistent_state_ )
461   {
462     throw KernelException(
463       "Kernel is in inconsistent state after an "
464       "earlier error. Please run ResetKernel first." );
465   }
466 
467   // reset profiling timers
468   reset_timers_for_dynamics();
469   kernel().event_delivery_manager.reset_timers_for_dynamics();
470 
471   t_real_ = 0;
472   t_slice_begin_ = timeval(); // set to timeval{0, 0} as unset flag
473   t_slice_end_ = timeval();   // set to timeval{0, 0} as unset flag
474 
475   // find shortest and longest delay across all MPI processes
476   // this call sets the member variables
477   kernel().connection_manager.update_delay_extrema_();
478   kernel().event_delivery_manager.init_moduli();
479 
480   // if at the beginning of a simulation, set up spike buffers
481   if ( not simulated_ )
482   {
483     kernel().event_delivery_manager.configure_spike_data_buffers();
484   }
485 
486   kernel().node_manager.ensure_valid_thread_local_ids();
487   kernel().node_manager.prepare_nodes();
488 
489   kernel().model_manager.create_secondary_events_prototypes();
490 
491   // we have to do enter_runtime after prepare_nodes, since we use
492   // calibrate to map the ports of MUSIC devices, which has to be done
493   // before enter_runtime
494   if ( not simulated_ ) // only enter the runtime mode once
495   {
496     double tick = Time::get_resolution().get_ms() * kernel().connection_manager.get_min_delay();
497     kernel().music_manager.enter_runtime( tick );
498   }
499   prepared_ = true;
500 
501   // check whether waveform relaxation is used on any MPI process;
502   // needs to be called before update_connection_intrastructure_since
503   // it resizes coefficient arrays for secondary events
504   kernel().node_manager.check_wfr_use();
505 
506   if ( kernel().node_manager.have_nodes_changed() or kernel().connection_manager.connections_have_changed() )
507   {
508 #pragma omp parallel
509     {
510       const thread tid = kernel().vp_manager.get_thread_id();
511       update_connection_infrastructure( tid );
512     } // of omp parallel
513   }
514 }
515 
516 void
assert_valid_simtime(Time const & t)517 nest::SimulationManager::assert_valid_simtime( Time const& t )
518 {
519   if ( t == Time::ms( 0.0 ) )
520   {
521     return;
522   }
523 
524   if ( t < Time::step( 1 ) )
525   {
526     LOG( M_ERROR,
527       "SimulationManager::run",
528       String::compose( "Simulation time must be >= %1 ms (one time step).", Time::get_resolution().get_ms() ) );
529     throw KernelException();
530   }
531 
532   if ( t.is_finite() )
533   {
534     Time time1 = clock_ + t;
535     if ( not time1.is_finite() )
536     {
537       std::string msg = String::compose(
538         "A clock overflow will occur after %1 of %2 ms. Please reset network "
539         "clock first!",
540         ( Time::max() - clock_ ).get_ms(),
541         t.get_ms() );
542       LOG( M_ERROR, "SimulationManager::run", msg );
543       throw KernelException();
544     }
545   }
546   else
547   {
548     std::string msg = String::compose(
549       "The requested simulation time exceeds the largest time NEST can handle "
550       "(T_max = %1 ms). Please use a shorter time!",
551       Time::max().get_ms() );
552     LOG( M_ERROR, "SimulationManager::run", msg );
553     throw KernelException();
554   }
555 }
556 
557 void
run(Time const & t)558 nest::SimulationManager::run( Time const& t )
559 {
560   assert_valid_simtime( t );
561 
562   kernel().random_manager.check_rng_synchrony();
563   kernel().io_manager.pre_run_hook();
564 
565   if ( not prepared_ )
566   {
567     std::string msg = "Run called without calling Prepare.";
568     LOG( M_ERROR, "SimulationManager::run", msg );
569     throw KernelException();
570   }
571 
572   to_do_ += t.get_steps();
573   to_do_total_ = to_do_;
574 
575   if ( to_do_ == 0 )
576   {
577     return;
578   }
579 
580   // Reset local spike counters within event_delivery_manager
581   kernel().event_delivery_manager.reset_counters();
582 
583   sw_simulate_.start();
584 
585   // from_step_ is not touched here.  If we are at the beginning
586   // of a simulation, it has been reset properly elsewhere.  If
587   // a simulation was ended and is now continued, from_step_ will
588   // have the proper value.  to_step_ is set as in advance_time().
589 
590   delay end_sim = from_step_ + to_do_;
591   if ( kernel().connection_manager.get_min_delay() < end_sim )
592   {
593     to_step_ = kernel().connection_manager.get_min_delay(); // update to end of time slice
594   }
595   else
596   {
597     to_step_ = end_sim; // update to end of simulation time
598   }
599 
600   // Warn about possible inconsistencies, see #504.
601   // This test cannot come any earlier, because we first need to compute
602   // min_delay_
603   // above.
604   if ( t.get_steps() % kernel().connection_manager.get_min_delay() != 0 )
605   {
606     LOG( M_WARNING,
607       "SimulationManager::run",
608       "The requested simulation time is not an integer multiple of the minimal "
609       "delay in the network. This may result in inconsistent results under the "
610       "following conditions: (i) A network contains more than one source of "
611       "randomness, e.g., two different poisson_generators, and (ii) Simulate "
612       "is called repeatedly with simulation times that are not multiples of "
613       "the minimal delay." );
614   }
615 
616   call_update_();
617 
618   kernel().io_manager.post_run_hook();
619   kernel().random_manager.check_rng_synchrony();
620 
621   sw_simulate_.stop();
622 }
623 
624 void
cleanup()625 nest::SimulationManager::cleanup()
626 {
627   if ( not prepared_ )
628   {
629     std::string msg = "Cleanup called without calling Prepare.";
630     LOG( M_ERROR, "SimulationManager::cleanup", msg );
631     throw KernelException();
632   }
633 
634   if ( not simulated_ )
635   {
636     prepared_ = false;
637     return;
638   }
639 
640   kernel().node_manager.finalize_nodes();
641   prepared_ = false;
642 }
643 
644 void
call_update_()645 nest::SimulationManager::call_update_()
646 {
647   assert( kernel().is_initialized() and not inconsistent_state_ );
648 
649   std::ostringstream os;
650   double t_sim = to_do_ * Time::get_resolution().get_ms();
651 
652   size_t num_active_nodes = kernel().node_manager.get_num_active_nodes();
653   os << "Number of local nodes: " << num_active_nodes << std::endl;
654   os << "Simulation time (ms): " << t_sim;
655 
656 #ifdef _OPENMP
657   os << std::endl
658      << "Number of OpenMP threads: " << kernel().vp_manager.get_num_threads();
659 #else
660   os << std::endl
661      << "Not using OpenMP";
662 #endif
663 
664 #ifdef HAVE_MPI
665   os << std::endl
666      << "Number of MPI processes: " << kernel().mpi_manager.get_num_processes();
667 #else
668   os << std::endl
669      << "Not using MPI";
670 #endif
671 
672   LOG( M_INFO, "SimulationManager::start_updating_", os.str() );
673 
674 
675   if ( to_do_ == 0 )
676   {
677     return;
678   }
679 
680   if ( print_time_ )
681   {
682     // TODO: Remove direct output
683     std::cout << std::endl;
684     print_progress_();
685   }
686 
687   simulating_ = true;
688   simulated_ = true;
689 
690   update_();
691 
692   simulating_ = false;
693 
694   if ( print_time_ )
695   {
696     std::cout << std::endl;
697   }
698 
699   kernel().mpi_manager.synchronize();
700 
701   LOG( M_INFO, "SimulationManager::run", "Simulation finished." );
702 }
703 
704 void
update_connection_infrastructure(const thread tid)705 nest::SimulationManager::update_connection_infrastructure( const thread tid )
706 {
707 #pragma omp barrier
708   if ( tid == 0 )
709   {
710     sw_communicate_prepare_.start();
711   }
712 
713   kernel().connection_manager.restructure_connection_tables( tid );
714   kernel().connection_manager.sort_connections( tid );
715   kernel().connection_manager.collect_compressed_spike_data( tid );
716 
717 #pragma omp barrier // wait for all threads to finish sorting
718 
719 #pragma omp single
720   {
721     kernel().connection_manager.compute_target_data_buffer_size();
722     kernel().event_delivery_manager.resize_send_recv_buffers_target_data();
723 
724     // check whether primary and secondary connections exists on any
725     // compute node
726     kernel().connection_manager.sync_has_primary_connections();
727     kernel().connection_manager.check_secondary_connections_exist();
728   }
729 
730   if ( kernel().connection_manager.secondary_connections_exist() )
731   {
732 #pragma omp barrier
733     kernel().connection_manager.compute_compressed_secondary_recv_buffer_positions( tid );
734 #pragma omp barrier
735 #pragma omp single
736     {
737       kernel().mpi_manager.communicate_recv_counts_secondary_events();
738       kernel().event_delivery_manager.configure_secondary_buffers();
739     }
740   }
741 
742 #ifdef TIMER_DETAILED
743   if ( tid == 0 )
744   {
745     sw_gather_target_data_.start();
746   }
747 #endif
748 
749   // communicate connection information from postsynaptic to
750   // presynaptic side
751   kernel().event_delivery_manager.gather_target_data( tid );
752 
753 #ifdef TIMER_DETAILED
754 #pragma omp barrier
755   if ( tid == 0 )
756   {
757     sw_gather_target_data_.stop();
758   }
759 #endif
760 
761   if ( kernel().connection_manager.secondary_connections_exist() )
762   {
763     kernel().connection_manager.compress_secondary_send_buffer_pos( tid );
764   }
765 
766 #pragma omp barrier
767   if ( kernel().connection_manager.use_compressed_spikes() )
768   {
769     kernel().connection_manager.clear_compressed_spike_data_map( tid );
770   }
771 
772 #pragma omp single
773   {
774     kernel().node_manager.set_have_nodes_changed( false );
775     kernel().connection_manager.unset_connections_have_changed();
776   }
777 
778 #pragma omp barrier
779   if ( tid == 0 )
780   {
781     sw_communicate_prepare_.stop();
782   }
783 }
784 
785 bool
wfr_update_(Node * n)786 nest::SimulationManager::wfr_update_( Node* n )
787 {
788   return ( n->wfr_update( clock_, from_step_, to_step_ ) );
789 }
790 
791 void
update_()792 nest::SimulationManager::update_()
793 {
794   // to store done values of the different threads
795   std::vector< bool > done;
796   bool done_all = true;
797   delay old_to_step;
798 
799   double start_current_update = sw_simulate_.elapsed();
800   bool update_time_limit_exceeded = false;
801 
802   std::vector< std::shared_ptr< WrappedThreadException > > exceptions_raised( kernel().vp_manager.get_num_threads() );
803 // parallel section begins
804 #pragma omp parallel
805   {
806     const thread tid = kernel().vp_manager.get_thread_id();
807 
808     do
809     {
810       if ( print_time_ )
811       {
812         gettimeofday( &t_slice_begin_, NULL );
813       }
814 
815       if ( kernel().sp_manager.is_structural_plasticity_enabled()
816         and ( std::fmod( Time( Time::step( clock_.get_steps() + from_step_ ) ).get_ms(),
817                 kernel().sp_manager.get_structural_plasticity_update_interval() ) == 0 ) )
818       {
819         for ( SparseNodeArray::const_iterator i = kernel().node_manager.get_local_nodes( tid ).begin();
820               i != kernel().node_manager.get_local_nodes( tid ).end();
821               ++i )
822         {
823           Node* node = i->get_node();
824           node->update_synaptic_elements( Time( Time::step( clock_.get_steps() + from_step_ ) ).get_ms() );
825         }
826 #pragma omp barrier
827 #pragma omp single
828         {
829           kernel().sp_manager.update_structural_plasticity();
830         }
831         // Remove 10% of the vacant elements
832         for ( SparseNodeArray::const_iterator i = kernel().node_manager.get_local_nodes( tid ).begin();
833               i != kernel().node_manager.get_local_nodes( tid ).end();
834               ++i )
835         {
836           Node* node = i->get_node();
837           node->decay_synaptic_elements_vacant();
838         }
839 
840         // after structural plasticity has created and deleted
841         // connections, update the connection infrastructure; implies
842         // complete removal of presynaptic part and reconstruction
843         // from postsynaptic data
844         update_connection_infrastructure( tid );
845 
846       } // of structural plasticity
847 
848       if ( from_step_ == 0 )
849       {
850 #ifdef HAVE_MUSIC
851 // advance the time of music by one step (min_delay * h) must
852 // be done after deliver_events_() since it calls
853 // music_event_out_proxy::handle(), which hands the spikes over to
854 // MUSIC *before* MUSIC time is advanced
855 
856 // wait until all threads are done -> synchronize
857 #pragma omp barrier
858 // the following block is executed by the master thread only
859 // the other threads are enforced to wait at the end of the block
860 #pragma omp master
861         {
862           // advance the time of music by one step (min_delay * h) must
863           // be done after deliver_events_() since it calls
864           // music_event_out_proxy::handle(), which hands the spikes over to
865           // MUSIC *before* MUSIC time is advanced
866           if ( slice_ > 0 )
867           {
868             kernel().music_manager.advance_music_time();
869           }
870 
871           // the following could be made thread-safe
872           kernel().music_manager.update_music_event_handlers( clock_, from_step_, to_step_ );
873         }
874 // end of master section, all threads have to synchronize at this point
875 #pragma omp barrier
876 #endif
877       }
878 
879       // preliminary update of nodes that use waveform relaxtion, only
880       // necessary if secondary connections exist and any node uses
881       // wfr
882       if ( kernel().connection_manager.secondary_connections_exist() and kernel().node_manager.wfr_is_used() )
883       {
884 #pragma omp single
885         {
886           // if the end of the simulation is in the middle
887           // of a min_delay_ step, we need to make a complete
888           // step in the wfr_update and only do
889           // the partial step in the final update
890           // needs to be done in omp single since to_step_ is a scheduler
891           // variable
892           old_to_step = to_step_;
893           if ( to_step_ < kernel().connection_manager.get_min_delay() )
894           {
895             to_step_ = kernel().connection_manager.get_min_delay();
896           }
897         }
898 
899         bool max_iterations_reached = true;
900         const std::vector< Node* >& thread_local_wfr_nodes = kernel().node_manager.get_wfr_nodes_on_thread( tid );
901         for ( long n = 0; n < wfr_max_iterations_; ++n )
902         {
903           bool done_p = true;
904 
905           // this loop may be empty for those threads
906           // that do not have any nodes requiring wfr_update
907           for ( std::vector< Node* >::const_iterator i = thread_local_wfr_nodes.begin();
908                 i != thread_local_wfr_nodes.end();
909                 ++i )
910           {
911             done_p = wfr_update_( *i ) and done_p;
912           }
913 
914 // add done value of thread p to done vector
915 #pragma omp critical
916           done.push_back( done_p );
917 // parallel section ends, wait until all threads are done -> synchronize
918 #pragma omp barrier
919 
920 // the following block is executed by a single thread
921 // the other threads wait at the end of the block
922 #pragma omp single
923           {
924             // check whether all threads are done
925             for ( size_t i = 0; i < done.size(); ++i )
926             {
927               done_all = done[ i ] and done_all;
928             }
929 
930             // gather SecondaryEvents (e.g. GapJunctionEvents)
931             kernel().event_delivery_manager.gather_secondary_events( done_all );
932 
933             // reset done and done_all
934             //(needs to be in the single threaded part)
935             done_all = true;
936             done.clear();
937           }
938 
939           // deliver SecondaryEvents generated during wfr_update
940           // returns the done value over all threads
941           done_p = kernel().event_delivery_manager.deliver_secondary_events( tid, true );
942 
943           if ( done_p )
944           {
945             max_iterations_reached = false;
946             break;
947           }
948         } // of for (wfr_max_iterations) ...
949 
950 #pragma omp single
951         {
952           to_step_ = old_to_step;
953           if ( max_iterations_reached )
954           {
955             std::string msg = String::compose( "Maximum number of iterations reached at interval %1-%2 ms",
956               clock_.get_ms(),
957               clock_.get_ms() + to_step_ * Time::get_resolution().get_ms() );
958             LOG( M_WARNING, "SimulationManager::wfr_update", msg );
959           }
960         }
961 
962       } // of if(wfr_is_used)
963         // end of preliminary update
964 
965 #ifdef TIMER_DETAILED
966 #pragma omp barrier
967       if ( tid == 0 )
968       {
969         sw_update_.start();
970       }
971 #endif
972       const SparseNodeArray& thread_local_nodes = kernel().node_manager.get_local_nodes( tid );
973 
974       for ( SparseNodeArray::const_iterator n = thread_local_nodes.begin(); n != thread_local_nodes.end(); ++n )
975       {
976         // We update in a parallel region. Therefore, we need to catch
977         // exceptions here and then handle them after the parallel region.
978         try
979         {
980           Node* node = n->get_node();
981           if ( not( node )->is_frozen() )
982           {
983             ( node )->update( clock_, from_step_, to_step_ );
984           }
985         }
986         catch ( std::exception& e )
987         {
988           // so throw the exception after parallel region
989           exceptions_raised.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( e ) );
990         }
991       }
992 
993 // parallel section ends, wait until all threads are done -> synchronize
994 #pragma omp barrier
995 #ifdef TIMER_DETAILED
996       if ( tid == 0 )
997       {
998         sw_update_.stop();
999         sw_gather_spike_data_.start();
1000       }
1001 #endif
1002 
1003       // gather and deliver only at end of slice, i.e., end of min_delay step
1004       if ( to_step_ == kernel().connection_manager.get_min_delay() )
1005       {
1006         if ( kernel().connection_manager.has_primary_connections() )
1007         {
1008           kernel().event_delivery_manager.gather_spike_data( tid );
1009         }
1010         if ( kernel().connection_manager.secondary_connections_exist() )
1011         {
1012 #pragma omp single
1013           {
1014             kernel().event_delivery_manager.gather_secondary_events( true );
1015           }
1016           kernel().event_delivery_manager.deliver_secondary_events( tid, false );
1017         }
1018       }
1019 
1020 #pragma omp barrier
1021 #ifdef TIMER_DETAILED
1022       if ( tid == 0 )
1023       {
1024         sw_gather_spike_data_.stop();
1025       }
1026 #endif
1027 
1028 // the following block is executed by the master thread only
1029 // the other threads are enforced to wait at the end of the block
1030 #pragma omp master
1031       {
1032         advance_time_();
1033 
1034         if ( print_time_ )
1035         {
1036           gettimeofday( &t_slice_end_, NULL );
1037           print_progress_();
1038         }
1039 
1040         // We cannot throw exception inside master, would not get caught.
1041         const double end_current_update = sw_simulate_.elapsed();
1042         const double update_time = end_current_update - start_current_update;
1043         update_time_limit_exceeded = update_time > update_time_limit_;
1044         min_update_time_ = std::min( min_update_time_, update_time );
1045         max_update_time_ = std::max( max_update_time_, update_time );
1046         start_current_update = end_current_update;
1047       }
1048 // end of master section, all threads have to synchronize at this point
1049 #pragma omp barrier
1050       kernel().io_manager.post_step_hook();
1051 // enforce synchronization after post-step activities of the recording backends
1052 #pragma omp barrier
1053       const double end_current_update = sw_simulate_.elapsed();
1054       if ( end_current_update - start_current_update > update_time_limit_ )
1055       {
1056         LOG( M_ERROR, "SimulationManager::update", "Update time limit exceeded." );
1057         throw KernelException();
1058       }
1059       start_current_update = end_current_update;
1060 
1061     } while ( to_do_ > 0 and not update_time_limit_exceeded and not exceptions_raised.at( tid ) );
1062 
1063     // End of the slice, we update the number of synaptic elements
1064     for ( SparseNodeArray::const_iterator i = kernel().node_manager.get_local_nodes( tid ).begin();
1065           i != kernel().node_manager.get_local_nodes( tid ).end();
1066           ++i )
1067     {
1068       Node* node = i->get_node();
1069       node->update_synaptic_elements( Time( Time::step( clock_.get_steps() + to_step_ ) ).get_ms() );
1070     }
1071 
1072   } // of omp parallel
1073 
1074   if ( update_time_limit_exceeded )
1075   {
1076     LOG( M_ERROR, "SimulationManager::update", "Update time limit exceeded." );
1077     throw KernelException();
1078   }
1079 
1080   // check if any exceptions have been raised
1081   for ( thread tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid )
1082   {
1083     if ( exceptions_raised.at( tid ).get() )
1084     {
1085       simulating_ = false; // must mark this here, see #311
1086       inconsistent_state_ = true;
1087       throw WrappedThreadException( *( exceptions_raised.at( tid ) ) );
1088     }
1089   }
1090 }
1091 
1092 void
advance_time_()1093 nest::SimulationManager::advance_time_()
1094 {
1095   // time now advanced time by the duration of the previous step
1096   to_do_ -= to_step_ - from_step_;
1097 
1098   // advance clock, update modulos, slice counter only if slice completed
1099   if ( ( delay ) to_step_ == kernel().connection_manager.get_min_delay() )
1100   {
1101     clock_ += Time::step( kernel().connection_manager.get_min_delay() );
1102     ++slice_;
1103     kernel().event_delivery_manager.update_moduli();
1104     from_step_ = 0;
1105   }
1106   else
1107   {
1108     from_step_ = to_step_;
1109   }
1110 
1111   long end_sim = from_step_ + to_do_;
1112 
1113   if ( kernel().connection_manager.get_min_delay() < ( delay ) end_sim )
1114   {
1115     // update to end of time slice
1116     to_step_ = kernel().connection_manager.get_min_delay();
1117   }
1118   else
1119   {
1120     to_step_ = end_sim; // update to end of simulation time
1121   }
1122 
1123   assert( to_step_ - from_step_ <= ( long ) kernel().connection_manager.get_min_delay() );
1124 }
1125 
1126 void
print_progress_()1127 nest::SimulationManager::print_progress_()
1128 {
1129   double rt_factor = 0.0;
1130 
1131   if ( t_slice_end_.tv_sec != 0 )
1132   {
1133     // usec
1134     long t_real_s = ( t_slice_end_.tv_sec - t_slice_begin_.tv_sec ) * 1e6;
1135     // usec
1136     t_real_ += t_real_s + ( t_slice_end_.tv_usec - t_slice_begin_.tv_usec );
1137     // ms
1138     double t_real_acc = ( t_real_ ) / 1000.;
1139     double t_sim_acc = ( to_do_total_ - to_do_ ) * Time::get_resolution().get_ms();
1140     // real-time factor = wall-clock time / model time
1141     rt_factor = t_real_acc / t_sim_acc;
1142   }
1143 
1144   int percentage = ( 100 - int( float( to_do_ ) / to_do_total_ * 100 ) );
1145 
1146   std::cout << "\r[ " << std::setw( 3 ) << std::right << percentage << "% ] "
1147             << "Model time: " << std::fixed << std::setprecision( 1 ) << clock_.get_ms() << " ms, "
1148             << "Real-time factor: " << std::setprecision( 4 ) << rt_factor
1149             << std::resetiosflags( std::ios_base::floatfield );
1150   std::flush( std::cout );
1151 }
1152 
1153 nest::Time const
get_previous_slice_origin() const1154 nest::SimulationManager::get_previous_slice_origin() const
1155 {
1156   return clock_ - Time::step( kernel().connection_manager.get_min_delay() );
1157 }
1158