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); } }
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)); }
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); }
/// <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); } }
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); }
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); }
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 }); }
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); }
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); }
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); } }
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. } }
/// <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)); }