/*
 *  test_multithreading_devices.sli
 *
 *  This file is part of NEST.
 *
 *  Copyright (C) 2004 The NEST Initiative
 *
 *  NEST is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  NEST is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/* BeginDocumentation
Name: testsuite::test_multithreading_devices - sli script to test data collection across threads

Synopsis: (test_multithreading_devices) run

Description:
This script tests, if data collection across threads is working
correctly. In particular, the test checks if the events dictionary
is the same if we run with one or two threads.

SeeAlso:testsuite::test_multithreading

Author: Jochen Martin Eppler
FirstVersion: May 2010 
*/

% don't run this test if we didn't compile with threads 
statusdict/threading :: (no) eq {statusdict/exitcodes/success :: quit_i} if

/unittest (8418) require
/unittest using

% arrays to store the event dictionaries and n_events for the
% different trials
/sd_n_events  [] def
/sd_events    [] def
/sd_filenames [] def
/mm_n_events  [] def
/mm_events    [] def
/mm_filenames [] def

% We run the simulation with a single thread and compare the events
% dictionary with the one obtained with 2 threads
[1 2] {
    
    /threads Set

    0 << /local_num_threads threads
	   /overwrite_files true
      >> SetStatus

    /iaf_psc_alpha Create /n1 Set
    /iaf_psc_alpha Create /n2 Set

    [n1 n2] {
	  << /I_e 1450.0 >> SetStatus	
    } forall
    
    /spike_detector   Create /sd Set
    /multimeter       Create /mm Set

    [sd mm] {
        << /withgid true /withtime true /to_file true >> SetStatus
    } forall	

    mm << /record_from [/V_m] >> SetStatus
    
    [n1 n2] sd ConvergentConnect
    mm [n1 n2] DivergentConnect

    100 Simulate

    /sd_events    sd_events    sd GetStatus /events    get append def
    /sd_n_events  sd_n_events  sd GetStatus /n_events  get append def
    /sd_filenames sd_filenames sd GetStatus /filenames get append def

    /mm_events    mm_events    mm GetStatus /events    get append def
    /mm_n_events  mm_n_events  mm GetStatus /n_events  get append def
    /mm_filenames mm_filenames mm GetStatus /filenames get append def

    ResetKernel
    
} forall

% sd_events    {values {cva Sort} Map} Map arrayload ; eq assert_or_die
% sd_n_events  arrayload ; eq assert_or_die
% sd_filenames length 2  eq assert_or_die
% 
% mm_events    {values {cva Sort} Map} Map arrayload ; eq assert_or_die
% mm_n_events  arrayload ; eq assert_or_die
% mm_filenames length 2  eq assert_or_die
% 
% %
% % We now test if the recorded data looks as expected
% %
% 
% ResetKernel
% 0 << /local_num_threads 4 >>  SetStatus
% 
% /multimeter  << /record_to [ /memory ] /record_from [ /V_m ] /withgid true /interval 1.0 >> Create /mm Set
% 
% 0 1 3 {
%   cvd /x Set
%   mm /iaf_psc_alpha << /C_m 1.0 /tau_m 1.0 /E_L 0.0 /V_reset 0.0 /V_th 15.0
%                        /I_e x /V_m x  >> Create Connect
% } for
% 
% 2.0 Simulate
% 
% % [4 5 2 3] is the neuron list sorted by their thread
% mm GetStatus /events get /senders get cva [4 5 2 3] eq assert_or_die
% 
% % check the corresponding potentials, also sorted by thread
% mm GetStatus /events get /V_m get cva [2 3 0 1] {cvd} Map eq assert_or_die