public static void MemoryConsumptionDebugging()
        {
            int order     = 100000;
            int bandwidth = 200;

            for (int rep = 0; rep < 10; ++rep)
            {
                var dok = DokSymmetric.CreateEmpty(order);
                for (int i = 0; i < order; ++i)
                {
                    dok[i, i] = 10.0;
                    if (i >= bandwidth)
                    {
                        dok[i - bandwidth, i] = 1.0;
                    }
                    else
                    {
                        dok[0, i] = 1.0;
                    }
                }
                dok[0, 0] = 10.0;

                SymmetricCscMatrix matrix = dok.BuildSymmetricCscMatrix(true);
                var rhs      = Vector.CreateWithValue(order, 2.0);
                var solution = Vector.CreateZero(order);

                using (var factorization = CholeskySuiteSparse.Factorize(matrix, true))
                {
                    factorization.SolveLinearSystem(rhs, solution);
                }
            }
        }
        private static void TestSystemSolution1()
        {
            Skip.IfNot(TestSettings.TestSuiteSparse, TestSettings.MessageWhenSkippingSuiteSparse);

            // Define linear system
            var rhs = Vector.CreateFromArray(new double[] { 6.0, 14.0, 11.0, 12.0 });
            var solutionExpected = Vector.CreateFromArray(new double[] { 1.0, 1.0, 1.0, 1.0 });
            var matrixDOK        = DokSymmetric.CreateEmpty(4);

            matrixDOK[0, 0] = 4.0; matrixDOK[0, 2] = 2.0;
            matrixDOK[1, 1] = 10.0; matrixDOK[1, 2] = 1.0; matrixDOK[1, 3] = 3.0;
            matrixDOK[2, 2] = 8.0;
            matrixDOK[3, 3] = 9.0;
            SymmetricCscMatrix matrixCSC = matrixDOK.BuildSymmetricCscMatrix(true);

            //const int n = 4;
            //const int nnz = 7;
            //int[] colOffsets = new int[n + 1] { 0, 1, 2, 5, nnz };
            //int[] rowIndices = new int[nnz] { 0, 1, 0, 1, 2, 1, 3 };
            //double[] values = new double[nnz] { 4.0, 10.0, 2.0, 1.0, 8.0, 3.0, 9.0 };
            //SymmetricCSC matrixCSC = new SymmetricCSC(values, rowIndices, colOffsets, false);

            //Solve it using SuiteSparse
            using (var factor = CholeskySuiteSparse.Factorize(matrixCSC, true))
            {
                Vector solution = factor.SolveLinearSystem(rhs);
                comparer.AssertEqual(solutionExpected, solution);
            }
        }
Beispiel #3
0
        public SymmetricCscMatrix BuildGlobalMatrix(ISubdomainFreeDofOrdering dofOrdering, IEnumerable <IElement> elements,
                                                    IElementMatrixProvider matrixProvider)
        {
            int numFreeDofs     = dofOrdering.NumFreeDofs;
            var subdomainMatrix = DokSymmetric.CreateEmpty(numFreeDofs);

            foreach (IElement element in elements)
            {
                // TODO: perhaps that could be done and cached during the dof enumeration to avoid iterating over the dofs twice
                (int[] elementDofIndices, int[] subdomainDofIndices) = dofOrdering.MapFreeDofsElementToSubdomain(element);
                IMatrix elementMatrix = matrixProvider.Matrix(element);
                subdomainMatrix.AddSubmatrixSymmetric(elementMatrix, elementDofIndices, subdomainDofIndices);
            }

            (double[] values, int[] rowIndices, int[] colOffsets) = subdomainMatrix.BuildSymmetricCscArrays(sortColsOfEachRow);
            if (!isIndexerCached)
            {
                cachedRowIndices = rowIndices;
                cachedColOffsets = colOffsets;
                isIndexerCached  = true;
            }
            else
            {
                Debug.Assert(Utilities.AreEqual(cachedRowIndices, rowIndices));
                Debug.Assert(Utilities.AreEqual(cachedColOffsets, colOffsets));
            }


            return(SymmetricCscMatrix.CreateFromArrays(numFreeDofs, values, cachedRowIndices, cachedColOffsets, false));
        }
