Beispiel #1
0
        private void AssembleMatrix(double dt, out BlockMsrMatrix SystemMatrix, out double[] SystemAffine)
        {
            // Init Matrix and Affine Part
            SystemMatrix = new BlockMsrMatrix(Mapping);
            SystemAffine = new double[Mapping.LocalLength];

            // choose TimeStepping-Scheme, based on what has been pushed to the stack,yet
            int Smax = TSCchain[0].S;

            Debug.Assert(Smax == TSCchain.Length);
            Tsc = TSCchain[Smax - PopulatedStackDepth];

            UpdateOperatorMatrix();



            //Implicit Part of RHS
            SystemMatrix.Acc(Tsc.theta1, Stack_OpMatrix[1]);
            SystemAffine.AccV(Tsc.theta1, Stack_OpAffine[1]);



            //Implicit Part of LHS
            SystemMatrix.AccEyeSp(1 / dt);

            // Explicit part of RHS
            Stack_OpMatrix[0].SpMV(-Tsc.theta0, CurrentState, 1.0, SystemAffine);
            SystemAffine.AccV(-Tsc.theta0, Stack_OpAffine[0]);

            //Explicit parts of LHS
            for (int i = 0; i < Tsc.beta.Length; i++)
            {
                SystemAffine.AccV(Tsc.beta[i] * 1 / dt, Stack_u[i]);
            }

            Debug.Assert(SystemMatrix.InfNorm() > 0);
            Debug.Assert(SystemAffine.L2Norm() > 0);

            if (subGrid != null)
            {
                int[] SubVecIdx = Mapping.GetSubvectorIndices(subGrid, true, new int[] { 0 });
                int   L         = SubVecIdx.Length;

                for (int i = 0; i < L; i++)
                {
                    SystemMatrix.ClearRow(SubVecIdx[i]);
                    SystemMatrix[SubVecIdx[i], SubVecIdx[i]] = 1;
                    SystemAffine[SubVecIdx[i]] = 0;
                }
            }
        }
Beispiel #2
0
        public static void SubSelection(
            [Values(SelectionType.all_combined, SelectionType.degrees, SelectionType.species, SelectionType.variables)] SelectionType SType
            )
        {
            Utils.TestInit((int)SType);
            Console.WriteLine("SubSelection({0})", SType);

            //Arrange --- extracts entries of matrix according to hardcoded selection
            int            DGdegree       = 2;
            int            GridResolution = 4;
            var            mgo            = Utils.CreateTestMGOperator(XDGusage.all, DGdegree, MatrixShape.full_var_spec, GridResolution);
            int            sampleCellA    = Utils.GetIdxOfFirstBlockWith(mgo.Mapping, false); //1 species
            int            sampleCellB    = Utils.GetIdxOfFirstBlockWith(mgo.Mapping, true);  //2 species
            BlockMsrMatrix compA          = Utils.GetCellCompMatrix(SType, mgo, sampleCellA);
            BlockMsrMatrix compB          = Utils.GetCellCompMatrix(SType, mgo, sampleCellB);

            //Arrange --- setup masking, which correspond to hardcoded
            SubBlockSelector sbsA = new SubBlockSelector(mgo.Mapping);

            sbsA.GetDefaultSelection(SType, sampleCellA); // single spec
            BlockMask        maskA = new BlockMask(sbsA, null);
            SubBlockSelector sbsB  = new SubBlockSelector(mgo.Mapping);

            sbsB.GetDefaultSelection(SType, sampleCellB); // double spec
            BlockMask maskB = new BlockMask(sbsB, null);

            //Arrange --- stop the watch
            Stopwatch stw = new Stopwatch();

            stw.Reset();

            //Act --- get subblocks
            stw.Start();
            BlockMsrMatrix subA = maskA.GetSubBlockMatrix(mgo.OperatorMatrix);
            BlockMsrMatrix subB = maskB.GetSubBlockMatrix(mgo.OperatorMatrix);

            stw.Stop();

            //Assert --- compare masking of single spec cell
            Debug.Assert(compA.InfNorm() != 0.0);
            subA.Acc(-1.0, compA);
            Assert.IsTrue(subA.InfNorm() == 0.0);

            //Assert --- compare masking of double spec cell
            Debug.Assert(compB.InfNorm() != 0.0);
            subB.Acc(-1.0, compB);
            Assert.IsTrue(subB.InfNorm() == 0.0);
        }
        /// <summary>
        /// Matrix/Affine assembly in the case of an implicit RK stage.
        /// </summary>
        protected override void AssembleMatrixCallback(out BlockMsrMatrix System, out double[] Affine, out BlockMsrMatrix PcMassMatrix, DGField[] argCurSt, bool Linearization)
        {
            if (Linearization == false)
            {
                throw new NotImplementedException("todo");
            }

            int Ndof = m_CurrentState.Count;

            // copy data from 'argCurSt' to 'CurrentStateMapping', if necessary
            // -----------------------------------------------------------
            DGField[] locCurSt = CurrentStateMapping.Fields.ToArray();
            if (locCurSt.Length != argCurSt.Length)
            {
                throw new ApplicationException();
            }
            int NF = locCurSt.Length;

            for (int iF = 0; iF < NF; iF++)
            {
                if (object.ReferenceEquals(locCurSt[iF], argCurSt[iF]))
                {
                    // nothing to do
                }
                else
                {
                    locCurSt[iF].Clear();
                    locCurSt[iF].Acc(1.0, argCurSt[iF]);
                }
            }

            // update of level-set
            // ----------------------

            bool updateAgglom = false;

            if (this.Config_LevelSetHandling == LevelSetHandling.Coupled_Once && m_ImplStParams.m_IterationCounter == 0 ||
                this.Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative)
            {
                //MoveLevelSetAndRelatedStuff(locCurSt, m_CurrentPhystime, m_CurrentDt, 1.0);
                if (Math.Abs(m_ImplStParams.m_ActualLevSetRelTime - m_ImplStParams.m_RelTime) > 1.0e-14)
                {
                    if (m_ImplStParams.m_IterationCounter <= 0)// only push tracker in the first iter
                    {
                        m_LsTrk.PushStacks();
                    }
                    MoveLevelSetAndRelatedStuff(locCurSt,
                                                m_ImplStParams.m_CurrentPhystime, m_ImplStParams.m_CurrentDt * m_ImplStParams.m_RelTime, IterUnderrelax,
                                                m_ImplStParams.m_Mass, m_ImplStParams.m_k);

                    // note that we need to update the agglomeration
                    updateAgglom = true;
                }
            }

            // update agglomeration
            // --------------------
#if DEBUG
            if (this.Config_LevelSetHandling == LevelSetHandling.LieSplitting || this.Config_LevelSetHandling == LevelSetHandling.StrangSplitting)
            {
                Debug.Assert(m_CurrentAgglomeration != null);
                Debug.Assert(m_PrecondMassMatrix != null);
                // ensure, that, when splitting is used we update the agglomerator in the very first iteration.
            }
#endif
            if (updateAgglom || m_CurrentAgglomeration == null)
            {
                this.UpdateAgglom(m_ImplStParams.m_IterationCounter > 0);



                // update Multigrid-XDG basis
                base.MultigridBasis.UpdateXdgAggregationBasis(m_CurrentAgglomeration);
            }


            // mass matrix update
            // ------------------

            if (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsIdentity)
            {
                // may occur e.g. if one runs the FSI solver as a pure single-phase solver,
                // i.e. if the Level-Set is outside the domain.

                PcMassMatrix = null;
            }
            else
            {
                // checks:
                Debug.Assert(this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsNonIdentity ||
                             this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeDependent ||
                             this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeAndSolutionDependent,
                             "Something is not implemented here.");
                if (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsNonIdentity &&
                    Config_LevelSetHandling != LevelSetHandling.None)
                {
                    throw new NotSupportedException("Illegal configuration;");
                }

                if (this.Config_LevelSetHandling == LevelSetHandling.Coupled_Once || this.Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative)
                {
                    if ((this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsNonIdentity && m_PrecondMassMatrix == null) || // compute mass matrix (only once in application lifetime)
                        (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeDependent && m_ImplStParams.m_IterationCounter == 0) || // compute mass matrix once per timestep
                        (this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsTimeAndSolutionDependent) // re-compute mass matrix in every iteration
                        )
                    {
                        BlockMsrMatrix PM, SM;
                        UpdateMassMatrix(out PM, out SM, m_ImplStParams.m_CurrentPhystime + m_ImplStParams.m_CurrentDt * m_ImplStParams.m_RelTime);
                        m_ImplStParams.m_Mass[1] = SM;
                        m_PrecondMassMatrix      = PM;
                    }
                }

                PcMassMatrix = m_PrecondMassMatrix;
            }

            // operator matrix update
            // ----------------------

            // we perform the extrapolation to have valid parameters if
            // - the operator matrix depends on these values
            this.m_CurrentAgglomeration.Extrapolate(CurrentStateMapping);

            var OpMatrix = new BlockMsrMatrix(CurrentStateMapping);
            var OpAffine = new double[Ndof];

            this.ComputeOperatorMatrix(OpMatrix, OpAffine, CurrentStateMapping, locCurSt, base.GetAgglomeratedLengthScales(), m_ImplStParams.m_CurrentPhystime + m_ImplStParams.m_CurrentDt * m_ImplStParams.m_RelTime);


            // assemble system
            // ---------------

            double dt = m_ImplStParams.m_CurrentDt;

            // select mass matrix (and some checks)
            double[]       RHS = new double[Ndof];
            BlockMsrMatrix MamaRHS, MamaLHS;
            if (this.Config_LevelSetHandling == LevelSetHandling.Coupled_Once ||
                this.Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative)
            {
                Debug.Assert(m_ImplStParams.m_Mass.Length == 2);
                MamaRHS = m_ImplStParams.m_Mass[0];
                MamaLHS = m_ImplStParams.m_Mass[1];
            }
            else if (this.Config_LevelSetHandling == LevelSetHandling.LieSplitting ||
                     this.Config_LevelSetHandling == LevelSetHandling.StrangSplitting ||
                     this.Config_LevelSetHandling == LevelSetHandling.None)
            {
                Debug.Assert(m_ImplStParams.m_Mass.Length == 1);
                MamaRHS = m_ImplStParams.m_Mass[0];
                MamaLHS = m_ImplStParams.m_Mass[0];
            }
            else
            {
                throw new NotImplementedException();
            }

            // right-hand-side, resp. affine vector
            if (MamaRHS != null)
            {
                MamaRHS.SpMV(1.0 / dt, m_ImplStParams.m_u0, 0.0, RHS);
            }
            else
            {
                Debug.Assert(this.Config_MassMatrixShapeandDependence == MassMatrixShapeandDependence.IsIdentity);
                RHS.SetV(m_ImplStParams.m_u0, 1.0 / dt);
            }
            for (int l = 0; l < m_ImplStParams.m_s; l++)
            {
                if (m_ImplStParams.m_RK_as[l] != 0.0)
                {
                    RHS.AccV(-m_ImplStParams.m_RK_as[l], m_ImplStParams.m_k[l]);
                }
            }

            Affine = RHS;
            Affine.ScaleV(-1.0);
            Affine.AccV(m_ImplStParams.m_RK_as[m_ImplStParams.m_s], OpAffine);

            // left-hand-side
            System = OpMatrix.CloneAs();
            System.Scale(m_ImplStParams.m_RK_as[m_ImplStParams.m_s]);
            if (MamaLHS != null)
            {
                System.Acc(1.0 / dt, MamaLHS);
            }
            else
            {
                System.AccEyeSp(1.0 / dt);
            }

            // perform agglomeration
            // ---------------------
            Debug.Assert(object.ReferenceEquals(m_CurrentAgglomeration.Tracker, m_LsTrk));
            m_CurrentAgglomeration.ManipulateMatrixAndRHS(System, Affine, CurrentStateMapping, CurrentStateMapping);

            // increase iteration counter
            // --------------------------
            m_ImplStParams.m_IterationCounter++;
        }
