Exemplo n.º 1
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.");
        }
Exemplo n.º 2
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.");
            }
        }