/// <summary> /// converts the temporary CSR format into the final matrix format /// </summary> abstract protected FormatBase AssembleFinalFormat(TempCSR tmp);
/// <summary> /// matrix assembly; must be called by each implementation, /// </summary> /// <param name="M"></param> protected void PackMatrix(IMutableMatrixEx M) { ilPSP.MPICollectiveWatchDog.Watch(); IPartitioning rp = M.RowPartitioning; IPartitioning cp = m_ColPart; // define Comm List // ================ SortedDictionary <int, List <int> > CommLists = new SortedDictionary <int, List <int> >(); // keys: processor rank p // values: List of global indices, which processor p needs to send to this processor int Lr; double[] val = null; int[] col = null; int L = rp.LocalLength; int i0 = (int)rp.i0; for (int iLoc = 0; iLoc < L; iLoc++) // loop over all matrix rows... { int iGlob = i0 + iLoc; //MsrMatrix.MatrixEntry[] row = (asMsr==null) ? M.GetRow(iGlob) : asMsr.GetRowShallow(iGlob); Lr = M.GetOccupiedColumnIndices(iGlob, ref col); for (int j = 0; j < Lr; j++) // loop over all nonzero entries in row 'iGlob' { int jGlob = col[j]; if (cp.i0 <= jGlob && jGlob < (cp.i0 + cp.LocalLength)) { // Entry on current processor } else { int proc = cp.FindProcess(jGlob); // Entry on Processor proc if (!CommLists.ContainsKey(proc)) { CommLists.Add(proc, new List <int>()); } List <int> CommList_proc = CommLists[proc]; if (!CommList_proc.Contains(jGlob)) // a lot of room for optimization { CommList_proc.Add(jGlob); } } } } // sort com list // ============= { foreach (List <int> cl in CommLists.Values) { cl.Sort(); } } // define matrix // ============= { TempCSR intTmp = new TempCSR(); SortedDictionary <int, ExternalTmp> extTmp = new SortedDictionary <int, ExternalTmp>(); foreach (int proc in CommLists.Keys) { extTmp.Add(proc, new ExternalTmp()); } for (int iLoc = 0; iLoc < L; iLoc++) { int iGlob = i0 + iLoc; Lr = M.GetRow(iGlob, ref col, ref val); for (int j = 0; j < Lr; j++) { int jGlob = col[j]; double Value = val[j]; bool bIsDiag = (iGlob == jGlob); if (cp.i0 <= jGlob && jGlob < (cp.i0 + cp.LocalLength)) { // Entry on current processor intTmp.AddEntry(jGlob - (int)cp.i0, Value, bIsDiag); } else { int proc = cp.FindProcess(jGlob); // Entry on Processor proc List <int> CommList_proc = CommLists[proc]; int jloc = CommList_proc.IndexOf(jGlob); ExternalTmp et = extTmp[proc]; et.AddEntry(jloc, jGlob, Value); } } intTmp.NextRow(); foreach (ExternalTmp et in extTmp.Values) { et.NextRow(); } } m_LocalMtx = AssembleFinalFormat(intTmp); ExtMatrix = new Dictionary <int, External>(); foreach (int proc in extTmp.Keys) { ExtMatrix.Add(proc, extTmp[proc].GetFinalObj()); } } // send/receive & transform Comm lists // ==================================== { SerialisationMessenger sms = new SerialisationMessenger(csMPI.Raw._COMM.WORLD); SortedDictionary <int, int[]> CommListsTo = new SortedDictionary <int, int[]>(); foreach (int proc in CommLists.Keys) { sms.SetCommPath(proc); } sms.CommitCommPaths(); foreach (int proc in CommLists.Keys) { sms.Transmitt(proc, CommLists[proc].ToArray()); } int _proc; int[] CommListReceived; sms.GetNext(out _proc, out CommListReceived); int Lcol = m_ColPart.LocalLength; int i0col = (int)m_ColPart.i0; while (CommListReceived != null) { // convert indices to local coordinates for (int i = 0; i < CommListReceived.Length; i++) { CommListReceived[i] -= i0col; // check: if (CommListReceived[i] < 0 || CommListReceived[i] >= Lcol) { throw new ApplicationException("internal error: something wrong with received Comm List."); } } CommListsTo.Add(_proc, CommListReceived); sms.GetNext(out _proc, out CommListReceived); } sms.Dispose(); m_SpmvCommPattern = new SpmvCommPattern(); m_SpmvCommPattern.ComLists = CommListsTo; } // record the number of elements which we receive // ============================================== { m_SpmvCommPattern.NoOfReceivedEntries = new Dictionary <int, int>(); foreach (int p in CommLists.Keys) { m_SpmvCommPattern.NoOfReceivedEntries.Add(p, CommLists[p].Count); } } }