public void ApplyToVector <I>(IList <I> input, IList <I[]> output, IPartitioning outputPartitioning) { using (new FuncTrace()) { Debug.Assert(DestGlobalId.Length == MappingIndex.Length); Debug.Assert(OldGlobalId.Length == MappingIndex.Length); int oldJ = DestGlobalId.Length; if (input.Count != oldJ) { throw new ArgumentException("Mismatch between input vector length and current data length."); } if (output.Count != outputPartitioning.LocalLength) { throw new ArgumentException("Length mismatch of output list and output partition."); } int j0Dest = outputPartitioning.i0; // keys: processors which should receive data from this processor Dictionary <int, ApplyToVector_Helper <I> > AllSendData = new Dictionary <int, ApplyToVector_Helper <I> >(); for (int j = 0; j < oldJ; j++) { I data_j = input[j]; foreach (int jDest in TargetIdx[j]) { if (outputPartitioning.IsInLocalRange(jDest)) { I[] destCollection = output[jDest - j0Dest]; ArrayTools.AddToArray(data_j, ref destCollection); output[jDest - j0Dest] = destCollection; } else { int targProc = outputPartitioning.FindProcess(jDest); ApplyToVector_Helper <I> dataTargPrc; if (!AllSendData.TryGetValue(targProc, out dataTargPrc)) { dataTargPrc = new ApplyToVector_Helper <I>(); AllSendData.Add(targProc, dataTargPrc); } dataTargPrc.TargetIndices.Add(jDest); dataTargPrc.Items.Add(data_j); } } } var AllRcvData = SerialisationMessenger.ExchangeData(AllSendData, outputPartitioning.MPI_Comm); foreach (var kv in AllRcvData) { int rcvProc = kv.Key; j0Dest = outputPartitioning.GetI0Offest(rcvProc); var TIdxs = kv.Value.TargetIndices; var TVals = kv.Value.Items; Debug.Assert(TIdxs.Count == TVals.Count); int L = TIdxs.Count; for (int l = 0; l < L; l++) { int idx = TIdxs[l] - j0Dest; Debug.Assert(outputPartitioning.IsInLocalRange(idx)); I[] destCollection = output[idx]; ArrayTools.AddToArray(TVals[idx], ref destCollection); output[idx] = destCollection; } } } }
/// <summary> /// Resorts a vector according to this permutation, i.e. the /// <em>j</em>-th item of the input vector is copied to the /// <see cref="Values"/>[j]-th entry of the output vector. /// </summary> /// <param name="input"> /// Input vector, length must be equal to the length of this permutation, unchanged on exit. /// </param> /// <param name="output"> /// On exit, <paramref name="output"/>[<see cref="Values"/>[j]] = <paramref name="input"/>[j] /// </param> public void ApplyToVector <I>(IList <I> input, IList <I> output, IPartitioning outputPartitioning) { using (new FuncTrace()) { if (input.Count != this.LocalLength) { throw new ArgumentException("wrong size of input vector."); } if (output.Count != outputPartitioning.LocalLength) { throw new ArgumentException("wrong size of output vector."); } long[] TargetInd = this.Values; // keys: processors which should receive data from this processor Dictionary <int, ApplyToVector_Helper <I> > sendData = new Dictionary <int, ApplyToVector_Helper <I> >(); int out_myI0 = outputPartitioning.i0; int out_nextI0 = out_myI0 + outputPartitioning.LocalLength; int J = this.Partitioning.LocalLength; for (int j = 0; j < J; j++) { if (out_myI0 <= TargetInd[j] && TargetInd[j] < out_nextI0) { // target index located on this processor output[(int)(TargetInd[j] - out_myI0)] = input[j]; } else { // target index located on other processor int TargProc = outputPartitioning.FindProcess(TargetInd[j]); ApplyToVector_Helper <I> sendData_TargProc = null; if (!sendData.TryGetValue(TargProc, out sendData_TargProc)) { sendData_TargProc = new ApplyToVector_Helper <I>(); sendData.Add(TargProc, sendData_TargProc); } sendData_TargProc.Items.Add(input[j]); sendData_TargProc.TargetIndices.Add(TargetInd[j]); } } var rcvData = SerialisationMessenger.ExchangeData( sendData, MPI.Wrappers.csMPI.Raw._COMM.WORLD); foreach (var rcvPkt in rcvData.Values) { int K = rcvPkt.Items.Count; Debug.Assert(rcvPkt.Items.Count == rcvPkt.TargetIndices.Count); for (int k = 0; k < K; k++) { int locIdx = (int)(rcvPkt.TargetIndices[k]) - out_myI0; output[locIdx] = rcvPkt.Items[k]; } } } }