private SparseLU lu; //Initialize the LU factorizaation /// <summary> /// This is a small routine call to initialize the Neuron Cell /// this will initialize the solution vectors which are <c>U</c>, <c>M</c>, <c>N</c>, and <c>H</c> /// </summary> protected override void PreSolve() { InitializeNeuronCell(); ///<c>R</c> this is the reaction vector for the reaction solve R = Vector.Build.Dense(Neuron.nodes.Count); ///<c>reactConst</c> this is a small list for collecting the conductances and reversal potential which is sent to the reaction solve routine reactConst = new List <double> { gk, gna, gl, ek, ena, el }; /// this sets the target time step size timeStep = SetTargetTimeStep(cap, 2 * Neuron.MaxRadius, Neuron.TargetEdgeLength, gna, gk, res, Rmemscf, cfl); ///UnityEngine.Debug.Log("Target Time Step = " + timeStep); ///<c>List<CoordinateStorage<double>> sparse_stencils = makeSparseStencils(Neuron, res, cap, k);</c> Construct sparse RHS and LHS in coordinate storage format, no zeros are stored \n /// <c>sparse_stencils</c> this is a list which contains only two matrices the LHS and RHS matrices for the Crank-Nicolson solve sparse_stencils = makeSparseStencils(Neuron, res, cap, timeStep); ///<c>CompressedColumnStorage</c> call Compresses the sparse matrices which are stored in <c>sparse_stencils[0]</c> and <c>sparse_stencils[1]</c> r_csc = CompressedColumnStorage <double> .OfIndexed(sparse_stencils[0]); //null; l_csc = CompressedColumnStorage <double> .OfIndexed(sparse_stencils[1]); //null; ///<c>double [] b</c> we define storage for the diffusion solve part b = new double[Neuron.nodes.Count]; ///<c>var lu = SparseLU.Create(l_csc, ColumnOrdering.MinimumDegreeAtA, 0.1);</c> this creates the LU decomposition of the HINES matrix which is defined by <c>l_csc</c> lu = SparseLU.Create(l_csc, ColumnOrdering.MinimumDegreeAtA, 0.1); }
public void TestMatrixParallelMultiply() { var data = ResourceLoader.Get <double>("general-40x40.mat"); var acs = new CoordinateStorage <double>(40, 800, 40 * 800); var bcs = new CoordinateStorage <double>(800, 40, 800 * 40); // This just exceeds min_total_ops in ParallelMultiply foreach (var item in data.EnumerateIndexed()) { int i = item.Item1; int j = item.Item2; for (var k = 0; k < 20; k++) { acs.At(i, j + 40 * k, item.Item3); bcs.At(i + 40 * k, j, item.Item3); } } var A = CompressedColumnStorage <double> .OfIndexed(acs); var B = CompressedColumnStorage <double> .OfIndexed(bcs); var sResult = A.Multiply(B); var pResult = A.ParallelMultiply(B); CollectionAssert.AreEqual(sResult.Values, pResult.Values); }
/// <summary> /// Read a matrix from stream. /// </summary> public static CompressedColumnStorage <T> ReadMatrix <T>(Stream stream) where T : struct, IEquatable <T>, IFormattable { using (var reader = new StreamReader(stream)) { return(CompressedColumnStorage <T> .OfIndexed(ReadStorage <T>(reader))); } }
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."); }
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."); } }