/*
 *  test_connect_array_fixed_indegree_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_indegree_mpi - SLI script to test connection with parameter arrays and connection rule fixed_indegree, with hybrid MPI and thread parallelism

   Synopsis: (test_connect_array_fixed_indegree_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_indegree

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

(unittest) run
/unittest using

skip_if_not_threaded

[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

/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_indegree /indegree K >> def

net1 net2 conn_dict syn_dict Connect % connects source to target subnet

/pass true def % error control flag
/n_loc 0 def  % used to check n. of neurons belonging to this MPI process
net2 % loop on all neurons of target subnet
{
        /neuron2 exch def

        neuron2 GetStatus /local get  % checks if neuron2 is local or not
        {
                /n_loc n_loc 1 add def  % increases n_loc
                % gets all connections to the target neuron
                /conn << /target [neuron2] >> 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 to target 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

                Warr1 length K eq         % checks the size of Warr1
		pass and /pass exch def   % updates control flag

                /Warr1 Warr1 Sort def       % sorts the elements of Warr1
                /i1 neuron2 gid1 sub K mul def  % first index = (n2 - gid1) * K

                % get row of original weight array, sort it
                % and compare it with Warr1
                /Wdiff Warr cva i1 K getinterval Sort Warr1 sub def
                % check that all elements of the difference are zero
                Wdiff 0.0 HasDifferentMemberQ not
		pass and /pass exch def   % updates control flag

        } if
} forall
pass n_loc 0 gt and
} distributed_collect_assert_or_die