Beispiel #4
0
        public void Init(MultigridOperator op)
        {
            using (new FuncTrace()) {
                if (m_MgOp != null)
                {
                    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                    // someone is trying to re-use this solver: see if the settings permit that
                    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                    if (op.LevelIndex != m_MgOp.LevelIndex)
                    {
                        throw new ArgumentException("Re-use on different level not possible.");
                    }
                    if (!this.MtxFull._RowPartitioning.EqualsPartition(op.OperatorMatrix._RowPartitioning))
                    {
                        throw new ArgumentException("Matrix has changed, unable to re-use");
                    }
                    if (!this.MtxFull._ColPartitioning.EqualsPartition(op.OperatorMatrix._ColPartitioning))
                    {
                        throw new ArgumentException("Matrix has changed, unable to re-use");
                    }
#if DEBUG
                    if (!object.ReferenceEquals(this.MtxFull, op.OperatorMatrix))
                    {
                        BlockMsrMatrix Check = this.MtxFull.CloneAs();
                        Check.Acc(-1.0, op.OperatorMatrix);
                        if (Check.InfNorm() != 0.0)
                        {
                            throw new ArgumentException("Matrix has changed, unable to re-use");
                        }
                    }
#endif
                    if (this.m_BlockingStrategy.GetNoOfBlocks(op) != this.blockSolvers.Count())
                    {
                        throw new ArgumentException("Blocking, unable to re-use");
                    }


                    return;
                }

                var Mop   = op.OperatorMatrix;
                var MgMap = op.Mapping;
                this.m_MgOp = op;
                int myMpiRank = MgMap.MpiRank;
                int myMpisize = MgMap.MpiSize;

                if (!Mop.RowPartitioning.EqualsPartition(MgMap.Partitioning))
                {
                    throw new ArgumentException("Row partitioning mismatch.");
                }
                if (!Mop.ColPartition.EqualsPartition(MgMap.Partitioning))
                {
                    throw new ArgumentException("Column partitioning mismatch.");
                }

                var ag = MgMap.AggGrid;

                int JComp  = ag.iLogicalCells.NoOfLocalUpdatedCells;
                int JGhost = ag.iLogicalCells.NoOfExternalCells;

#if DEBUG
                ilPSP.Connectors.Matlab.BatchmodeConnector matlab;
                if (m_MatlabParalellizationCheck)
                {
                    matlab = new ilPSP.Connectors.Matlab.BatchmodeConnector();
                }
                else
                {
                    matlab = null;
                }
#endif

                //Mop.Clear();
                //for(int i = Mop.RowPartitioning.i0; i < Mop.RowPartitioning.iE; i++) {
                //    Mop[i, i] = i + 1;
                //}


                // get cell blocks
                // ===============

                var _Blocks         = this.m_BlockingStrategy.GetBlocking(op);
                int NoOfSchwzBlocks = _Blocks.Count();

                // test cell blocks
                // ================
#if DEBUG
                {
                    // ensure that each cell is used exactly once, among all blocks
                    bool[] test = new bool[ag.iLogicalCells.NoOfLocalUpdatedCells];
                    foreach (var bi in _Blocks)
                    {
                        foreach (int j in bi)
                        {
                            Debug.Assert(test[j] == false);
                            test[j] = true;
                        }
                        ;
                    }
                    for (int i = 0; i < test.Length; i++)
                    {
                        Debug.Assert(test[i] == true);
                    }
                }
#endif

                // extend blocks according to desired overlap
                // ==========================================
                {
                    BitArray marker = new BitArray(JComp + JGhost);

                    if (Overlap < 0)
                    {
                        throw new ArgumentException();
                    }
                    if (Overlap > 0)
                    {
                        if (Overlap > 1 && Mop.RowPartitioning.MpiSize > 1)
                        {
                            throw new NotSupportedException("In MPI parallel runs, the maximum supported overlap for the Schwarz preconditioner is 1.");
                        }

                        foreach (List <int> bi in _Blocks) // loop over blocks...
                        {
                            marker.SetAll(false);          // marks all cells which are members of the block
                            foreach (int jcomp in bi)
                            {
                                marker[jcomp] = true;
                            }

                            // determine overlap regions
                            for (int k = 0; k < Overlap; k++)
                            {
                                int Jblock = bi.Count;
                                for (int j = 0; j < Jblock; j++)
                                {
                                    int   jCell  = bi[j];
                                    int[] Neighs = ag.iLogicalCells.CellNeighbours[jCell];
                                    foreach (int jNeigh in Neighs)
                                    {
                                        if (marker[jNeigh] == false)
                                        {
                                            // neighbor cell is not already a member of the block
                                            // => add it.
                                            bi.Add(jNeigh);
                                            marker[jNeigh] = true;
                                        }
                                    }
                                }
                            }

                            bi.Sort();
                        }
                    }

                    BlockCells = _Blocks.Select(list => list.ToArray()).ToArray();
                }


                // convert cell blocks to DOF blocks
                // =================================

                List <int>[] BlkIdx_gI_lR;                  //  for each Schwarz block, (global) indices in the local range
                List <int>[] BlkIdx_gI_eR;                  //  for each Schwarz block, (global) indices of external rows and columns
                List <int>[] TempRowIdx_gI;                 // for each Schwarz block, (global) indices into the temporary matrix
                List <int>[] BlkIdx_lI_eR;                  //  for each Schwarz block, (local)  indices of external rows and columns
                List <int>[] LocalBlocks_i0, LocalBlocks_N; // blocking of the Schwarz-Blocks.

                // for matrix 'ExternalRowsTemp': which rows of 'Mop' are required locally
                List <int> ExternalRowsIndices, ExternalRows_BlockI0, ExternalRows_BlockN;
                {
                    int Jup = MgMap.AggGrid.iLogicalCells.NoOfLocalUpdatedCells;
                    int Jgh = MgMap.AggGrid.iLogicalCells.NoOfExternalCells;

                    int LocalizedBlockCounter = 0;

                    BlkIdx_gI_lR   = NoOfSchwzBlocks.ForLoop(iPart => new List <int>(BlockCells[iPart].Length * MgMap.MaximalLength));
                    BlkIdx_gI_eR   = NoOfSchwzBlocks.ForLoop(iPart => new List <int>());
                    LocalBlocks_i0 = NoOfSchwzBlocks.ForLoop(iPart => new List <int>());
                    LocalBlocks_N  = NoOfSchwzBlocks.ForLoop(iPart => new List <int>());

                    TempRowIdx_gI = NoOfSchwzBlocks.ForLoop(iPart => new List <int>());
                    BlkIdx_lI_eR  = NoOfSchwzBlocks.ForLoop(iPart => new List <int>());


                    ExternalRowsIndices  = new List <int>();
                    ExternalRows_BlockI0 = new List <int>();
                    ExternalRows_BlockN  = new List <int>();

                    for (int iPart = 0; iPart < NoOfSchwzBlocks; iPart++)   // loop over parts...
                    {
                        int[] bc    = BlockCells[iPart];
                        var   biI   = BlkIdx_gI_lR[iPart];
                        var   biE   = BlkIdx_gI_eR[iPart];
                        var   l1    = TempRowIdx_gI[iPart];
                        var   l2    = BlkIdx_lI_eR[iPart];
                        var   LBBi0 = LocalBlocks_i0[iPart];
                        var   LBBN  = LocalBlocks_N[iPart];


                        int Jblock         = bc.Length;
                        int anotherCounter = 0;

                        for (int jblk = 0; jblk < Jblock; jblk++)   // loop over cells in blocks...
                        {
                            int j = bc[jblk];
                            int N = MgMap.GetLength(j);

                            if (j < Jup)
                            {
                                // locally updated cell
                                int i0 = MgMap.GlobalUniqueIndex(0, j, 0);

                                for (int n = 0; n < N; n++)
                                {
                                    biI.Add(i0 + n);
                                }
                            }
                            else
                            {
                                // external cell
                                int i0E = MgMap.GlobalUniqueIndex(0, j, 0); //
                                int i0L = MgMap.LocalUniqueIndex(0, j, 0);  //
                                ExternalRows_BlockI0.Add(LocalizedBlockCounter);
                                ExternalRows_BlockN.Add(N);
                                //LEBi0.Add(LocalizedBlockCounter);
                                //LEBn.Add(N);
                                for (int n = 0; n < N; n++)
                                {
                                    biE.Add(i0E + n);
                                    ExternalRowsIndices.Add(i0E + n);
                                    l1.Add(LocalizedBlockCounter + n);
                                    l2.Add(i0L + n);
                                    Debug.Assert(Mop._RowPartitioning.FindProcess(i0E + n) != myMpiRank);
                                }

                                LocalizedBlockCounter += N;
                            }

                            LBBi0.Add(anotherCounter);
                            LBBN.Add(N);

                            anotherCounter += N;
                        }
                    }

                    //this.BlockIndices = _LocallyStoredBlockIndices.Select(bi => bi.ToArray()).ToArray();
                }


                // get rows for blocks that use external cells
                // ===========================================

#if DEBUG
                {
                    if (Overlap == 0)
                    {
                        Debug.Assert(ExternalRowsIndices.Count == 0);
                        Debug.Assert(ExternalRows_BlockI0.Count == 0);
                        Debug.Assert(ExternalRows_BlockN.Count == 0);
                    }

                    foreach (var bi in BlkIdx_gI_lR)
                    {
                        foreach (int idx in bi)
                        {
                            Debug.Assert(idx >= m_MgOp.Mapping.i0);
                            Debug.Assert(idx < m_MgOp.Mapping.iE);
                        }
                    }

                    foreach (var ei in BlkIdx_gI_eR)
                    {
                        foreach (int idx in ei)
                        {
                            Debug.Assert(idx < m_MgOp.Mapping.i0 || idx >= m_MgOp.Mapping.iE);
                        }
                    }


                    int LL   = m_MgOp.Mapping.LocalLength;
                    int jMax = m_MgOp.Mapping.AggGrid.iLogicalCells.NoOfCells - 1;
                    int LE   = m_MgOp.Mapping.LocalUniqueIndex(0, jMax, 0) + m_MgOp.Mapping.GetLength(jMax);


                    foreach (var ci in BlkIdx_lI_eR)
                    {
                        foreach (int idx in ci)
                        {
                            Debug.Assert(idx >= LL);
                            Debug.Assert(idx < LE);
                        }
                    }

                    if (m_MatlabParalellizationCheck)
                    {
                        int globalBlockCounter = 0;
                        for (int rankCounter = 0; rankCounter < myMpisize; rankCounter++)
                        {
                            int rank_NoBlks = NoOfSchwzBlocks.MPIBroadcast(rankCounter);
                            if (rankCounter == myMpiRank)
                            {
                                Debug.Assert(rank_NoBlks == NoOfSchwzBlocks);
                            }

                            for (int iBlock = 0; iBlock < rank_NoBlks; iBlock++)
                            {
                                double[] vec;
                                if (rankCounter == myMpiRank)
                                {
                                    vec = ArrayTools.Cat(BlkIdx_gI_lR[iBlock], BlkIdx_gI_eR[iBlock]).Select(ii => ((double)(ii + 1))).ToArray();
                                }
                                else
                                {
                                    vec = new double[0];
                                }

                                matlab.PutVector(vec, string.Format("BlockIdx{0}", globalBlockCounter));

                                globalBlockCounter++;
                                csMPI.Raw.Barrier(csMPI.Raw._COMM.WORLD);
                            }
                        }
                    }
                }
#endif


                BlockMsrMatrix ExternalRowsTemp;
                if (myMpisize > 1 && Overlap > 0)
                {
                    //int NoOfLocalRows = _ExternalBlockIndices.Sum(L => L.Count);

                    BlockPartitioning PermRow = new BlockPartitioning(ExternalRowsIndices.Count, ExternalRows_BlockI0, ExternalRows_BlockN, Mop.MPI_Comm, i0isLocal: true);

                    // Remark: we use a permutation matrix for MPI-exchange of rows

                    BlockMsrMatrix Perm = new BlockMsrMatrix(PermRow, Mop._RowPartitioning);
                    for (int iRow = 0; iRow < ExternalRowsIndices.Count; iRow++)
                    {
                        Debug.Assert(Mop._RowPartitioning.IsInLocalRange(ExternalRowsIndices[iRow]) == false);
                        Perm[iRow + PermRow.i0, ExternalRowsIndices[iRow]] = 1;
                    }

                    ExternalRowsTemp = BlockMsrMatrix.Multiply(Perm, Mop);

#if DEBUG
                    if (m_MatlabParalellizationCheck)
                    {
                        matlab.PutSparseMatrix(Perm, "Perm");
                        matlab.PutSparseMatrix(ExternalRowsTemp, "ExternalRowsTemp");
                    }
#endif
                }
                else
                {
                    ExternalRowsTemp = null;
                }

                ExternalRowsIndices  = null;
                ExternalRows_BlockI0 = null;
                ExternalRows_BlockN  = null;



                // create solvers
                // ==============


                {
                    blockSolvers = new ISparseSolver[NoOfSchwzBlocks];

#if DEBUG
                    List <BlockMsrMatrix> Blocks = new List <BlockMsrMatrix>();
#endif
                    for (int iPart = 0; iPart < NoOfSchwzBlocks; iPart++)
                    {
                        var bi = BlkIdx_gI_lR[iPart];

                        int Bsz;
                        if (MgMap.MinimalLength == MgMap.MaximalLength)
                        {
                            Bsz = MgMap.MaximalLength;
                        }
                        else
                        {
                            Bsz = 1;
                        }

                        var l1 = TempRowIdx_gI[iPart];

                        //if (M.RowPartitioning.MpiSize > 1) {
                        //    int i0Proc = M.RowPartitioning.i0;
                        //    bi = bi.CloneAs();
                        //    for (int i = 0; i < bi.Length; i++) {
                        //        bi[i] += i0Proc;
                        //    }
                        //}

                        BlockPartitioning localBlocking = new BlockPartitioning(bi.Count + l1.Count, LocalBlocks_i0[iPart], LocalBlocks_N[iPart], csMPI.Raw._COMM.SELF);

                        if (l1.Count > 0)
                        {
                            // convert the indices into 'ExternalRowsTemp' to global indices
                            int l1L    = l1.Count;
                            int offset = ExternalRowsTemp._RowPartitioning.i0;
                            for (int i = 0; i < l1L; i++)
                            {
                                l1[i] += offset;
                            }
                        }

                        BlockMsrMatrix Block = new BlockMsrMatrix(localBlocking, localBlocking);// bi.Length, bi.Length, Bsz, Bsz);
                        Mop.WriteSubMatrixTo(Block, bi, default(int[]), bi, default(int[]));
                        if (l1.Count > 0)
                        {
                            int   offset   = bi.Count;
                            int[] targRows = l1.Count.ForLoop(i => i + offset);

                            var   biE         = BlkIdx_gI_eR[iPart];
                            int[] extTargCols = biE.Count.ForLoop(i => i + offset);

                            Mop.AccSubMatrixTo(1.0, Block, bi, default(int[]), new int[0], default(int[]), biE, extTargCols);
                            ExternalRowsTemp.AccSubMatrixTo(1.0, Block, l1, targRows, bi, default(int[]), biE, extTargCols);
                        }
#if DEBUG
                        if (m_MatlabParalellizationCheck)
                        {
                            Blocks.Add(Block);
                        }
#endif
                        blockSolvers[iPart] = new PARDISOSolver()
                        {
                            CacheFactorization = true,
                            UseDoublePrecision = false
                        };
                        //blockSolvers[iPart] = new FullDirectSolver();
                        //blockSolvers[iPart] = new ilPSP.LinSolvers.MUMPS.MUMPSSolver();
                        blockSolvers[iPart].DefineMatrix(Block);
                    }

#if DEBUG
                    if (m_MatlabParalellizationCheck)
                    {
                        int globalBlockCounter = 0;
                        for (int rankCounter = 0; rankCounter < myMpisize; rankCounter++)
                        {
                            int rank_NoBlks = NoOfSchwzBlocks.MPIBroadcast(rankCounter);
                            for (int iBlock = 0; iBlock < rank_NoBlks; iBlock++)
                            {
                                BlockMsrMatrix Block;
                                if (rankCounter == myMpiRank)
                                {
                                    Block = Blocks[iBlock];
                                }
                                else
                                {
                                    Block = null;
                                }

                                matlab.PutSparseMatrix(Block, string.Format("Block{0}", globalBlockCounter));

                                globalBlockCounter++;
                                csMPI.Raw.Barrier(csMPI.Raw._COMM.WORLD);
                            }
                        }
                    }
#endif
                }

                // Record required indices
                // =======================
                {
                    this.BlockIndices_Local    = new int[NoOfSchwzBlocks][];
                    this.BlockIndices_External = new int[NoOfSchwzBlocks][];
                    int LocalI0     = MgMap.i0;
                    int LocalLength = MgMap.LocalLength;

                    for (int iBlock = 0; iBlock < NoOfSchwzBlocks; iBlock++)
                    {
                        var   _bi = BlkIdx_gI_lR[iBlock];
                        int   L   = _bi.Count;
                        int[] bil = new int[L];
                        this.BlockIndices_Local[iBlock] = bil;

                        for (int l = 0; l < L; l++)
                        {
                            bil[l] = _bi[l] - LocalI0;
                            Debug.Assert(bil[l] >= 0);
                            Debug.Assert(bil[l] < MgMap.LocalLength);
                        }

                        var _biE = BlkIdx_lI_eR[iBlock];
                        if (_biE.Count > 0)
                        {
                            this.BlockIndices_External[iBlock] = _biE.ToArray();
                        }
                    }
                }


                this.MtxFull = Mop;

                if (CoarseSolver != null)
                {
                    CoarseSolver.Init(op.CoarserLevel);
                }

                // Debug & Test-Code
                // =================
#if DEBUG
                if (m_MatlabParalellizationCheck)
                {
                    Console.WriteLine("Matlab dir: " + matlab.WorkingDirectory);

                    matlab.PutSparseMatrix(Mop, "Full");
                    int GlobalNoOfBlocks = NoOfSchwzBlocks.MPISum();



                    for (int iGlbBlock = 0; iGlbBlock < GlobalNoOfBlocks; iGlbBlock++)
                    {
                        matlab.Cmd("BlockErr({0} + 1, 1) = norm( Block{0} - Full( BlockIdx{0}, BlockIdx{0} ), inf );", iGlbBlock);
                    }

                    Random   rnd     = new Random(myMpiRank);
                    double[] testRHS = new double[MgMap.LocalLength];
                    for (int i = 0; i < testRHS.Length; i++)
                    {
                        testRHS[i] = rnd.NextDouble();
                    }
                    matlab.PutVector(testRHS, "testRHS");

                    MPIexchange <double[]> ResExchange = new MPIexchange <double[]>(MgMap, testRHS);
                    ResExchange.TransceiveStartImReturn();
                    ResExchange.TransceiveFinish(0.0);

                    int offset = MgMap.LocalLength;

                    int g = 0;
                    for (int rankCounter = 0; rankCounter < myMpisize; rankCounter++)
                    {
                        int rank_NoBlks = NoOfSchwzBlocks.MPIBroadcast(rankCounter);
                        for (int iBlock = 0; iBlock < rank_NoBlks; iBlock++)
                        {
                            double[] SubVec;
                            if (rankCounter == myMpiRank)
                            {
                                int LL = this.BlockIndices_Local[iBlock].Length;
                                int LE;
                                if (this.BlockIndices_External[iBlock] != null)
                                {
                                    LE = this.BlockIndices_External[iBlock].Length;
                                }
                                else
                                {
                                    LE = 0;
                                }
                                int L = LL + LE;

                                SubVec = new double[L];
                                for (int i = 0; i < LL; i++)
                                {
                                    SubVec[i] = testRHS[this.BlockIndices_Local[iBlock][i]];
                                }
                                if (LE > 0)
                                {
                                    for (int i = 0; i < LE; i++)
                                    {
                                        SubVec[i + LL] = ResExchange.Vector_Ext[this.BlockIndices_External[iBlock][i] - offset];
                                    }
                                }
                            }
                            else
                            {
                                SubVec = new double[0];
                            }

                            matlab.PutVector(SubVec, "SubVec" + g);

                            g++;
                        }
                    }

                    for (int iGlbBlock = 0; iGlbBlock < GlobalNoOfBlocks; iGlbBlock++)
                    {
                        matlab.Cmd("RhsErr({0} + 1, 1) = norm( SubVec{0} - testRHS( BlockIdx{0} ), inf );", iGlbBlock);
                    }

                    double[] testX = new double[testRHS.Length];
                    MPIexchangeInverse <double[]> XExchange = new MPIexchangeInverse <double[]>(MgMap, testX);

                    g = 0;
                    for (int rankCounter = 0; rankCounter < myMpisize; rankCounter++)
                    {
                        int rank_NoBlks = NoOfSchwzBlocks.MPIBroadcast(rankCounter);
                        for (int iBlock = 0; iBlock < rank_NoBlks; iBlock++)
                        {
                            if (rankCounter == myMpiRank)
                            {
                                int LL = this.BlockIndices_Local[iBlock].Length;
                                int LE;
                                if (this.BlockIndices_External[iBlock] != null)
                                {
                                    LE = this.BlockIndices_External[iBlock].Length;
                                }
                                else
                                {
                                    LE = 0;
                                }
                                int L = LL + LE;


                                for (int i = 0; i < LL; i++)
                                {
                                    testX[this.BlockIndices_Local[iBlock][i]] += (g + 1);
                                }
                                if (LE > 0)
                                {
                                    for (int i = 0; i < LE; i++)
                                    {
                                        XExchange.Vector_Ext[this.BlockIndices_External[iBlock][i] - offset] += (g + 1);
                                    }
                                }
                            }
                            else
                            {
                                //nop
                            }

                            g++;
                        }
                    }
                    XExchange.TransceiveStartImReturn();
                    XExchange.TransceiveFinish(1.0);

                    matlab.Cmd("testXref = zeros({0},1);", MgMap.TotalLength);
                    for (int iGlbBlock = 0; iGlbBlock < GlobalNoOfBlocks; iGlbBlock++)
                    {
                        matlab.Cmd("testXref(BlockIdx{0},1) = testXref(BlockIdx{0},1) + ({0} + 1);", iGlbBlock);
                    }

                    matlab.PutVector(testX, "testX");
                    matlab.Cmd("testXErr = norm(testX - testXref, inf);");

                    MultidimensionalArray BlockErr = MultidimensionalArray.Create(GlobalNoOfBlocks, 1);
                    MultidimensionalArray RhsErr   = MultidimensionalArray.Create(GlobalNoOfBlocks, 1);
                    MultidimensionalArray testXErr = MultidimensionalArray.Create(1, 1);

                    matlab.GetMatrix(BlockErr, "BlockErr");
                    matlab.GetMatrix(RhsErr, "RhsErr");
                    matlab.GetMatrix(testXErr, "testXErr");

                    matlab.Execute();

                    for (int iGlbBlock = 0; iGlbBlock < GlobalNoOfBlocks; iGlbBlock++)
                    {
                        Console.WriteLine("Block #{0} Error (external? ) " + BlockErr[iGlbBlock, 0], iGlbBlock);
                        Console.WriteLine("RHS #{0} Error " + RhsErr[iGlbBlock, 0], iGlbBlock);
                        Debug.Assert(BlockErr[iGlbBlock, 0] == 0);
                        Debug.Assert(RhsErr[iGlbBlock, 0] == 0);
                    }

                    Console.WriteLine("X Error " + testXErr[0, 0]);
                    Debug.Assert(testXErr[0, 0] == 0.0);

                    matlab.Dispose();
                }
#endif
            }
        }