Beispiel #4
0
        private static void TestIndexer()
        {
            Matrix       dense = Matrix.CreateFromArray(SparsePosDef10by10.Matrix);
            DokSymmetric dok   = CreateDok(SparsePosDef10by10.Matrix);

            comparer.AssertEqual(dense, dok);
        }
        // will probably not work since the matrix will not always be positive definite
        //[SkippableFact]
        private static void TestRowAdditionReverse()
        {
            Skip.IfNot(TestSettings.TestSuiteSparse, TestSettings.MessageWhenSkippingSuiteSparse);

            Matrix original = Matrix.CreateFromArray(SparsePosDef10by10.Matrix);
            Vector rhs      = Vector.CreateFromArray(SparsePosDef10by10.Rhs);

            // Start the matrix as diagonal
            var matrixExpected = Matrix.CreateIdentity(original.NumColumns);
            var dok            = DokSymmetric.CreateIdentity(SparsePosDef10by10.Order);
            var factor         = CholeskySuiteSparse.Factorize(dok.BuildSymmetricCscMatrix(true), false);

            for (int i = 0; i < matrixExpected.NumRows; ++i)
            {
                // Update matrix
                Vector newRowVector = original.GetRow(i);
                matrixExpected.SetSubrow(i, newRowVector);
                matrixExpected.SetSubcolumn(i, newRowVector);
                //Console.WriteLine($"\nOnly dofs [0, {i}]");
                factor.AddRow(i, SparseVector.CreateFromDense(newRowVector));

                // Solve new linear system
                Vector solutionExpected = matrixExpected.FactorCholesky(true).SolveLinearSystem(rhs);
                Vector solutionComputed = factor.SolveLinearSystem(rhs);
                comparer.AssertEqual(solutionExpected, solutionComputed);
            }
        }
        private static void CheckSystemSolution2()
        {
            Skip.IfNot(TestSettings.TestSuiteSparse, TestSettings.MessageWhenSkippingSuiteSparse);

            int order = SparsePosDef10by10.Order;

            // Build the matrices and right hand sides
            var dense = Matrix.CreateFromArray(SparsePosDef10by10.Matrix);
            //var skyline = SkylineMatrix.CreateFromArrays(order, SparsePositiveDefinite.skylineValues,
            //    SparsePositiveDefinite.skylineDiagOffsets, false);
            //var dok = DOKSymmetricColMajor.CreateFromSparseMatrix(skyline);
            var dok = DokSymmetric.CreateEmpty(order);

            for (int j = 0; j < order; ++j)
            {
                for (int i = 0; i <= j; ++i)
                {
                    if (dense[i, j] != 0)
                    {
                        dok[i, j] = dense[i, j];
                    }
                }
            }
            Vector b = Vector.CreateFromArray(SparsePosDef10by10.Rhs);
            Matrix B = Matrix.CreateFromArray(SquareInvertible10by10.Matrix);

            // Solve using dense algebra
            CholeskyFull chol           = dense.FactorCholesky(false);
            Matrix       U              = chol.GetFactorU();
            Matrix       L              = U.Transpose();
            Vector       xSolveExpect   = chol.SolveLinearSystem(b);
            Matrix       XSolveExpect   = dense.Invert() * B;
            Vector       xBackExpect    = U.Invert() * b;
            Matrix       XBackExpect    = U.Invert() * B;
            Vector       xForwardExpect = L.Invert() * b;
            Matrix       XForwardExpect = L.Invert() * B;

            // Solve using SuiteSparse
            var(values, rowIndices, colOffsets) = dok.BuildSymmetricCscArrays(true);
            CholeskySuiteSparse factor = CholeskySuiteSparse.Factorize(order, values.Length, values, rowIndices, colOffsets,
                                                                       true);
            Vector xSolveComput   = factor.SolveLinearSystem(b);
            Matrix XSolveComput   = factor.SolveLinearSystems(B);
            Vector xBackComput    = factor.BackSubstitution(b);
            Matrix XBackComput    = factor.BackSubstitutions(B);
            Vector xForwardComput = factor.ForwardSubstitution(b);
            Matrix XForwardComput = factor.ForwardSubstitutions(B);
            Vector xSolveComput2  = factor.BackSubstitution(factor.ForwardSubstitution(b));

            // Check results
            comparer.AssertEqual(xSolveExpect, xSolveComput);
            comparer.AssertEqual(XSolveExpect, XSolveComput);
            comparer.AssertEqual(xBackExpect, xBackComput);
            comparer.AssertEqual(XBackExpect, XBackComput);
            comparer.AssertEqual(xForwardExpect, xForwardComput);
            comparer.AssertEqual(XForwardExpect, XForwardComput);
        }
