public static Vector SolveChol(CompressedColumnStorage <double> A, Vector x, Vector b, out bool status, out string algorithm) { var orderings = new[] { CSparse.ColumnOrdering.MinimumDegreeAtPlusA, CSparse.ColumnOrdering.MinimumDegreeAtA, CSparse.ColumnOrdering.MinimumDegreeStS, CSparse.ColumnOrdering.Natural }; status = false; algorithm = "LU"; foreach (var ordering in orderings) { try { status = true; if (A.RowCount == A.ColumnCount) { var lu = new SparseCholesky(A, ordering); var xc = x.Clone(); var bc = b.Clone(); lu.Solve(bc.ToDouble(), xc.ToDouble()); algorithm = "CHOL/" + ordering; status = true; return(xc); } } catch (Exception e) { status = false; } } return(x); }
/// <inheritdoc /> public void Initialize() { var matrix = A; //var ttt = A.ToDenseMatrix(); var sp = new Stopwatch(); sp.Start(); cholesky = SparseCholesky.Create(matrix, ColumnOrdering.MinimumDegreeAtPlusA); IsInitialized = true; sp.Stop(); if (Target != null) { Target.Trace.Write(TraceRecord.Create(BriefFiniteElementNet.Common.TraceLevel.Info, string.Format(CultureInfo.CurrentCulture, "Cholesky decomposition of matrix took about {0:#,##0} ms", sp.ElapsedMilliseconds))); } }
public void TestEmptyFactorize() { var A = new SparseMatrix(0, 0, 0); var chol = SparseCholesky.Create(A, ColumnOrdering.MinimumDegreeAtPlusA); Assert.NotNull(chol); Assert.IsTrue(chol.NonZerosCount == 0); }
public void TestConstructorThrowsOnNonSpd() { // Load matrix from a file. var A = ResourceLoader.Get <double>("symmetric-40.mat"); Assert.Throws <Exception>(() => { var chol = SparseCholesky.Create(A, ColumnOrdering.MinimumDegreeAtPlusA); }); }
void PrecomputeDistanceMatrix2D(int W, int H, bool show = true) { int N = area_cnt; //////////////////////////////////////////////////////////// // step III-1. build matrix A for distance computation // [CAUTION] this is NEGATED matrix to use Cholesky decomp. //////////////////////////////////////////////////////////// var C_dist = new CoordinateStorage <double>(N, N, 5 * N); // banded matrix without exception for (int matid_this = 0; matid_this < N; matid_this++) { List <int> matid_neighbor; if (!MatrixNeighbors.TryGetValue(matid_this, out matid_neighbor)) { continue; } double A_diag = -1e-6; // small value to use Cholesky decomposition Action <int> CheckNeighbor = (id) => { int matid_next = matid_neighbor[id]; if (matid_next != -1) { A_diag += -1.0; C_dist.At(matid_this, matid_next, -1.0); } }; CheckNeighbor(0); CheckNeighbor(1); CheckNeighbor(2); CheckNeighbor(3); C_dist.At(matid_this, matid_this, -A_diag); } var A_dist = Converter.ToCompressedColumnStorage(C_dist) as SparseMatrix; //////////////////////////////////////////////////////////// // step III-2. build matrix A for heat diffusion //////////////////////////////////////////////////////////// #if USE_3RDPARTY solver_dist = new SuperLU(A_dist); var options = solver_dist.Options; options.SymmetricMode = true; solver_dist.Factorize(); #else solver_dist = SparseCholesky.Create(A_dist, ColumnOrdering.MinimumDegreeAtPlusA); #endif }
void PrecomputeHeatMatrix2D(double dt) { int N = area_cnt; //////////////////////////////////////////////////////////// // step I-1. build matrix A for heat diffusion //////////////////////////////////////////////////////////// var C_heat = new CoordinateStorage <double>(N, N, 5 * N); // banded matrix without exception for (int matid_this = 0; matid_this < N; matid_this++) { List <int> matid_neighbor; if (!MatrixNeighbors.TryGetValue(matid_this, out matid_neighbor)) { continue; } if (matid_neighbor[0] != -1) { C_heat.At(matid_this, matid_neighbor[0], -1.0 * dt); } if (matid_neighbor[1] != -1) { C_heat.At(matid_this, matid_neighbor[1], -1.0 * dt); } if (matid_neighbor[2] != -1) { C_heat.At(matid_this, matid_neighbor[2], -1.0 * dt); } if (matid_neighbor[3] != -1) { C_heat.At(matid_this, matid_neighbor[3], -1.0 * dt); } C_heat.At(matid_this, matid_this, 1.0 + 4.0 * dt); } var A_heat = Converter.ToCompressedColumnStorage(C_heat) as SparseMatrix; //////////////////////////////////////////////////////////// // step I-2. build matrix A for heat diffusion //////////////////////////////////////////////////////////// #if USE_3RDPARTY solver_heat = new SuperLU(A_heat); var options = solver_heat.Options; options.SymmetricMode = true; solver_heat.Factorize(); #else solver_heat = SparseCholesky.Create(A_heat, ColumnOrdering.MinimumDegreeAtPlusA); #endif }
/// <summary> /// Performs the Cholesky factorization: A = L * L^T of a symmetric positive definite matrix A. /// Only the upper triangle of the original matrix is required and is provided in symmetric CSC format by /// <paramref name="cscValues"/>, <paramref name="cscRowIndices"/> and <paramref name="cscColOffsets"/>. /// </summary> /// <param name="order">The number of rows/columns of the square matrix.</param> /// <param name="numNonZerosUpper">The number of explicitly stored entries in the upper triangle of the matrix.</param> /// <param name="cscValues"> /// Contains the non-zero entries of the upper triangle. Its length must be equal to <paramref name="numNonZerosUpper"/>. /// The non-zero entries of each row must appear consecutively in <paramref name="cscValues"/>. They should also be /// sorted in increasing order of their row indices, to speed up subsequent the factorization. /// </param> /// <param name="cscRowIndices"> /// Contains the row indices of the non-zero entries. Its length must be equal to <paramref name="numNonZerosUpper"/>. /// There is an 1 to 1 matching between these two arrays: <paramref name="cscRowIndices"/>[i] is the row index of the /// entry <paramref name="cscValues"/>[i]. Also: 0 <= <paramref name="cscRowIndices"/>[i] < /// <paramref name="order"/>. /// </param> /// <param name="cscColOffsets"> /// Contains the index of the first entry of each column into the arrays <paramref name="cscValues"/> and /// <paramref name="cscRowIndices"/>. Its length must be <paramref name="order"/> + 1. The last entry must be /// <paramref name="numNonZerosUpper"/>. /// </param> /// <exception cref="IndefiniteMatrixException">Thrown if the original matrix is not positive definite.</exception> public static CholeskyCSparseNet Factorize(int order, int numNonZerosUpper, double[] cscValues, int[] cscRowIndices, int[] cscColOffsets) { try { var matrixCSparse = new SparseMatrix(order, order, cscValues, cscRowIndices, cscColOffsets); var factorization = SparseCholesky.Create(matrixCSparse, ColumnOrdering.Natural); return(new CholeskyCSparseNet(order, factorization)); } catch (Exception ex) //TODO: how can I make sure this exception was thrown because of an indefinite matrix? { throw new IndefiniteMatrixException(ex.Message); } }
public void TestSolve() { // Load matrix from a file. var A = ResourceLoader.Get <double>("symmetric-40-spd.mat"); // Create test data. var x = Helper.CreateTestVector(A.ColumnCount); var b = Helper.Multiply(A, x); var r = Vector.Clone(b); var chol = SparseCholesky.Create(A, ColumnOrdering.MinimumDegreeAtPlusA); // Solve Ax = b. chol.Solve(b, x); // Compute residual r = b - Ax. A.Multiply(-1.0, x, 1.0, r); Assert.IsTrue(Vector.Norm(r.Length, r) < EPS); }
private static void TestNormalEquationsSolution() { // Load a regtangular matrix from a file. string filePath = null; var A = MatrixMarketReader.ReadMatrix <double>(filePath); int m = A.RowCount; int n = A.ColumnCount; // Create test data. var x = CSparse.Double.Vector.Create(n, 1.0); var b = new double[m]; // Compute right hand side vector b. A.Multiply(1.0, x, 0.0, b); // Apply column ordering to A to reduce fill-in. var order = ColumnOrdering.MinimumDegreeAtPlusA; if (m > n) { var At = A.Transpose(); var AtA = At.Multiply(A); var c = CSparse.Double.Vector.Create(n, 0.0); At.Multiply(b, c); var chol = SparseCholesky.Create(AtA, order); // Solve normal equation A'Ax = A'b (overwrite x). chol.Solve(c, x); } else { Assert.True(false); } // Compute residual b - Ax (overwrite b). A.Multiply(-1.0, x, 1.0, b); }
public static void TestLinearSystemSolution() { // Load matrix from a file. var A = MatrixMarketReader.ReadMatrix <double>(PosDefMatrixPath); int m = A.RowCount; int n = A.ColumnCount; Assert.True(m == n); // Create test data. var xExpected = CSparse.Double.Vector.Create(n, 1.0); var b = new double[m]; // Compute right hand side vector b. A.Multiply(1.0, xExpected, 0.0, b); // Apply column ordering to A to reduce fill-in. var order = ColumnOrdering.MinimumDegreeAtPlusA; // Factorize var xComputed = new double[n]; var chol = SparseCholesky.Create(A, order); // Solve Ax = b (do not overwrite x). chol.Solve(b, xComputed); // Check the solution comparer.AssertEqual(xExpected, xComputed); // Compute residual b - Ax (do not overwrite b). var r = new double[m]; Array.Copy(b, r, m); A.Multiply(-1.0, xComputed, 1.0, r); }
private CholeskyCSparseNet(int order, SparseCholesky factorization) { this.Order = order; this.factorization = factorization; }
protected override void Solve() { InitNeuronCell(); int nT; // Number of Time steps List <bool> channels = new List <bool>(); if (HK_auto) { h = 0.1 * NeuronCell.edgeLengths.Average(); if (h > 0.29) { h = 0.29; } if (h <= 1) { k = h / 100; } // For cell 13_0ref if (h <= 0.15) { k = h / 50; } // For cell 13_1ref if (h <= 0.08) { k = h / 25; } // For cell 13_2ref if (h <= 0.04) { k = h / 12.5; } // For cell 13_3ref if (h <= 0.02) { k = h / 5.5; } // For cell 13_4ref } if (use_Ck) { k = Ck * h; } // for timing data DateTime start; DateTime end; DateTime now = DateTime.Now; TimeSpan tspan; // setup up paths for writing output string strPath = Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory); string subPath = strPath + @"\VR_Simulations"; bool exists = System.IO.Directory.Exists(subPath); // check if directory exists if (!exists) { System.IO.Directory.CreateDirectory(subPath); } // set the path for writing strPath = subPath; DirectoryInfo di = Directory.CreateDirectory(strPath + @"\SimulationRun" + "_" + now.Hour + "_" + now.Minute + "_" + now.Second); strPath = strPath + @"\SimulationRun" + "_" + now.Hour + "_" + now.Minute + "_" + now.Second; // Number of time steps nT = (int)System.Math.Floor(endTime / k); Timer timer = new Timer(nT + 1); timer.StartTimer(); // set some constants for the HINES matrix double diffConst = (1 / (2 * res * cap)); double cfl = diffConst * k / h; // pre-allocate 2d arrays, not jagged, maybe incorporate jagged arrays later? double[,] rhsMarray = new double[NeuronCell.vertCount, NeuronCell.vertCount]; double[,] lhsMarray = new double[NeuronCell.vertCount, NeuronCell.vertCount]; // reaction vector Vector R = Vector.Build.Dense(NeuronCell.vertCount); List <double> reactConst = new List <double> { gk, gna, gl, ek, ena, el }; // temporary voltage vector Vector tempV = Vector.Build.Dense(NeuronCell.vertCount); // Make the system stencil matrices for diffusion solve List <double[, ]> stencils = makeStencils(NeuronCell, h, k, diffConst); rhsMarray = stencils[0]; lhsMarray = stencils[1]; // Write rhsM and lhsM to file if (printMatrices) { printMatrix(rhsMarray, lhsMarray, strPath, now); } // for allocation of the sparse matrices CompressedColumnStorage <double> r_csc = null; CompressedColumnStorage <double> l_csc = null; // makes the rhs, lhs in sparse format r_csc = Converter.ToCompressedColumnStorage(Converter.FromDenseArray(rhsMarray)); l_csc = Converter.ToCompressedColumnStorage(Converter.FromDenseArray(lhsMarray)); // for solving Ax = b problem double[] b = new double[NeuronCell.vertCount]; // Apply column ordering to A to reduce fill-in. var order = ColumnOrdering.MinimumDegreeAtPlusA; // Create Cholesky factorization start = DateTime.Now; var chl = SparseCholesky.Create(l_csc, order); end = DateTime.Now; // Print cell info to a text file if (printCellInfo) { printCell(NeuronCell, h, k, nT, endTime, cfl, strPath, now, start, end); } // Write diffusion times to a file var timeWrite = new StreamWriter(strPath + @"\diffusion_times_chl_" + now.Hour + "_" + now.Minute + "_" + now.Second + ".txt", true); var sw = new StreamWriter(strPath + @"\outputVoltage_" + now.Hour + "_" + now.Minute + "_" + now.Second + ".txt", true); var tw = new StreamWriter(strPath + @"\timesteps_" + now.Hour + "_" + now.Minute + "_" + now.Second + ".txt", true); try { for (i = 0; i < nT; i++) { if (SomaOn) { U.SetSubVector(0, NeuronCell.vertCount, setSoma(U, NeuronCell.somaID, vstart)); } timer.StartTimer(); mutex.WaitOne(); start = DateTime.Now; r_csc.Multiply(U.ToArray(), b); // Peform b = rhs * U_curr chl.Solve(b, b); b = maxCheck(b); end = DateTime.Now; tspan = end - start; // get time span to write timeWrite.WriteLine(tspan.TotalMilliseconds + Environment.NewLine); // write diffusion time to file // Set U_next = b U.SetSubVector(0, NeuronCell.vertCount, Vector.Build.DenseOfArray(b)); // Save voltage from diffusion step for state probabilities tempV.SetSubVector(0, NeuronCell.vertCount, U); // Reaction channels.Add(k_ONOFF); channels.Add(na_ONOFF); channels.Add(leak_ONOFF); R.SetSubVector(0, NeuronCell.vertCount, reactF(reactConst, U, N, M, H, channels, NeuronCell.boundaryID)); R.Multiply(k / cap, R); // This is the solution for the voltage after the reaction is included! U.Add(R, U); //Now update state variables using FE on M,N,H N.Add(fN(tempV, N).Multiply(k), N); M.Add(fM(tempV, M).Multiply(k), M); H.Add(fH(tempV, H).Multiply(k), H); //Always reset to IC conditions and boundary conditions (for now) U.SetSubVector(0, NeuronCell.vertCount, boundaryConditions(U, NeuronCell.boundaryID)); if (SomaOn) { U.SetSubVector(0, NeuronCell.vertCount, setSoma(U, NeuronCell.somaID, vstart)); } if (printVolt_time) { for (int j = 0; j < NeuronCell.vertCount; j++) { sw.Write(U[j] + " "); } sw.Write("\n"); tw.Write((k * (double)i) + " "); tw.Write("\n"); } mutex.ReleaseMutex(); timer.StopTimer(i.ToString()); } timeWrite.Close(); sw.Close(); tw.Close(); } catch (Exception e) { GameManager.instance.DebugLogThreadSafe(e); } GameManager.instance.DebugLogSafe("Simulation Over."); }
public void BuildFrom(MeshAdjacency meshAdjacency, int[] constraintIndices) { vertexCount = meshAdjacency.vertexCount; this.constraintIndices = constraintIndices.Clone() as int[]; this.constraintWeight = 1.0; // count unconstrained laplacian non-zero fields int nzmax = vertexCount; for (int i = 0; i != vertexCount; i++) { nzmax += meshAdjacency.vertexVertices.lists[i].size; } // build Ls EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build Ls", 0.0f); var Ls_storage = new CoordinateStorage <double>(vertexCount, vertexCount, nzmax); for (int i = 0; i != vertexCount; i++) // D { //TODO proper fix //Ls_storage.At(i, i, meshAdjacency.vertexVertices.lists[i].size); Ls_storage.At(i, i, Mathf.Max(1, meshAdjacency.vertexVertices.lists[i].size)); } for (int i = 0; i != vertexCount; i++) // A { foreach (var j in meshAdjacency.vertexVertices[i]) { Ls_storage.At(i, j, -1.0); } } Ls = Converter.ToCompressedColumnStorage(Ls_storage) as SparseMatrix; // build Lc EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build Lc", 0.0f); var Lc_storage = new CoordinateStorage <double>(vertexCount + constraintIndices.Length, vertexCount, nzmax + constraintIndices.Length); for (int i = 0; i != vertexCount; i++) { //TODO proper fix //Lc_storage.At(i, i, meshAdjacency.vertexVertices.lists[i].size); Lc_storage.At(i, i, Mathf.Max(1, meshAdjacency.vertexVertices.lists[i].size)); } for (int i = 0; i != vertexCount; i++) { foreach (var j in meshAdjacency.vertexVertices[i]) { Lc_storage.At(i, j, -1.0); } } for (int i = 0; i != constraintIndices.Length; i++) { Lc_storage.At(vertexCount + i, constraintIndices[i], constraintWeight); } Lc = Converter.ToCompressedColumnStorage(Lc_storage) as SparseMatrix; // build LcT EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build LcT", 0.0f); LcT = Lc.Transpose() as SparseMatrix; // build LcT_Lc EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build LcT_Lc", 0.0f); LcT_Lc = LcT.Multiply(Lc) as SparseMatrix; // build LcT_Lc_chol EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build LcT_Lc_chol", 0.0f); LcT_Lc_chol = SparseCholesky.Create(LcT_Lc, ColumnOrdering.MinimumDegreeAtPlusA); // done EditorUtilityProxy.ClearProgressBar(); }
public void BuildFrom(MeshAdjacency meshAdjacency, int[] roiIndices, int roiBoundaryLevels, int[] roiConstraintIndices = null) { unsafe { using (var visited = new UnsafeArrayBool(meshAdjacency.vertexCount)) using (var visitedBoundary = new UnsafeArrayBool(meshAdjacency.vertexCount)) using (var visitor = new UnsafeBFS(meshAdjacency.vertexCount)) { // find boundary visited.Clear(false); visitedBoundary.Clear(false); visitor.Clear(); int visitedCount = 0; int visitedBoundaryCount = 0; foreach (int i in roiIndices) { visited.val[i] = true; visitedCount++; visitor.Ignore(i); } foreach (int i in roiIndices) { foreach (var j in meshAdjacency.vertexVertices[i]) { visitor.Insert(j); } } // step boundary while (visitor.MoveNext()) { int i = visitor.position; visited.val[i] = true; visitedCount++; visitedBoundary.val[i] = true; visitedBoundaryCount++; if (visitor.depth < roiBoundaryLevels) { foreach (var j in meshAdjacency.vertexVertices[i]) { visitor.Insert(j); } } } // add constraints if (roiConstraintIndices != null) { foreach (int i in roiConstraintIndices) { if (visited.val[i]) { if (visitedBoundary.val[i] == false) { visitedBoundary.val[i] = true; visitedBoundaryCount++; } } else { Debug.LogWarning("ignoring user constraint outside ROI: vertex " + i); } } } // build translations internalCount = 0; externalCount = meshAdjacency.vertexCount; internalFromExternal = new int[externalCount]; externalFromInternal = new int[visitedCount]; for (int i = 0; i != meshAdjacency.vertexCount; i++) { if (visited.val[i]) { int internalIndex = internalCount++; externalFromInternal[internalIndex] = i; internalFromExternal[i] = internalIndex; } else { internalFromExternal[i] = -1; } } // find constraint indices constraintIndices = new int[visitedBoundaryCount]; constraintWeight = 1.0; int constraintCount = 0; for (int i = 0; i != internalCount; i++) { if (visitedBoundary.val[externalFromInternal[i]]) { constraintIndices[constraintCount++] = i; } } // count unconstrained laplacian non-zero fields int nzmax = internalCount; for (int i = 0; i != internalCount; i++) { nzmax += InternalValence(meshAdjacency, i); } // build Ls EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build Ls", 0.0f); var Ls_storage = new CoordinateStorage <double>(internalCount, internalCount, nzmax); for (int i = 0; i != internalCount; i++) // D { //TODO proper fix //Ls_storage.At(i, i, InternalValence(meshAdjacency, i)); Ls_storage.At(i, i, Mathf.Max(1, InternalValence(meshAdjacency, i))); } for (int i = 0; i != internalCount; i++) // A { foreach (var k in meshAdjacency.vertexVertices[externalFromInternal[i]]) { int j = internalFromExternal[k]; if (j != -1) { Ls_storage.At(i, j, -1.0); } } } Ls = Converter.ToCompressedColumnStorage(Ls_storage) as SparseMatrix; // build Lc EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build Lc", 0.0f); var Lc_storage = new CoordinateStorage <double>(internalCount + constraintCount, internalCount, nzmax + constraintCount); for (int i = 0; i != internalCount; i++) { //TODO proper fix //Lc_storage.At(i, i, InternalValence(meshAdjacency, i)); Lc_storage.At(i, i, Mathf.Max(1, InternalValence(meshAdjacency, i))); } for (int i = 0; i != internalCount; i++) { foreach (var k in meshAdjacency.vertexVertices[externalFromInternal[i]]) { int j = internalFromExternal[k]; if (j != -1) { Lc_storage.At(i, j, -1.0); } } } for (int i = 0; i != constraintIndices.Length; i++) { Lc_storage.At(internalCount + i, constraintIndices[i], constraintWeight); } Lc = Converter.ToCompressedColumnStorage(Lc_storage) as SparseMatrix; // build LcT EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build LcT", 0.0f); LcT = Lc.Transpose() as SparseMatrix; // build LcT_Lc EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build LcT_Lc", 0.0f); LcT_Lc = LcT.Multiply(Lc) as SparseMatrix; // build LcT_Lc_chol EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build LcT_Lc_chol", 0.0f); LcT_Lc_chol = SparseCholesky.Create(LcT_Lc, ColumnOrdering.MinimumDegreeAtPlusA); // done EditorUtilityProxy.ClearProgressBar(); } } }
protected override void Solve() { InitializeNeuronCell(); for (int kSim = 0; kSim <= numRuns; kSim++) { int nT; // Number of Time steps List <bool> channels = new List <bool> { false, false, false }; // For adding/removing channels // TODO: NEED TO DO THIS BETTER if (HK_auto) { h = 0.1 * NeuronCell.edgeLengths.Average(); if (h > 0.29) { h = 0.29; } if (h <= 1) { k = h / 100; } // For cell 13_0ref if (h <= 0.15) { k = h / 50; } // For cell 13_1ref if (h <= 0.08) { k = h / 25; } // For cell 13_2ref if (h <= 0.04) { k = h / 12.5; } // For cell 13_3ref if (h <= 0.02) { k = h / 5.5; } // For cell 13_4ref } // for timing data DateTime now = DateTime.Now; // setup up paths for writing output string strPath = Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory); string subPath = strPath + @"\VR_Simulations"; bool exists = System.IO.Directory.Exists(subPath); // check if directory exists if (!exists) { System.IO.Directory.CreateDirectory(subPath); } // set the path for writing strPath = subPath; DirectoryInfo di = Directory.CreateDirectory(strPath + @"\SimulationRun" + "_" + kSim); strPath = strPath + @"\SimulationRun" + "_" + kSim; // Number of time steps nT = (int)System.Math.Floor(endTime / k); // set some constants for the HINES matrix double diffConst = (1 / (2 * res * cap)); double cfl = diffConst * k / h; //TODO: JAMES GET RID OF ARRAYS GO STRAIGHT FOR SPARSE ALLOCATION, THIS IS SILLY! --> QUEISSER/SEIBOLD! // pre-allocate 2d arrays, not jagged, maybe incorporate jagged arrays later? --> NO! double[,] rhsMarray = new double[NeuronCell.vertCount, NeuronCell.vertCount]; double[,] lhsMarray = new double[NeuronCell.vertCount, NeuronCell.vertCount]; // reaction vector Vector R = Vector.Build.Dense(NeuronCell.vertCount); List <double> reactConst = new List <double> { gk, gna, gl, ek, ena, el }; // temporary voltage vector Vector tempV = Vector.Build.Dense(NeuronCell.vertCount); // TODO: turn make stencils function to use sparse allocation!! --> QUEISSER/SEIBOLD! // Make the system stencil matrices for diffusion solve List <double[, ]> stencils = makeStencils(NeuronCell, h, k, diffConst); rhsMarray = stencils[0]; lhsMarray = stencils[1]; // Write rhsM and lhsM to file if (printMatrices) { printMatrix(rhsMarray, lhsMarray, strPath, kSim); } // for allocation of the sparse matrices CompressedColumnStorage <double> r_csc = null; CompressedColumnStorage <double> l_csc = null; // makes the rhs, lhs in sparse format r_csc = Converter.ToCompressedColumnStorage(Converter.FromDenseArray(rhsMarray)); l_csc = Converter.ToCompressedColumnStorage(Converter.FromDenseArray(lhsMarray)); // for solving Ax = b problem double[] b = new double[NeuronCell.vertCount]; // TODO: UNDERSTAND WHAT THIS IS DOING! --> QUEISSER/SEIBOLD! // Apply column ordering to A to reduce fill-in. var order = ColumnOrdering.MinimumDegreeAtPlusA; // TODO: GO INTO Source code and print the L matrix // Time the reordering steps? --> Ask Queisser again about this! // Create Cholesky factorization setup Timer timer = new Timer(1); timer.StartTimer(); var chl = SparseCholesky.Create(l_csc, order); timer.StopTimer("MatSetup t= "); timer.ExportCSV("matrixSetup"); // Print cell info to a text file if (printCellInfo) { printCell(NeuronCell, h, k, nT, endTime, cfl, strPath, kSim); } // For printing voltage data and time steps var sw = new StreamWriter(strPath + @"\outputVoltage_" + kSim + ".txt", true); var tw = new StreamWriter(strPath + @"\timesteps_" + kSim + ".txt", true); timer = new Timer(nT); try { for (i = 0; i < nT; i++) { if (SomaOn) { U.SetSubVector(0, NeuronCell.vertCount, setSoma(U, NeuronCell.somaID, vstart)); } mutex.WaitOne(); r_csc.Multiply(U.ToArray(), b); // Peform b = rhs * U_curr // Diffusion solver timer.StartTimer(); chl.Solve(b, b); timer.StopTimer(i.ToString()); // Set U_next = b U.SetSubVector(0, NeuronCell.vertCount, Vector.Build.DenseOfArray(b)); // Save voltage from diffusion step for state probabilities tempV.SetSubVector(0, NeuronCell.vertCount, U); // Reaction channels[0] = na_ONOFF; channels[1] = k_ONOFF; channels[2] = leak_ONOFF; R.SetSubVector(0, NeuronCell.vertCount, reactF(reactConst, U, N, M, H, channels, NeuronCell.boundaryID)); R.Multiply(k / cap, R); // This is the solution for the voltage after the reaction is included! U.Add(R, U); //Now update state variables using FE on M,N,H N.Add(fN(tempV, N).Multiply(k), N); M.Add(fM(tempV, M).Multiply(k), M); H.Add(fH(tempV, H).Multiply(k), H); //Always reset to IC conditions and boundary conditions (for now) U.SetSubVector(0, NeuronCell.vertCount, boundaryConditions(U, NeuronCell.boundaryID)); if (SomaOn) { U.SetSubVector(0, NeuronCell.vertCount, setSoma(U, NeuronCell.somaID, vstart)); } if (printVolt_time) { for (int j = 0; j < NeuronCell.vertCount; j++) { sw.Write(U[j] + " "); } sw.Write("\n"); tw.Write((k * (double)i) + " "); tw.Write("\n"); } mutex.ReleaseMutex(); } sw.Close(); tw.Close(); } catch (Exception e) { GameManager.instance.DebugLogThreadSafe(e); } finally { timer.ExportCSV("diffusionTimes"); sw.Close(); tw.Close(); } GameManager.instance.DebugLogSafe("Simulation Over."); } }
protected override void Solve() { InitNeuronCell(); //if (SomaOn) { U.SetSubVector(0, myCell.vertCount, setSoma(U, myCell.somaID, vstart)); } int nT; // Number of Time steps List <bool> channels = new List <bool> { false, false, false }; // For adding/removing channels // TODO: NEED TO DO THIS BETTER if (HK_auto) { h = 0.1 * NeuronCell.edgeLengths.Average(); //if (h > 0.29) { h = 0.29; } if (h <= 1) { k = h / 140; } if (h <= 0.5) { k = h / 70; } if (h <= 0.25) { k = h / 35; } if (h <= 0.12) { k = h / 18; } if (h <= 0.06) { k = h / 9; } if (h <= 0.03) { k = h / 5; } } // Number of time steps nT = (int)System.Math.Floor(endTime / k); // set some constants for the HINES matrix double diffConst = (1 / (2 * res * cap)); double cfl = diffConst * k / h; // reaction vector Vector R = Vector.Build.Dense(NeuronCell.vertCount); List <double> reactConst = new List <double> { gk, gna, gl, ek, ena, el }; // temporary voltage vector Vector tempV = Vector.Build.Dense(NeuronCell.vertCount); // Construct sparse RHS and LHS in coordinate storage format, no zeros are stored List <CoordinateStorage <double> > sparse_stencils = makeSparseStencils(NeuronCell, h, k, diffConst); // Compress the sparse matrices CompressedColumnStorage <double> r_csc = CompressedColumnStorage <double> .OfIndexed(sparse_stencils[0]); //null; CompressedColumnStorage <double> l_csc = CompressedColumnStorage <double> .OfIndexed(sparse_stencils[1]); //null; // Permutation matrix----------------------------------------------------------------------// int[] p = new int[NeuronCell.vertCount]; p = Permutation.Create(NeuronCell.vertCount, 0); CompressedColumnStorage <double> Id_csc = CompressedColumnStorage <double> .CreateDiagonal(NeuronCell.vertCount, 1); Id_csc.PermuteRows(p); //--------------------------------------------------------------------------------------------// // for solving Ax = b problem double[] b = new double[NeuronCell.vertCount]; // Apply column ordering to A to reduce fill-in. //var order = ColumnOrdering.MinimumDegreeAtPlusA; // Create Cholesky factorization setup var chl = SparseCholesky.Create(l_csc, p); //var chl = SparseCholesky.Create(l_csc, order); try { for (i = 0; i < nT; i++) { if (SomaOn) { U.SetSubVector(0, NeuronCell.vertCount, setSoma(U, NeuronCell.somaID, vstart)); } mutex.WaitOne(); r_csc.Multiply(U.ToArray(), b); // Peform b = rhs * U_curr // Diffusion solver chl.Solve(b, b); // Set U_next = b U.SetSubVector(0, NeuronCell.vertCount, Vector.Build.DenseOfArray(b)); // Save voltage from diffusion step for state probabilities tempV.SetSubVector(0, NeuronCell.vertCount, U); // Reaction channels[0] = na_ONOFF; channels[1] = k_ONOFF; channels[2] = leak_ONOFF; R.SetSubVector(0, NeuronCell.vertCount, reactF(reactConst, U, N, M, H, channels, NeuronCell.boundaryID)); R.Multiply(k / cap, R); // This is the solution for the voltage after the reaction is included! U.Add(R, U); //Now update state variables using FE on M,N,H N.Add(fN(tempV, N).Multiply(k), N); M.Add(fM(tempV, M).Multiply(k), M); H.Add(fH(tempV, H).Multiply(k), H); //Always reset to IC conditions and boundary conditions (for now) U.SetSubVector(0, NeuronCell.vertCount, boundaryConditions(U, NeuronCell.boundaryID)); if (SomaOn) { U.SetSubVector(0, NeuronCell.vertCount, setSoma(U, NeuronCell.somaID, vstart)); } mutex.ReleaseMutex(); } } catch (Exception e) { GameManager.instance.DebugLogThreadSafe(e); } GameManager.instance.DebugLogSafe("Simulation Over."); }
public DisposableSparseCholesky(SparseMatrix matrix) { cholesky = SparseCholesky.Create(matrix, ColumnOrdering.MinimumDegreeAtPlusA); }
protected override void Solve() { InitNeuronCell(); for (int kSim = 0; kSim <= numRuns; kSim++) { //if (SomaOn) { U.SetSubVector(0, myCell.vertCount, setSoma(U, myCell.somaID, vstart)); } int nT; // Number of Time steps List <bool> channels = new List <bool> { false, false, false }; // For adding/removing channels // TODO: NEED TO DO THIS BETTER if (HK_auto) { h = 0.1 * NeuronCell.edgeLengths.Average(); //if (h > 0.29) { h = 0.29; } if (h <= 1) { k = h / 130; } // 0 refine if (h <= 0.5) { k = h / 65; } // 1 refine if (h <= 0.25) { k = h / 32.5; } // 2 refine if (h <= 0.12) { k = h / 18; } // 3 refine if (h <= 0.06) { k = h / 9; } // 4 refine if (h <= 0.03) { k = h / 5; } } // setup up paths for writing output string strPath = Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory); string subPath = strPath + @"\VR_Simulations"; bool exists = System.IO.Directory.Exists(subPath); // check if directory exists if (!exists) { System.IO.Directory.CreateDirectory(subPath); } // set the path for writing strPath = subPath; DirectoryInfo di = Directory.CreateDirectory(strPath + @"\SimulationRun" + "_" + kSim); strPath = strPath + @"\SimulationRun" + "_" + kSim; // Number of time steps nT = (int)System.Math.Floor(endTime / k); // set some constants for the HINES matrix double diffConst = (1 / (2 * res * cap)); double cfl = diffConst * k / h; // reaction vector Vector R = Vector.Build.Dense(NeuronCell.vertCount); List <double> reactConst = new List <double> { gk, gna, gl, ek, ena, el }; // temporary voltage vector Vector tempV = Vector.Build.Dense(NeuronCell.vertCount); // Construct sparse RHS and LHS in coordinate storage format, no zeros are stored List <CoordinateStorage <double> > sparse_stencils = makeSparseStencils(NeuronCell, h, k, diffConst); // Compress the sparse matrices CompressedColumnStorage <double> r_csc = CompressedColumnStorage <double> .OfIndexed(sparse_stencils[0]); //null; CompressedColumnStorage <double> l_csc = CompressedColumnStorage <double> .OfIndexed(sparse_stencils[1]); //null; // Permutation matrix----------------------------------------------------------------------// int[] p = new int[NeuronCell.vertCount]; if (randomPermute) { p = Permutation.Create(NeuronCell.vertCount, 1); } else { p = Permutation.Create(NeuronCell.vertCount, 0); } CompressedColumnStorage <double> Id_csc = CompressedColumnStorage <double> .CreateDiagonal(NeuronCell.vertCount, 1); Id_csc.PermuteRows(p); //--------------------------------------------------------------------------------------------// // for solving Ax = b problem double[] b = new double[NeuronCell.vertCount]; // Apply column ordering to A to reduce fill-in. //var order = ColumnOrdering.MinimumDegreeAtPlusA; // Create Cholesky factorization setup Timer timer = new Timer(); timer.StartTimer(); var chl = SparseCholesky.Create(l_csc, p); //var chl = SparseCholesky.Create(l_csc, order); timer.StopTimer("Matrix Setup"); timer.ExportCSV_path(strPath + @"\chlSetup_" + kSim); // Write permutation, rhsM, lhsM, and choleskyR matrix to file if (printMatrices) { printMatrix(Id_csc, r_csc, l_csc, chl.L, strPath, kSim); } // Print cell info to a text file if (printCellInfo) { printCell(NeuronCell, h, k, nT, endTime, cfl, strPath, kSim); } // For printing voltage data and time steps var sw = new StreamWriter(strPath + @"\outputVoltage_" + kSim + ".txt", true); var tw = new StreamWriter(strPath + @"\timesteps_" + kSim + ".txt", true); timer = new Timer(nT); try { for (i = 0; i < nT; i++) { if (SomaOn) { U.SetSubVector(0, NeuronCell.vertCount, setSoma(U, NeuronCell.somaID, vstart)); } mutex.WaitOne(); r_csc.Multiply(U.ToArray(), b); // Peform b = rhs * U_curr // Diffusion solver timer.StartTimer(); chl.Solve(b, b); timer.StopTimer(i.ToString()); // Set U_next = b U.SetSubVector(0, NeuronCell.vertCount, Vector.Build.DenseOfArray(b)); // Save voltage from diffusion step for state probabilities tempV.SetSubVector(0, NeuronCell.vertCount, U); // Reaction channels[0] = na_ONOFF; channels[1] = k_ONOFF; channels[2] = leak_ONOFF; R.SetSubVector(0, NeuronCell.vertCount, reactF(reactConst, U, N, M, H, channels, NeuronCell.boundaryID)); R.Multiply(k / cap, R); // This is the solution for the voltage after the reaction is included! U.Add(R, U); //Now update state variables using FE on M,N,H N.Add(fN(tempV, N).Multiply(k), N); M.Add(fM(tempV, M).Multiply(k), M); H.Add(fH(tempV, H).Multiply(k), H); //Always reset to IC conditions and boundary conditions (for now) U.SetSubVector(0, NeuronCell.vertCount, boundaryConditions(U, NeuronCell.boundaryID)); if (SomaOn) { U.SetSubVector(0, NeuronCell.vertCount, setSoma(U, NeuronCell.somaID, vstart)); } if (printVolt_time) { for (int j = 0; j < NeuronCell.vertCount; j++) { sw.Write(U[j] + " "); } sw.Write("\n"); tw.Write((k * (double)i) + " "); tw.Write("\n"); } mutex.ReleaseMutex(); } sw.Close(); tw.Close(); } catch (Exception e) { GameManager.instance.DebugLogThreadSafe(e); } finally { timer.ExportCSV_path(strPath + @"\diffusionTimes_" + kSim); sw.Close(); tw.Close(); } GameManager.instance.DebugLogSafe("Simulation Over."); } }