예제 #1
0
        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)));
            }
        }
예제 #3
0
        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);
        }
예제 #4
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);
            });
        }
예제 #5
0
    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
    }
예제 #6
0
    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 &lt;= <paramref name="cscRowIndices"/>[i] &lt;
 /// <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);
     }
 }
예제 #8
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
 private CholeskyCSparseNet(int order, SparseCholesky factorization)
 {
     this.Order         = order;
     this.factorization = factorization;
 }
예제 #12
0
        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();
                        }
            }
        }
예제 #15
0
        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.");
            }
        }
예제 #16
0
        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.");
        }
예제 #17
0
 public DisposableSparseCholesky(SparseMatrix matrix)
 {
     cholesky = SparseCholesky.Create(matrix, ColumnOrdering.MinimumDegreeAtPlusA);
 }
예제 #18
0
        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.");
            }
        }