Beispiel #7
0
 /// <summary>
 /// Reads a symmetric sparse matrix from the file specified by <paramref name="path"/>. The file needs to contain only
 /// the upper or lower triangle.
 /// </summary>
 /// <param name="path">The absolute path of the array.</param>
 /// <exception cref="IOException">Thrown if there is no such file or if the dimensions of the matrix specified in the
 ///     first line are invalid.</exception>
 public DokSymmetric ReadFileAsDokSymmetricColMajor(string path)
 {
     using (var reader = new StreamReader(path))
     {
         (int numRows, int numCols, int nnz) = ReadMatrixDimensions(reader);
         var builder = DokSymmetric.CreateEmpty(numCols);
         ReadMatrixEntries(reader, nnz, builder);
         return(builder);
     }
 }
Beispiel #8
0
        private static void TestGetColumn()
        {
            Matrix       dense = Matrix.CreateFromArray(SparsePosDef10by10.Matrix);
            DokSymmetric dok   = CreateDok(SparsePosDef10by10.Matrix);

            for (int j = 0; j < SparsePosDef10by10.Order; ++j)
            {
                comparer.AssertEqual(dense.GetColumn(j), dok.GetColumn(j)); //TODO: have hardcoded columns to compare against
            }
        }
        //TODO: Move this method to DokSymmetric, so that I can optimize access to its private data
        internal static SkylineMatrix GetSubmatrixSymmetricSkyline(double[] skyValues, int[] skyDiagOffsets,
                                                                   int[] rowsColsToKeep)
        {
            //TODO: perhaps this can be combined with the CSC and full version to get all 2 submatrices needed for
            //      Schur complements more efficiently.

            int subOrder = rowsColsToKeep.Length;

            if (subOrder == 0)
            {
                return(SkylineMatrix.CreateFromArrays(subOrder, new double[0], new int[1] {
                    0
                }, false, false));
            }
            var submatrix = DokSymmetric.CreateEmpty(subOrder);

            for (int subCol = 0; subCol < subOrder; ++subCol)
            {
                int col        = rowsColsToKeep[subCol];
                int diagOffset = skyDiagOffsets[col];
                int colHeight  = skyDiagOffsets[col + 1] - diagOffset - 1; // excluding diagonal
                for (int subRow = 0; subRow <= subCol; ++subRow)
                {
                    int row = rowsColsToKeep[subRow];
                    if (row <= col)
                    {
                        int entryHeight = col - row;  // excluding diagonal
                        if (entryHeight <= colHeight) // inside stored non zero pattern
                        {
                            double val = skyValues[diagOffset + entryHeight];
                            if (val != 0.0)
                            {
                                submatrix.SetEntryUpper(subRow, subCol, val);             // Skyline format stores many unnecessary zeros.
                            }
                        }
                    }
                    else // Transpose row <-> col. The cached column height and offset must be recalculated.
                    {
                        int transposedDiagOffset = skyDiagOffsets[row];
                        int transposedColHeight  = skyDiagOffsets[row + 1] - transposedDiagOffset - 1; // excluding diagonal
                        int entryHeight          = row - col;                                          // excluding diagonal
                        if (entryHeight <= transposedColHeight)                                        // inside stored non zero pattern
                        {
                            double val = skyValues[transposedDiagOffset + entryHeight];
                            if (val != 0.0)
                            {
                                submatrix[subRow, subCol] = val;             // Skyline format stores many unnecessary zeros.
                            }
                        }
                    }
                }
            }
            return(submatrix.BuildSkylineMatrix());
        }
        private IList <Vector> FEAnalysisCantilever2LoadCases(Matrix x)
        {
            int numLoadCases = 2;
            int numAllDofs   = 2 * (nelx + 1) * (nely + 1);
            var K            = DokSymmetric.CreateEmpty(numAllDofs);
            var F            = new Vector[] { Vector.CreateZero(numAllDofs), Vector.CreateZero(numAllDofs) };
            var U            = new Vector[] { Vector.CreateZero(numAllDofs), Vector.CreateZero(numAllDofs) };

            Matrix Ke             = ElementStiffness();
            int    numElementDofs = Ke.NumRows;

            int[] elementDofsLocal = Enumerable.Range(0, numElementDofs).ToArray();

            // Global stiffness matrix assembly
            for (int ely = 1; ely <= nely; ++ely)
            {
                for (int elx = 1; elx <= nelx; ++elx)
                {
                    int[]  elementDofsGlobal = GetElementDofs(elx, ely);
                    double density           = Math.Pow(x[ely - 1, elx - 1], penal);
                    K.AddSubmatrixSymmetric(density * Ke, elementDofsLocal, elementDofsGlobal);
                }
            }

            // Define supports for cantilever beam
            IEnumerable <int> fixedDofs = Enumerable.Range(0, 2 * (nely + 1));

            int[] freeDofs = Enumerable.Range(0, numAllDofs).Except(fixedDofs).ToArray();

            // Load case 1: unit load towards -y at bottom right corner
            F[0][2 * (nelx + 1) * (nely + 1) - 1] = -1.0;

            // Load case 2: unit load towards +y at top right corner
            F[1][2 * (nelx) * (nely + 1) + 1] = 1.0;

            // Solve linear system
            CholeskyCSparseNet factorizedKf = CholeskyCSparseNet.Factorize(
                K.GetSubmatrix(freeDofs).BuildSymmetricCscMatrix(true)); // only factorize the matrix once

            for (int c = 0; c < numLoadCases; ++c)
            {
                Vector Ff = F[c].GetSubvector(freeDofs);
                Vector Uf = factorizedKf.SolveLinearSystem(Ff);
                for (int i = 0; i < freeDofs.Length; ++i)
                {
                    U[c][freeDofs[i]] = Uf[i];
                }
                //U[c].CopyNonContiguouslyFrom(freeDofs, Uf, Enumerable.Range(0, freeDofs.Length).ToArray()); // alternative way, but probably slower.
                //foreach (int i in fixedDofs) U[c][i] = 0.0; // They are 0 by default
            }
            return(U);
        }