Beispiel #5
0
        public static void SubMatrixTest(
            [Values(XDGusage.none, XDGusage.mixed1, XDGusage.mixed2, XDGusage.all)] XDGusage UseXdg,
            [Values(1, 3)] int DGOrder,
            [Values(false, true)] bool compressL1,
            [Values(false, true)] bool compressL2)
        {
            unsafe
            {
                int[] Params = new int[8], ParamsGlob = new int[8];
                fixed(int *pParams = Params, pParamsGlob = ParamsGlob)
                {
                    pParams[0] = (int)UseXdg;
                    pParams[1] = DGOrder;
                    pParams[2] = compressL1 ? 1 : 0;
                    pParams[3] = compressL2 ? 1 : 0;
                    pParams[4] = -pParams[0];
                    pParams[5] = -pParams[1];
                    pParams[6] = -pParams[2];
                    pParams[7] = -pParams[3];

                    csMPI.Raw.Allreduce((IntPtr)pParams, (IntPtr)pParamsGlob, 8, csMPI.Raw._DATATYPE.INT, csMPI.Raw._OP.MIN, csMPI.Raw._COMM.WORLD);
                }

                int[] ParamsMin = ParamsGlob.GetSubVector(0, 4);
                int[] ParamsMax = ParamsGlob.GetSubVector(4, 4);
                for (int i = 0; i < 4; i++)
                {
                    if (Params[i] != ParamsMin[i])
                    {
                        throw new ApplicationException();
                    }
                    if (Params[i] != -ParamsMax[i])
                    {
                        throw new ApplicationException();
                    }
                }

                Console.WriteLine("SubMatrixTest({0},{1},{2},{3})", UseXdg, DGOrder, compressL1, compressL2);
            }

            using (var solver = new Matrix_MPItestMain()
            {
                m_UseXdg = UseXdg, m_DGorder = DGOrder
            }) {
                // create the test data
                // ====================

                BoSSS.Solution.Application.CommandLineOptions opts = null;
                //opts = new BoSSS.Solution.Application.CommandLineOptions();
                solver.Init(null, opts);
                solver.RunSolverMode();

                Stopwatch stw = new Stopwatch();
                stw.Reset();
                stw.Start();

                BlockMsrMatrix M = solver.OperatorMatrix;

                int[] Ilist1 = solver.ProblemMapping.GetSubvectorIndices(false, 0);
                int[] Ilist2 = solver.ProblemMapping.GetSubvectorIndices(false, 1);

                foreach (int i in Ilist1)
                {
                    Assert.IsTrue(solver.ProblemMapping.IsInLocalRange(i));
                }
                foreach (int i in Ilist2)
                {
                    Assert.IsTrue(solver.ProblemMapping.IsInLocalRange(i));
                }

                var Blk1 = solver.ProblemMapping.GetSubBlocking(Ilist1, csMPI.Raw._COMM.WORLD, compressL1 ? -1 : 0);
                var Blk2 = solver.ProblemMapping.GetSubBlocking(Ilist2, csMPI.Raw._COMM.WORLD, compressL2 ? -1 : 0);



                int[] Tlist1 = compressL1 ? default(int[]) : Blk1.GetOccupiedIndicesList();
                int[] Tlist2 = compressL2 ? default(int[]) : Blk2.GetOccupiedIndicesList();
                if (Tlist1 != null)
                {
                    Assert.AreEqual(Tlist1.Length, Ilist1.Length);
                    foreach (int i in Tlist1)
                    {
                        Assert.IsTrue(Blk1.IsInLocalRange(i));
                    }
                }
                if (Tlist2 != null)
                {
                    Assert.AreEqual(Tlist2.Length, Ilist2.Length);
                    foreach (int i in Tlist2)
                    {
                        Assert.IsTrue(Blk2.IsInLocalRange(i));
                    }
                }
                BlockMsrMatrix M11 = new BlockMsrMatrix(Blk1, Blk1);
                BlockMsrMatrix M12 = new BlockMsrMatrix(Blk1, Blk2);
                BlockMsrMatrix M21 = new BlockMsrMatrix(Blk2, Blk1);
                BlockMsrMatrix M22 = new BlockMsrMatrix(Blk2, Blk2);

                M.AccSubMatrixTo(1.0, M11, Ilist1, Tlist1, Ilist1, Tlist1);
                M.AccSubMatrixTo(1.0, M12, Ilist1, Tlist1, Ilist2, Tlist2);
                M.AccSubMatrixTo(1.0, M21, Ilist2, Tlist2, Ilist1, Tlist1);
                M.AccSubMatrixTo(1.0, M22, Ilist2, Tlist2, Ilist2, Tlist2);

                BlockMsrMatrix restored_M = new BlockMsrMatrix(M._RowPartitioning, M._ColPartitioning);
                int[]          Idx1       = compressL1 ? Blk1.LocalLength.ForLoop(i => i + Blk1.i0) : Tlist1;
                int[]          Idx2       = compressL2 ? Blk2.LocalLength.ForLoop(i => i + Blk2.i0) : Tlist2;
                M11.AccSubMatrixTo(1.0, restored_M, Idx1, Ilist1, Idx1, Ilist1);
                M12.AccSubMatrixTo(1.0, restored_M, Idx1, Ilist1, Idx2, Ilist2);
                M21.AccSubMatrixTo(1.0, restored_M, Idx2, Ilist2, Idx1, Ilist1);
                M22.AccSubMatrixTo(1.0, restored_M, Idx2, Ilist2, Idx2, Ilist2);

                // test transpose-operator
                var M_TT   = M.Transpose().Transpose();
                var M11_TT = M11.Transpose().Transpose();
                var M12_TT = M12.Transpose().Transpose();
                var M21_TT = M21.Transpose().Transpose();
                var M22_TT = M22.Transpose().Transpose();
                M_TT.Acc(-1.0, M);
                M11_TT.Acc(-1.0, M11);
                M12_TT.Acc(-1.0, M12);
                M21_TT.Acc(-1.0, M21);
                M22_TT.Acc(-1.0, M22);
                double M_TT_norm   = M_TT.InfNorm();
                double M11_TT_norm = M11_TT.InfNorm();
                double M12_TT_norm = M12_TT.InfNorm();
                double M21_TT_norm = M21_TT.InfNorm();
                double M22_TT_norm = M22_TT.InfNorm();
                Assert.IsTrue(M_TT_norm == 0.0, "Transpose^2 is not identity.");
                Assert.IsTrue(M11_TT_norm == 0.0, "Transpose^2 is not identity.");
                Assert.IsTrue(M12_TT_norm == 0.0, "Transpose^2 is not identity.");
                Assert.IsTrue(M21_TT_norm == 0.0, "Transpose^2 is not identity.");
                Assert.IsTrue(M22_TT_norm == 0.0, "Transpose^2 is not identity.");

                //M.SaveToTextFileSparse(@"C:\tmp\M.txt");
                //M11.SaveToTextFileSparse(@"C:\tmp\M11.txt");
                //M12.SaveToTextFileSparse(@"C:\tmp\M12.txt");
                //M21.SaveToTextFileSparse(@"C:\tmp\M21.txt");
                //M22.SaveToTextFileSparse(@"C:\tmp\M22.txt");
                //restored_M.SaveToTextFileSparse(@"C:\tmp\Mr.txt");

                stw.Stop();

                using (var MatlabRef = new BatchmodeConnector()) {
                    MatlabRef.PutVector(Ilist1.Select(i => (double)i + 1.0).ToArray(), "Ilist1");
                    MatlabRef.PutVector(Ilist2.Select(i => (double)i + 1.0).ToArray(), "Ilist2");
                    MatlabRef.PutVector(Tlist1 == null ? Ilist1.Length.ForLoop(i => (double)i + 1.0 + Blk1.i0) : Tlist1.Select(i => (double)i + 1.0).ToArray(), "Tlist1");
                    MatlabRef.PutVector(Tlist2 == null ? Ilist2.Length.ForLoop(i => (double)i + 1.0 + Blk2.i0) : Tlist2.Select(i => (double)i + 1.0).ToArray(), "Tlist2");

                    MultidimensionalArray CheckRes = MultidimensionalArray.Create(1, 4);

                    MatlabRef.PutSparseMatrix(M, "M");
                    MatlabRef.PutSparseMatrix(M11, "M11");
                    MatlabRef.PutSparseMatrix(M12, "M12");
                    MatlabRef.PutSparseMatrix(M21, "M21");
                    MatlabRef.PutSparseMatrix(M22, "M22");

                    MatlabRef.Cmd("L1 = {0};", Blk1.TotalLength);
                    MatlabRef.Cmd("L2 = {0};", Blk2.TotalLength);
                    MatlabRef.Cmd("refM11 = sparse(L1, L1);");
                    MatlabRef.Cmd("refM12 = sparse(L1, L2);");
                    MatlabRef.Cmd("refM21 = sparse(L2, L1);");
                    MatlabRef.Cmd("refM22 = sparse(L2, L2);");

                    MatlabRef.Cmd("refM11(Tlist1, Tlist1) = M(Ilist1, Ilist1);");
                    MatlabRef.Cmd("refM12(Tlist1, Tlist2) = M(Ilist1, Ilist2);");
                    MatlabRef.Cmd("refM21(Tlist2, Tlist1) = M(Ilist2, Ilist1);");
                    MatlabRef.Cmd("refM22(Tlist2, Tlist2) = M(Ilist2, Ilist2);");

                    MatlabRef.Cmd("err11 = norm(refM11 - M11, inf);");
                    MatlabRef.Cmd("err12 = norm(refM12 - M12, inf);");
                    MatlabRef.Cmd("err21 = norm(refM21 - M21, inf);");
                    MatlabRef.Cmd("err22 = norm(refM22 - M22, inf);");

                    MatlabRef.Cmd("CheckRes = [err11, err12, err21, err22];");
                    MatlabRef.GetMatrix(CheckRes, "CheckRes");

                    MatlabRef.Execute();

                    Console.WriteLine("Matlab check 11: " + CheckRes[0, 0]);
                    Console.WriteLine("Matlab check 12: " + CheckRes[0, 1]);
                    Console.WriteLine("Matlab check 21: " + CheckRes[0, 2]);
                    Console.WriteLine("Matlab check 22: " + CheckRes[0, 3]);

                    Assert.IsTrue(CheckRes[0, 0] == 0.0);
                    Assert.IsTrue(CheckRes[0, 1] == 0.0);
                    Assert.IsTrue(CheckRes[0, 2] == 0.0);
                    Assert.IsTrue(CheckRes[0, 3] == 0.0);
                }

                stw.Start();

                restored_M.Acc(-1.0, M);
                double err = restored_M.InfNorm();
                Console.WriteLine("Submatrix operations error: " + err);
                Assert.IsTrue(err == 0.0);

                restored_M.Clear();
                restored_M.Acc(1.0, M);
                IMutuableMatrixEx_Extensions.Acc(restored_M, -1.0, M);
                double err2 = restored_M.InfNorm();
                Console.WriteLine("Submatrix operations error: " + err2);
                Assert.IsTrue(err2 == 0.0);

                stw.Stop();

                Console.WriteLine("Time spend in matrix operations: " + stw.Elapsed.TotalSeconds + " sec.");

                TotTime_MatrixOp += stw.Elapsed;
            }
        }
