Ejemplo n.º 1
0
 /// <summary>
 /// converts the temporary CSR format into the final matrix format
 /// </summary>
 abstract protected FormatBase AssembleFinalFormat(TempCSR tmp);
Ejemplo n.º 2
0
        /// <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);
                }
            }
        }