Beispiel #11
0
        private static void TestSystemSolution()
        {
            int order   = SparsePosDef10by10.Order;
            var skyline = SkylineMatrix.CreateFromArrays(order, SparsePosDef10by10.SkylineValues,
                                                         SparsePosDef10by10.SkylineDiagOffsets, true, true);
            var dok       = DokSymmetric.CreateFromSparseMatrix(skyline);
            var b         = Vector.CreateFromArray(SparsePosDef10by10.Rhs);
            var xExpected = Vector.CreateFromArray(SparsePosDef10by10.Lhs);

            (double[] cscValues, int[] cscRowIndices, int[] cscColOffsets) = dok.BuildSymmetricCscArrays(true);
            var    factor    = CholeskyCSparseNet.Factorize(order, cscValues.Length, cscValues, cscRowIndices, cscColOffsets);
            Vector xComputed = factor.SolveLinearSystem(b);

            comparer.AssertEqual(xExpected, xComputed);
        }
Beispiel #12
0
        private static void TestAddSubmatrix()
        {
            var k1        = Matrix.CreateFromArray(GlobalMatrixAssembly.SubMatrix1);
            var k2        = Matrix.CreateFromArray(GlobalMatrixAssembly.SubMatrix2);
            var k3        = Matrix.CreateFromArray(GlobalMatrixAssembly.SubMatrix3);
            var expectedK = Matrix.CreateFromArray(GlobalMatrixAssembly.GlobalMatrix);

            var computedK = DokSymmetric.CreateEmpty(GlobalMatrixAssembly.GlobalOrder);

            computedK.AddSubmatrixSymmetric(k1, GlobalMatrixAssembly.IndicesDictionary1);
            computedK.AddSubmatrixSymmetric(k2, GlobalMatrixAssembly.IndicesDictionary2);
            computedK.AddSubmatrixSymmetric(k3, GlobalMatrixAssembly.IndicesDictionary3);

            comparer.AssertEqual(expectedK, computedK);
        }
        private IList <Vector> FEAnalysisHalfMbbBeam(Matrix x)
        {
            int numAllDofs = 2 * (nelx + 1) * (nely + 1);
            var K          = DokSymmetric.CreateEmpty(numAllDofs);
            var F          = Vector.CreateZero(numAllDofs);
            var U          = Vector.CreateZero(numAllDofs);

            Matrix Ke             = ElementStiffness();
            int    numElementDofs = Ke.NumRows;

            int[] elementDofsLocal = Enumerable.Range(0, numElementDofs).ToArray();

            // Global stiffness matrix assembly
            for (int ely = 1; ely <= nely; ++ely)
            {
                for (int elx = 1; elx <= nelx; ++elx)
                {
                    int[]  elementDofsGlobal = GetElementDofs(elx, ely);
                    double density           = Math.Pow(x[ely - 1, elx - 1], penal);
                    K.AddSubmatrixSymmetric(density * Ke, elementDofsLocal, elementDofsGlobal);
                }
            }

            // Define loads and supports for half MBB beam
            F[1] = -1.0;
            var fixedDofs = new HashSet <int>(); //TODO: Use LINQ to simplify this

            for (int i = 0; i < 2 * (nely + 1); i += 2)
            {
                fixedDofs.Add(i);
            }
            fixedDofs.Add(numAllDofs - 1);
            int[] freeDofs = Enumerable.Range(0, numAllDofs).Except(fixedDofs).ToArray();

            // Solve linear system
            DokSymmetric Kf = K.GetSubmatrix(freeDofs);
            Vector       Ff = F.GetSubvector(freeDofs);
            Vector       Uf = CholeskyCSparseNet.Factorize(Kf.BuildSymmetricCscMatrix(true)).SolveLinearSystem(Ff);

            for (int i = 0; i < freeDofs.Length; ++i)
            {
                U[freeDofs[i]] = Uf[i];
            }
            //U.CopyNonContiguouslyFrom(freeDofs, Uf, Enumerable.Range(0, freeDofs.Length).ToArray()); // alternative way, but probably slower.
            //foreach (int i in fixedDofs) U[i] = 0.0; // They are 0 by default

            return(new Vector[] { U });
        }