Beispiel #6
0
        public static void MultiplyTest(
            [Values(XDGusage.none, XDGusage.mixed1, XDGusage.mixed2, XDGusage.all)] XDGusage UseXdg,
            [Values(1, 3)] int DGOrder,
            [Values(false, true)] bool compressL1,
            [Values(false, true)] bool compressL2)
        {
            unsafe
            {
                int[] Params = new int[8], ParamsGlob = new int[8];
                fixed(int *pParams = Params, pParamsGlob = ParamsGlob)
                {
                    pParams[0] = (int)UseXdg;
                    pParams[1] = DGOrder;
                    pParams[2] = compressL1 ? 1 : 0;
                    pParams[3] = compressL2 ? 1 : 0;
                    pParams[4] = -pParams[0];
                    pParams[5] = -pParams[1];
                    pParams[6] = -pParams[2];
                    pParams[7] = -pParams[3];

                    csMPI.Raw.Allreduce((IntPtr)pParams, (IntPtr)pParamsGlob, 8, csMPI.Raw._DATATYPE.INT, csMPI.Raw._OP.MIN, csMPI.Raw._COMM.WORLD);
                }

                int[] ParamsMin = ParamsGlob.GetSubVector(0, 4);
                int[] ParamsMax = ParamsGlob.GetSubVector(4, 4);
                for (int i = 0; i < 4; i++)
                {
                    if (Params[i] != ParamsMin[i])
                    {
                        throw new ApplicationException();
                    }
                    if (Params[i] != -ParamsMax[i])
                    {
                        throw new ApplicationException();
                    }
                }

                Console.WriteLine("MultiplyTest({0},{1},{2},{3})", UseXdg, DGOrder, compressL1, compressL2);
            }

            using (var solver = new Matrix_MPItestMain()
            {
                m_UseXdg = UseXdg, m_DGorder = DGOrder
            }) {
                // create the test data
                // ====================

                solver.Init(null);
                solver.RunSolverMode();

                Stopwatch stw = new Stopwatch();
                stw.Reset();
                stw.Start();

                BlockMsrMatrix M = solver.OperatorMatrix;

                int[] Ilist1 = solver.ProblemMapping.GetSubvectorIndices(false, 0);
                int[] Ilist2 = solver.ProblemMapping.GetSubvectorIndices(false, 1);

                foreach (int i in Ilist1)
                {
                    Assert.IsTrue(solver.ProblemMapping.IsInLocalRange(i));
                }
                foreach (int i in Ilist2)
                {
                    Assert.IsTrue(solver.ProblemMapping.IsInLocalRange(i));
                }

                var Blk1 = solver.ProblemMapping.GetSubBlocking(Ilist1, csMPI.Raw._COMM.WORLD, compressL1 ? -1 : 0);
                var Blk2 = solver.ProblemMapping.GetSubBlocking(Ilist2, csMPI.Raw._COMM.WORLD, compressL2 ? -1 : 0);



                int[] Tlist1 = compressL1 ? default(int[]) : Blk1.GetOccupiedIndicesList();
                int[] Tlist2 = compressL2 ? default(int[]) : Blk2.GetOccupiedIndicesList();
                if (Tlist1 != null)
                {
                    Assert.AreEqual(Tlist1.Length, Ilist1.Length);
                    foreach (int i in Tlist1)
                    {
                        Assert.IsTrue(Blk1.IsInLocalRange(i));
                    }
                }
                if (Tlist2 != null)
                {
                    Assert.AreEqual(Tlist2.Length, Ilist2.Length);
                    foreach (int i in Tlist2)
                    {
                        Assert.IsTrue(Blk2.IsInLocalRange(i));
                    }
                }
                BlockMsrMatrix M11 = new BlockMsrMatrix(Blk1, Blk1);
                BlockMsrMatrix M12 = new BlockMsrMatrix(Blk1, Blk2);
                BlockMsrMatrix M21 = new BlockMsrMatrix(Blk2, Blk1);
                BlockMsrMatrix M22 = new BlockMsrMatrix(Blk2, Blk2);

                M.AccSubMatrixTo(1.0, M11, Ilist1, Tlist1, Ilist1, Tlist1);
                M.AccSubMatrixTo(1.0, M12, Ilist1, Tlist1, Ilist2, Tlist2);
                M.AccSubMatrixTo(1.0, M21, Ilist2, Tlist2, Ilist1, Tlist1);
                M.AccSubMatrixTo(1.0, M22, Ilist2, Tlist2, Ilist2, Tlist2);

                /*
                 * MultidimensionalArray CheckRes2 = MultidimensionalArray.Create(1, 4);
                 * using (var MatlabRef = new BatchmodeConnector()) {
                 *
                 *  MatlabRef.PutVector(Ilist1.Select(i => (double)i + 1.0).ToArray(), "Ilist1");
                 *  MatlabRef.PutVector(Ilist2.Select(i => (double)i + 1.0).ToArray(), "Ilist2");
                 *  MatlabRef.PutVector(Tlist1 == null ? Ilist1.Length.ForLoop(i => (double)i + 1.0 + Blk1.i0) : Tlist1.Select(i => (double)i + 1.0).ToArray(), "Tlist1");
                 *  MatlabRef.PutVector(Tlist2 == null ? Ilist2.Length.ForLoop(i => (double)i + 1.0 + Blk2.i0) : Tlist2.Select(i => (double)i + 1.0).ToArray(), "Tlist2");
                 *
                 *  MatlabRef.PutSparseMatrix(solver.AltOperatorMatrix, "M");
                 *
                 *
                 *  MatlabRef.Cmd("L1 = {0};", Blk1.TotalLength);
                 *  MatlabRef.Cmd("L2 = {0};", Blk2.TotalLength);
                 *  //MatlabRef.Cmd("refM11 = sparse(L1, L1);");
                 *  //MatlabRef.Cmd("refM12 = sparse(L1, L2);");
                 *  MatlabRef.Cmd("refM21 = sparse(L2, L1);");
                 *  //MatlabRef.Cmd("refM22 = sparse(L2, L2);");
                 *
                 *  //MatlabRef.Cmd("refM11(Tlist1, Tlist1) = M(Ilist1, Ilist1);");
                 *  //MatlabRef.Cmd("refM12(Tlist1, Tlist2) = M(Ilist1, Ilist2);");
                 *  MatlabRef.Cmd("refM21(Tlist2, Tlist1) = M(Ilist2, Ilist1);");
                 *  //MatlabRef.Cmd("refM22(Tlist2, Tlist2) = M(Ilist2, Ilist2);");
                 *
                 *  //MatlabRef.Cmd("err11 = norm(refM11 - M11, inf);");
                 *  //MatlabRef.Cmd("err12 = norm(refM12 - M12, inf);");
                 *  //MatlabRef.Cmd("err21 = norm(refM21 - M21, inf);");
                 *  //MatlabRef.Cmd("err22 = norm(refM22 - M22, inf);");
                 *
                 *  MatlabRef.Cmd("CheckRes = [refM21(1339, 1321), 0.0, 1.567, 0 ];");
                 *  MatlabRef.GetMatrix(CheckRes2, "CheckRes");
                 *
                 *  MatlabRef.Execute();
                 * }
                 */

                // test multipliation (later verified by matlab)
                BlockMsrMatrix M11xM12 = new BlockMsrMatrix(M11._RowPartitioning, M12._ColPartitioning);
                M11xM12.Acc(1.0, M12);
                BlockMsrMatrix.Multiply(M11xM12, M11, M12);

                BlockMsrMatrix M22xM21 = new BlockMsrMatrix(M22._RowPartitioning, M21._ColPartitioning);
                BlockMsrMatrix.Multiply(M22xM21, M22, M21);
                double ProdNorm = M22xM21.InfNorm();



                stw.Stop();

                //M.SaveToTextFileSparse(@"C:\tmp\M.txt");
                //M11.SaveToTextFileSparse(@"C:\tmp\M11.txt");
                //M12.SaveToTextFileSparse(@"C:\tmp\M12.txt");
                //M21.SaveToTextFileSparse(@"C:\tmp\M21.txt");
                //M22.SaveToTextFileSparse(@"C:\tmp\M22.txt");
                //M22xM21.SaveToTextFileSparse(@"C:\tmp\M22xM21.txt");


                using (var MatlabRef = new BatchmodeConnector()) {
                    MultidimensionalArray CheckRes = MultidimensionalArray.Create(1, 4);

                    MatlabRef.PutSparseMatrix(M11, "M11");
                    MatlabRef.PutSparseMatrix(M12, "M12");
                    MatlabRef.PutSparseMatrix(M21, "M21");
                    MatlabRef.PutSparseMatrix(M22, "M22");
                    MatlabRef.PutSparseMatrix(M11xM12, "M11xM12");
                    MatlabRef.PutSparseMatrix(M22xM21, "M22xM21");

                    MatlabRef.Cmd("refM11xM12 = M12 + M11*M12;");
                    MatlabRef.Cmd("refM22xM21 = M22*M21;");

                    MatlabRef.Cmd("err1112 = norm(refM11xM12 - M11xM12, inf);");
                    MatlabRef.Cmd("err2221 = norm(refM22xM21 - M22xM21, inf);");

                    MatlabRef.Cmd("CheckRes = [err1112, err2221, 0, 0];");
                    MatlabRef.GetMatrix(CheckRes, "CheckRes");

                    MatlabRef.Execute();

                    Console.WriteLine("Matlab check M11*M12: " + CheckRes[0, 0]);
                    Console.WriteLine("Matlab check M22*M21: " + CheckRes[0, 1]);

                    Assert.IsTrue(CheckRes[0, 0] == 0.0);
                    Assert.IsTrue(CheckRes[0, 1] < 1.0e-10 * ProdNorm);
                    //Assert.IsTrue(CheckRes[0, 2] == 0.0);
                    //Assert.IsTrue(CheckRes[0, 3] == 0.0);
                }


                Console.WriteLine("Time spend in matrix operations: " + stw.Elapsed.TotalSeconds + " sec.");

                TotTime_MatrixOp += stw.Elapsed;
            }
        }
