/*
 *  test_connect_array_fixed_outdegree_mpi.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_connect_array_fixed_outdegree_mpi - SLI script to test connection with parameter arrays and connection rule fixed_outdegree, with hybrid MPI and thread parallelism

   Synopsis: (test_connect_array_fixed_outdegree_mpi) run

   Description:

   Tests with hybrid MPI and thread parallelism the possibility to use
   parameter arrays to define connection weights and/or delays in conjunction
   with the connection rules fixed_outdegree

   FirstVersion: August 2016
   Author: Bruno Golosio
   SeeAlso: Connect
 */

(unittest) run
/unittest using

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% for a more comprehensive test, uncomment the line for writing the
% results in files, and check the results using the bash script 
% test_connect_array_fixed_outdegree_mpi.sh with the number of
% MPI processes as argument:
% ./test_connect_array_fixed_outdegree_mpi.sh number-of-MPI-processes
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

/write_file false def
%  Uncomment the following line for writing the results in files
%/write_file true def


is_threaded not { exit_test_gracefully } if

[2 3] % check for 2, 3 processes
{

/N 20 def          % number of neurons in each subnet
/K 5 def           % number of connections per neuron

ResetKernel

0 <<
  /local_num_threads 2
>> SetStatus

write_file{
        /filename (proc_) Rank cvs join (.tmp) join def
        % cout filename print
        /fp filename (w) file def
} if

/gid1 N 1 add def            % gid1 = N + 1
/gid2 N 2 mul def            % gid2 = N * 2
/net1 [1 N] Range def        % global ids of source subnet
/net2 [gid1 gid2] Range def  % global ids of target subnet

/iaf_neuron N 2 mul Create ;  % creates source and target subnets

/NC N K mul def     % number of connections
/Dmax NC 1 add def  % maximum delay

/Warr [1 NC] Range cv_dv def    % weight array Warr=[1, ..., NC]
/Darr [2 Dmax] Range cv_dv def  % delay array  Darr=[2, ..., NC+1]
% cv_dv converts sli-array type to double-vector type

% synapses and connection dictionaries
/syn_dict << /model /static_synapse /weight Warr /delay Darr >> def
/conn_dict << /rule /fixed_outdegree /outdegree K >> def

net1 net2 conn_dict syn_dict Connect % connects source to target subnet

/pass true def % error control flag
net1 % loop on all neurons of source subnet
{
        /neuron1 exch def
        write_file {
                fp neuron1 cvs (:) join print ;
        } if

        %cout (n1 ) print neuron1 =
        % gets all connections from the source neuron
        /conn << /source [neuron1] >> GetConnections def

        /sdict_lst conn GetSynapseStatus def % gets info on synapses

        /Warr1 0 array def % creates empty weight array

        sdict_lst % loop on synapses that connect from source neuron
        {
                /sdict exch def
                /w sdict /weight get def  % gets synaptic weight
                /d sdict /delay get def   % gets synaptic delay
                /diff d w sub def         % diff = delay - weight 
                diff 1.0 eq               % checks that d = w + 1
		pass and /pass exch def   % updates control flag

                /Warr1 Warr1 w append def  % appends w to Warr1
        } forall

        %cout (Wl ) print Warr1 length = % checks the size of Warr1
        %/Warr1 Warr1 Sort def       % sorts the elements of Warr1
        write_file {
                Warr1 {
                        fp ( ) print ;
                        fp exch cvs print ;
                } forall
                fp endl ;
        } if

        /i1 neuron1 1 sub K mul def  % first index = (n1 - 1) * K

        % get row of original weight array
        /Wrow Warr cva i1 K getinterval def
        Warr1 {
                /w exch def
                % check that all elements of Warr are in Wrow
                Wrow w MemberQ
		pass and /pass exch def   % updates control flag

        } forall

} forall

write_file {
           fp close
} if

pass
} distributed_collect_assert_or_die