Beispiel #14
0
        private static DokSymmetric CreateDok(double[,] symmMatrix)
        {
            int n   = symmMatrix.GetLength(0);
            var dok = DokSymmetric.CreateEmpty(n);

            for (int j = 0; j < n; ++j)
            {
                for (int i = 0; i <= j; ++i)
                {
                    if (symmMatrix[i, j] != 0.0)
                    {
                        dok[i, j] = symmMatrix[i, j];
                    }
                }
            }
            return(dok);
        }
        internal static DokSymmetric CreateRandomMatrix(int order, double nonZeroChance)
        {
            var rand = new Random();
            var dok  = DokSymmetric.CreateEmpty(order);

            for (int j = 0; j < order; ++j)
            {
                for (int i = 0; i <= j; ++i)
                {
                    if (rand.NextDouble() <= nonZeroChance)
                    {
                        dok[i, j] = rand.NextDouble();
                    }
                }
            }
            return(dok);
        }
Beispiel #16
0
                IMatrixView matrixConstrConstr) BuildGlobalSubmatrices(
            ISubdomainFreeDofOrdering freeDofOrdering, ISubdomainConstrainedDofOrdering constrainedDofOrdering,
            IEnumerable <IElement> elements, IElementMatrixProvider matrixProvider)
        {
            int numFreeDofs     = freeDofOrdering.NumFreeDofs;
            var subdomainMatrix = DokSymmetric.CreateEmpty(numFreeDofs);

            //TODO: also reuse the indexers of the constrained matrices.
            constrainedAssembler.InitializeNewMatrices(freeDofOrdering.NumFreeDofs, constrainedDofOrdering.NumConstrainedDofs);

            // Process the stiffness of each element
            foreach (IElement element in elements)
            {
                // TODO: perhaps that could be done and cached during the dof enumeration to avoid iterating over the dofs twice
                (int[] elementDofsFree, int[] subdomainDofsFree) = freeDofOrdering.MapFreeDofsElementToSubdomain(element);
                (int[] elementDofsConstrained, int[] subdomainDofsConstrained) =
                    constrainedDofOrdering.MapConstrainedDofsElementToSubdomain(element);

                IMatrix elementMatrix = matrixProvider.Matrix(element);
                subdomainMatrix.AddSubmatrixSymmetric(elementMatrix, elementDofsFree, subdomainDofsFree);
                constrainedAssembler.AddElementMatrix(elementMatrix, elementDofsFree, subdomainDofsFree,
                                                      elementDofsConstrained, subdomainDofsConstrained);
            }

            // Create and cache the CSC arrays for the free dofs.
            (double[] values, int[] rowIndices, int[] colOffsets) = subdomainMatrix.BuildSymmetricCscArrays(sortColsOfEachRow);
            if (!isIndexerCached)
            {
                cachedRowIndices = rowIndices;
                cachedColOffsets = colOffsets;
                isIndexerCached  = true;
            }
            else
            {
                Debug.Assert(Utilities.AreEqual(cachedRowIndices, rowIndices));
                Debug.Assert(Utilities.AreEqual(cachedColOffsets, colOffsets));
            }

            // Create the free and constrained matrices.
            subdomainMatrix = null; // Let the DOK be garbaged collected early, in case there isn't sufficient memory.
            var matrixFreeFree =
                SymmetricCscMatrix.CreateFromArrays(numFreeDofs, values, cachedRowIndices, cachedColOffsets, false);

            (CsrMatrix matrixConstrFree, CsrMatrix matrixConstrConstr) = constrainedAssembler.BuildMatrices();
            return(matrixFreeFree, matrixConstrFree.TransposeToCSC(false), matrixConstrFree, matrixConstrConstr);
        }