Beispiel #7
0
        //
        //
        /// <summary>
        /// applies the agglomeration on a general matrix
        /// </summary>
        /// <param name="Matrix">the matrix that should be manipulated.</param>
        /// <param name="Rhs">the right-hand-side that should be manipulated</param>
        /// <param name="ColMap"></param>
        /// <param name="ColMapAggSw">Turns column agglomeration on/off fore each variable individually; default == null is on. </param>
        /// <param name="RowMap"></param>
        /// <param name="RowMapAggSw">The same shit as for <paramref name="ColMapAggSw"/>, just for rows.</param>
        public void ManipulateMatrixAndRHS<M, T>(M Matrix, T Rhs, UnsetteledCoordinateMapping RowMap, UnsetteledCoordinateMapping ColMap, bool[] RowMapAggSw = null, bool[] ColMapAggSw = null)
            where M : IMutableMatrixEx
            where T : IList<double>
        {
            MPICollectiveWatchDog.Watch();
            //var mtxS = GetFrameMatrices(Matrix, RowMap, ColMap);

            if (Matrix == null && Rhs == null)
                // nothing to do
                return;

            if (TotalNumberOfAgglomerations <= 0)
                // nothing to do
                return;

            if (RowMapAggSw != null)
                throw new NotImplementedException();

            // generate agglomeration sparse matrices
            // ======================================

            int RequireRight;
            if (Matrix == null) {
                // we don't need multiplication-from-the-right at all
                RequireRight = 0;
            } else {
                if (RowMap.EqualsUnsetteled(ColMap) && ArrayTools.ListEquals(ColMapAggSw, RowMapAggSw)) {
                    // we can use the same matrix for right and left multiplication
                    RequireRight = 1;

                } else {
                    // separate matrix for the multiplication-from-the-right is required
                    RequireRight = 2;
                }
            }

            BlockMsrMatrix LeftMul = null, RightMul = null;
            {

                foreach (var kv in DictAgglomeration) {
                    var Species = kv.Key;
                    var m_Agglomerator = kv.Value;

                    if (m_Agglomerator != null) {

                        CellMask spcMask = this.Tracker.Regions.GetSpeciesMask(Species);

                        MiniMapping rowMini = new MiniMapping(RowMap, Species, this.Tracker.Regions);
                        BlockMsrMatrix LeftMul_Species = m_Agglomerator.GetRowManipulationMatrix(RowMap, rowMini.MaxDeg, rowMini.NoOfVars, rowMini.i0Func, rowMini.NFunc, false, spcMask);
                        if (LeftMul == null) {
                            LeftMul = LeftMul_Species;
                        } else {
                            LeftMul.Acc(1.0, LeftMul_Species);
                        }

                        if (!object.ReferenceEquals(LeftMul, RightMul) && RightMul != null) {
                            MiniMapping colMini = new MiniMapping(ColMap, Species, this.Tracker.Regions);
                            BlockMsrMatrix RightMul_Species = m_Agglomerator.GetRowManipulationMatrix(ColMap, colMini.MaxDeg, colMini.NoOfVars, colMini.i0Func, colMini.NFunc, false, spcMask);

                            if (RightMul == null) {
                                RightMul = RightMul_Species;
                            } else {
                                RightMul.Acc(1.0, RightMul_Species);
                            }

                        } else if (RequireRight == 1) {
                            RightMul = LeftMul;
                        } else {
                            RightMul = null;
                        }
                    }
                }
            }

            // apply the agglomeration to the matrix
            // =====================================

            if (Matrix != null) {
                BlockMsrMatrix RightMulTr = RightMul.Transpose();

                BlockMsrMatrix _Matrix;
                if (Matrix is BlockMsrMatrix) {
                    _Matrix = (BlockMsrMatrix)((object)Matrix);
                } else {
                    _Matrix = Matrix.ToBlockMsrMatrix(RowMap, ColMap);
                }

                var AggMatrix = BlockMsrMatrix.Multiply(LeftMul, BlockMsrMatrix.Multiply(_Matrix, RightMulTr));

                if (object.ReferenceEquals(_Matrix, Matrix)) {
                    _Matrix.Clear();
                    _Matrix.Acc(1.0, AggMatrix);
                } else {
                    Matrix.Acc(-1.0, _Matrix); //   das ist so
                    Matrix.Acc(1.0, AggMatrix); //  meagaschlecht !!!!!!
                }
            }

            // apply the agglomeration to the Rhs
            // ==================================

            if (Rhs != null) {

                double[] tmp = Rhs.ToArray();
                if (object.ReferenceEquals(tmp, Rhs))
                    throw new ApplicationException("Flache kopie sollte eigentlich ausgeschlossen sein!?");

                LeftMul.SpMV(1.0, tmp, 0.0, Rhs);
            }
        }
