Example #1
0
 /// <summary>
 /// This is the main solver, it is running on it own thread.
 /// Inside this solver it
 /// 1. initialize the stencil matrix (only once) for the diffusion solve of the operator splitting
 /// 2. there is a for-loop which is controled by <c>i</c>
 /// 3. Inside the for-loop we do the diffusion solve first, then reaction solve, and then updated the state ODEs
 /// We make the following definitions: \n
 ///\f[A(V):=\frac{a}{2RC}\frac{\partial ^ 2V}{\partial x^2}\f] \n
 ///\f[r(V):= -\frac{\bar{ g} _{ K} }{ C}n ^ 4(V - V_k) -\frac{\bar{ g} _{ Na} }{ C}m ^ 3h(V - V_{ Na})-\frac{\bar{ g} _l}{ C} (V - V_l)\f] \n
 /// then we solve in two separate steps \n
 ///\f[\frac{dV}{dt}=A(V)+r(V),\f] \n
 /// where \f$A(V)\f$ is the second order differential operator on \f$V\f$ and \f$r(V)\f$ is the reaction part.
 /// We employ a Lie Splitting by first solving \n
 /// \f[\frac{ dV ^ *}{ dt}= A(V ^ *)\f] \n
 /// with initial conditions \f$V_0^*=V(t_n)= V_n\f$ at the beginning of the time step to get the intermediate solution \f$V^*\f$
 /// Then we solve \f$\frac{dV^{**}}{dt}=r(V^{**})\f$ with initial condition \f$V_0^{**}=V^*\f$ to get \f$V^{**}\f$, and \f$V_{n+1}=V(t_{n+1})=V^{**}\f$ the voltage at the end of the time step.
 /// For equation the diffusion we use a Crank-Nicolson scheme
 /// </summary>
 ///
 //tex:
 //$$A(V):=\frac{a}{2RC}\frac{\partial ^ 2V}{\partial x^2}$$
 //$$r(V):= -\frac{\bar{ g} _{ K} }{ C}n ^ 4(V - V_k) -\frac{\bar{ g} _{ Na} }{ C}m ^ 3h(V - V_{ Na})-\frac{\bar{ g} _l}{ C} (V - V_l)$$
 // then we solve in two separate steps
 //$$\frac{dV}{dt}=A(V)+r(V),$$
 //where $A(V)$ is the second order differential operator on $V$ and $r(V)$ is the reaction term on $V$. We employ a Lie Splitting by first solving
 //$$\frac{ dV ^ *}{ dt}= A(V ^ *)$$
 //with initial condition $V_0^*=V(t_n)= V_n$ at the beginning of the time step to get the intermediate solution $V^*$. Then we solve
 //$\frac{dV^{**}}{dt}=r(V^{**})$ with initial condition $V_0^{**}=V^*$ to get $V^{**}$, and $V_{n+1}=V(t_{n+1})=V^{**}$ the voltage at the end of the time step.
 //For equation the diffusion we use a Crank-Nicolson scheme
 protected override void SolveStep(int t)
 {
     ///<c>if ((i * k >= 0.015) && SomaOn) { U[0] = vstart; }</c> this checks of the somaclamp is on and sets the soma location to <c>vstart</c>
     ///if ((t * k >= 0.015) && SomaOn) { U[0] = vstart; }
     ///This part does the diffusion solve \n
     /// <c>r_csc.Multiply(U.ToArray(), b);</c> the performs the RHS*Ucurr and stores it in <c>b</c> \n
     /// <c>lu.Solve(b, b);</c> this does the forward/backward substitution of the LU solve and sovles LHS = b \n
     /// <c>U.SetSubVector(0, Neuron.vertCount, Vector.Build.DenseOfArray(b));</c> this sets the U vector to the voltage at the end of the diffusion solve
     r_csc.Multiply(U.ToArray(), b);
     lu.Solve(b, b);
     U.SetSubVector(0, Neuron.nodes.Count, Vector.Build.DenseOfArray(b));
     /// this part solves the reaction portion of the operator splitting \n
     /// <c>R.SetSubVector(0, Neuron.vertCount, reactF(reactConst, U, N, M, H, cap));</c> this first evaluates at the reaction function \f$r(V)\f$ \n
     /// <c>R.Multiply(k, R); </c> this multiplies by the time step size \n
     /// <c>U.add(R,U)</c> adds it back to U to finish off the operator splitting
     /// For the reaction solve we are solving
     /// \f[\frac{U_{next}-U_{curr}}{k} = R(U_{curr})\f]
     R.SetSubVector(0, Neuron.nodes.Count, reactF(reactConst, U, N, M, H, cap));
     R.Multiply(timeStep, R);
     U.Add(R, U);
     /// this part solve the state variables using Forward Euler
     /// the general rule is \f$N_{next} = N_{curr}+k\cdot f_N(U_{curr},N_{curr})\f$
     N.Add(fN(U, N).Multiply(timeStep), N);
     M.Add(fM(U, M).Multiply(timeStep), M);
     H.Add(fH(U, H).Multiply(timeStep), H);
     ///<c>if ((i * k >= 0.015) && SomaOn) { U[0] = vstart; }</c> this checks of the somaclamp is on and sets the soma location to <c>vstart</c>
     ///if ((t * k >= 0.015) && SomaOn) { U[0] = vstart; }
 }
Example #2
0
        public static double[] Muly(CompressedColumnStorage mtx, double[] vec)
        {
            var buf = new double[mtx.RowCount];

            mtx.Multiply(vec, buf);

            return(buf);
        }
Example #3
0
        public static double ComputeResidual(CompressedColumnStorage <Complex> A, Complex[] x, Complex[] b, bool relativeError = true)
        {
            var e = Vector.Clone(b);

            A.Multiply(-1.0, x, 1.0, e);

            if (relativeError)
            {
                return(Vector.Norm(e) / (A.FrobeniusNorm() * Vector.Norm(b)));
            }

            return(Vector.Norm(e));
        }
Example #4
0
        /// <summary>
        /// Gets the residual of Ax-b.
        /// </summary>
        /// <param name="A">A.</param>
        /// <param name="x">The x.</param>
        /// <param name="b">The b.</param>
        /// <returns></returns>
        public static double GetResidual(CompressedColumnStorage A, double[] x, double[] b)
        {
            var buf = 0.0;

            var n = b.Length;

            var recoveredB = new double[n];

            A.Multiply(x, recoveredB);

            for (var i = 0; i < n; i++)
            {
                recoveredB[i] -= b[i];
            }

            //var norm = recoveredB.GetLargestAbsoluteValue();

            return
                (recoveredB.Average());

            //Norm(recoveredB) / (A.Norm(MatrixNorm.OneNorm) * Norm(x) + Norm(b));

            return(buf);
        }
Example #5
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.");
        }
Example #6
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.");
        }
Example #7
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.");
            }
        }
Example #8
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.");
            }
        }