Beispiel #17
0
        private static void TestRandomMatrix()
        {
            // Create the random matrix and write it to a temporary file
            DokSymmetric originalMatrix   = RandomUtilities.CreateRandomMatrix(1000, 0.2);
            var          coordinateWriter = new CoordinateTextFileWriter();

            coordinateWriter.NumericFormat = new ExponentialFormat {
                NumDecimalDigits = 10
            };
            string tempFile = "temp.txt";

            coordinateWriter.WriteToFile(originalMatrix, tempFile);

            // Read the temporary file and compare it with the generated matrix
            var          reader     = new CoordinateTextFileReader();
            DokSymmetric readMatrix = reader.ReadFileAsDokSymmetricColMajor(tempFile);
            bool         success    = comparer.AreEqual(originalMatrix, readMatrix);

            // Clean up
            File.Delete(tempFile);
            Assert.True(success);
        }
        private static void TestRowDeletion()
        {
            Skip.IfNot(TestSettings.TestSuiteSparse, TestSettings.MessageWhenSkippingSuiteSparse);

            Matrix original = Matrix.CreateFromArray(SparsePosDef10by10.Matrix);
            Vector rhs      = Vector.CreateFromArray(SparsePosDef10by10.Rhs);

            // Start the matrix from the original
            var matrixExpected = Matrix.CreateFromArray(SparsePosDef10by10.Matrix);
            var dok            = DokSymmetric.CreateEmpty(SparsePosDef10by10.Order);

            for (int j = 0; j < matrixExpected.NumColumns; ++j)
            {
                for (int i = 0; i <= j; ++i)
                {
                    if (matrixExpected[i, j] != 0)
                    {
                        dok[i, j] = matrixExpected[i, j];
                    }
                }
            }
            var factor = CholeskySuiteSparse.Factorize(dok.BuildSymmetricCscMatrix(true), false);

            for (int i = 0; i < matrixExpected.NumRows; ++i)
            {
                // Update matrix
                Vector identityRow = Vector.CreateZero(matrixExpected.NumColumns);
                identityRow[i] = 1.0;
                matrixExpected.SetSubrow(i, identityRow);
                matrixExpected.SetSubcolumn(i, identityRow);
                //Console.WriteLine($"\nOnly dofs [{i + 1}, 10)");
                factor.DeleteRow(i);

                // Solve new linear system
                Vector solutionExpected = matrixExpected.FactorCholesky(false).SolveLinearSystem(rhs);
                Vector solutionComputed = factor.SolveLinearSystem(rhs);
                comparer.AssertEqual(solutionExpected, solutionComputed);
            }
        }