Beispiel #8
0
        public static void SubBlockExtractionWithCoupling(
            [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg,
            [Values(2)] int DGOrder,
            [Values(MatrixShape.diagonal, MatrixShape.diagonal_var, MatrixShape.diagonal_spec, MatrixShape.diagonal_var_spec)] MatrixShape MShape
            )
        {
            Utils.TestInit((int)UseXdg, DGOrder, (int)MShape);
            Console.WriteLine("ExtractDiagonalBlocks({0},{1},{2})", UseXdg, DGOrder, MShape);

            //Arrange --- get multigridoperator
            MultigridOperator MGOp = Utils.CreateTestMGOperator(UseXdg, DGOrder, MShape);
            BlockMsrMatrix    M    = MGOp.OperatorMatrix;
            MultigridMapping  map  = MGOp.Mapping;

            //Arrange --- setup masking
            SubBlockSelector SBS  = new SubBlockSelector(map);
            BlockMask        mask = new BlockMask(SBS, null);

            bool[] coupling = Utils.SetCoupling(MShape);

            //Arrange --- some time measurement
            Stopwatch stw = new Stopwatch();

            stw.Reset();

            //Arrange --- setup auxiliary matrix
            //this will show us if more is extracted, than it should ...
            var Mprep = new BlockMsrMatrix(map);

            Mprep.Acc(1.0, M);

            //Act --- diagonal subblock extraction
            stw.Start();
            var blocks = mask.GetDiagonalBlocks(Mprep, coupling[0], coupling[1]);

            stw.Stop();

            //Assert --- all diagonal blocks are extracted
            Assert.IsTrue(blocks.Length == map.LocalNoOfBlocks);


            for (int i = 0; i < map.LocalNoOfBlocks; i++)
            {
                //Arrange --- get ith diagonal block of M: M_i
                int iBlock = i + map.AggGrid.CellPartitioning.i0;
                int L      = map.GetBlockLen(iBlock);
                int i0     = map.GetBlockI0(iBlock);
                var Mblock = MultidimensionalArray.Create(L, L);
                M.ReadBlock(i0, i0, Mblock);

                //Act --- M_i-Mones_i
                Mblock.Acc(-1.0, blocks[i]);

                //Assert --- are extracted blocks and
                Assert.IsTrue(Mblock.InfNorm() == 0.0, String.Format("infNorm of block {0} neq 0!", i));
            }



            //BlockMsrMatrix all1;
            //all1.SetAll(1);
            //Generate broken diagonal matrix, die zur Maske passt: M
            //M+all1=M_prep
            //Wende Extraction auf M_prep an, Man sollte nun M bekommen
            //Test: M_prep-extract(M_prep)=all1
            //Test-crit: Result.SumEntries=DOF^2 oder Result.Max()==Result.Min()==1
            //oder (besser)
            //Test: M-extract(M_prep)=zeros
            //Test-crit: Result.InfNorm()==0

            //Der Test kann für ExtractSubMatrix mit ignore coupling wiederholt werden
            //eventuell: Testmatrix finden mit brauchbaren Nebendiagonalen für einen Fall

            //Was wird getestet: funktioniert ignorecoupling richtig?
        }