Beispiel #19
0
        private static void TestGetSubmatrix()
        {
            DokSymmetric matrix = CreateDok(new double[, ]
            {
                { 0, 0, 20, 0, 0, 0 },
                { 0, 1, 0, 31, 0, 0 },
                { 20, 0, 2, 0, 42, 0 },
                { 0, 31, 0, 3, 0, 53 },
                { 0, 0, 42, 0, 4, 0 },
                { 0, 0, 0, 53, 0, 5 }
            });
            var          rowsToKeep        = new int[] { 4, 2, 5 };
            DokSymmetric submatrixExpected = CreateDok(new double[, ]
            {
                { 4, 42, 0 },
                { 42, 2, 0 },
                { 0, 0, 5 }
            });

            DokSymmetric submatrixComputed = matrix.GetSubmatrix(rowsToKeep);

            comparer.AssertEqual(submatrixExpected, submatrixComputed);
        }
        public void UpdateModelAndAnalyze(IVectorView youngModuli)
        {
            this.youngModuli = youngModuli;

            // Global stiffness matrix assembly
            int numAllDofs = 2 * (numElementsX + 1) * (numElementsY + 1);
            var K          = DokSymmetric.CreateEmpty(numAllDofs);

            for (int e = 0; e < NumElements; ++e)
            {
                int[] elementDofsGlobal = GetElementDofs(e);
                K.AddSubmatrixSymmetric(unitStiffness.Scale(youngModuli[e]), elementDofsLocal, elementDofsGlobal);
            }

            // Apply boundary conditions
            (int[] freeDofs, Vector[] Fs) = ApplyBoundaryConditions();
            int numLoadCases = Fs.Length;

            globalDisplacements = new Vector[numLoadCases];

            // Solve linear system
            DokSymmetric Kf     = K.GetSubmatrix(freeDofs);
            var          factor = CholeskyCSparseNet.Factorize(Kf.BuildSymmetricCscMatrix(true));

            for (int c = 0; c < numLoadCases; ++c)
            {
                Vector Ff = Fs[c].GetSubvector(freeDofs);
                Vector Uf = factor.SolveLinearSystem(Ff);
                var    U  = Vector.CreateZero(numAllDofs);
                for (int i = 0; i < freeDofs.Length; ++i)
                {
                    U[freeDofs[i]] = Uf[i];
                }
                globalDisplacements[c] = U;
                //U.CopyNonContiguouslyFrom(freeDofs, Uf, Enumerable.Range(0, freeDofs.Length).ToArray()); // alternative way, but probably slower.
            }
        }
Beispiel #21
0
 /// <summary>
 /// Finds a fill-reducting permutation for the rows/columns of a symmetric sparse matrix, described by its sparsity
 /// pattern. The returned permutation is new-to-old.
 /// </summary>
 /// <param name="pattern">The indices of the non-zero entries of a symmetric matrix.</param>
 /// <returns>
 /// permutation: An array containing the fill reducing permutation.
 /// stats: Measuments taken during the execution of the reordering algorithm.
 /// </returns>
 /// <exception cref="SuiteSparseException">Thrown if SuiteSparse dlls cannot be loaded or if AMD fails.</exception>
 public (int[] permutation, ReorderingStatistics stats) FindPermutation(DokSymmetric dok)
 {
     (double[] values, int[] rowIndices, int[] colOffsets) = dok.BuildSymmetricCscArrays(true);
     return(FindPermutation(dok.NumColumns, rowIndices.Length, rowIndices, colOffsets));
 }