Exemplo n.º 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; }
 }
Exemplo n.º 2
0
        public static Vector SolveLU(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";

            try
            {
                status = true;
                if (A.RowCount == A.ColumnCount)
                {
                    var lu = new SparseLU(A, CSparse.ColumnOrdering.MinimumDegreeAtA, 1.0);
                    var xc = x.Clone();
                    var bc = b.Clone();
                    lu.Solve(bc.ToDouble(), xc.ToDouble());
                    algorithm = "LU/" + CSparse.ColumnOrdering.MinimumDegreeAtPlusA;
                    status    = true;
                    return(xc);
                }
            }
            catch (Exception e)
            {
                status = false;
            }

            return(x);
        }
Exemplo n.º 3
0
        public void mosek2(List<leaf> _listLeaf, List<branch> _listBranch, List<node> _listNode, double force)
        {
            //variable settings
            ShoNS.Array.SparseDoubleArray mat = new SparseDoubleArray(_listNode.Count * 3, _listNode.Count * 3);
            ShoNS.Array.SparseDoubleArray F = new SparseDoubleArray(_listNode.Count * 3, 1);
            ShoNS.Array.SparseDoubleArray xx = new SparseDoubleArray(_listNode.Count*3,1);
            ShoNS.Array.SparseDoubleArray shift = new SparseDoubleArray(_listNode.Count*3, _listNode.Count*3);
            for (int k = 0; k < _listNode.Count;k++ )
            {
                var node = _listNode[k];
                xx[k * 3 + 0, 0] = node.x;
                xx[k * 3 + 1, 0] = node.y;
                xx[k * 3 + 2, 0] = node.z;
            /*                if (node.nodeType == node.type.fx)
                {
                    for (int i = 0; i < node.shareB.Count; i++)
                    {
                        var branch = node.shareB[i];
                        var index = node.numberB[i];
                        if (branch.branchType == branch.type.fix)
                        {
                            node.x = branch.crv.Points[index].Location.X;
                            node.y = branch.crv.Points[index].Location.Y;
                            node.z = branch.slice2.height;
                            xx[k * 3 + 0, 0] = node.x;
                            xx[k * 3 + 1, 0] = node.y;
                            xx[k * 3 + 2, 0] = node.z;
                        }
                    }
                }*/
            }

            List<int> series=new List<int>();
            List<Point3d> origin = new List<Point3d>();
            for(int i=0;i<_listNode.Count;i++)
            {
                series.Add(i);
            }
            int L1=0;
            int L2=_listNode.Count;
            for(int i=0;i<_listNode.Count;i++)
            {
                var node=_listNode[i];
                if(node.nodeType==node.type.fx)
                {
                    L2--;
                    series[i]=L2;
                }else{
                    series[i]=L1;
                    origin.Add(new Point3d(node.x, node.y, node.z));
                    L1++;
                }
            }
            for (int i = 0; i < _listNode.Count; i++)
            {
                shift[i * 3 + 0, series[i] * 3 + 0] = 1;
                shift[i * 3 + 1, series[i] * 3 + 1] = 1;
                shift[i * 3 + 2, series[i] * 3 + 2] = 1;
                F[i * 3 + 2, 0] = -force;//force
            }
            foreach (var leaf in _listLeaf)
            {
                foreach (var tup in leaf.tuples)
                {
                    var det = tup.SPK[0, 0] * tup.SPK[1, 1] - tup.SPK[0, 1] * tup.SPK[0, 1];
                    if (det > 0)
                    {
                        for (int i = 0; i < tup.nNode; i++)
                        {
                            for (int j = 0; j < tup.nNode; j++)
                            {
                                for (int k = 0; k < 3; k++)
                                {
                                    for (int l = 0; l < 2; l++)
                                    {
                                        for (int m = 0; m < 2; m++)
                                        {
                                            var val = tup.B[l, m, i * 3 + k, j * 3 + k] * tup.SPK[l, m] * tup.refDv * tup.area;
                                            mat[leaf.globalIndex[tup.internalIndex[i]] * 3 + k, leaf.globalIndex[tup.internalIndex[j]] * 3 + k] += val;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            foreach (var branch in _listBranch)
            {
                foreach (var tup in branch.tuples)
                {
                    for (int i = 0; i < tup.nNode; i++)
                    {
                        for (int j = 0; j < tup.nNode; j++)
                        {
                            for (int k = 0; k < 3; k++)
                            {
                                //if (tup.SPK[0, 0] > 0)
                                {
                                    var val = tup.B[0, 0, i * 3 + k, j * 3 + k] * tup.SPK[0, 0] * tup.refDv * tup.area;
                                    for (int l = 0; l < 1; l++)
                                    {
                                        for (int m = 0; m < 1; m++)
                                        {
                                            var val2 = tup.B[l, m, i * 3 + k, j * 3 + k] * tup.SPK[l, m] * tup.refDv * tup.area;
                                            mat[branch.globalIndex[tup.internalIndex[i]] * 3 + k, branch.globalIndex[tup.internalIndex[j]] * 3 + k] += val2;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            var reactionForce = mat * xx as SparseDoubleArray;
            double max1 = 0;
            double max2 = 0;
            for (int i = 0; i < _listNode.Count; i++)
            {
                if (_listNode[i].nodeType == node.type.fr)
                {
                    var nx = reactionForce[i * 3 + 0, 0];
                    var ny = reactionForce[i * 3 + 1, 0];
                    var norm = Math.Sqrt(nx * nx + ny * ny);
                    if (norm > max1) max1 = norm;
                }
                else
                {
                    var nx = reactionForce[i * 3 + 0, 0];
                    var ny = reactionForce[i * 3 + 1, 0];
                    var norm = Math.Sqrt(nx * nx + ny * ny);
                    if (norm > max2) max2 = norm;
                }
            }
            //System.Windows.Forms.MessageBox.Show(max1.ToString() + ".-." + max2.ToString());
            var newMat = (shift.T.Multiply(mat) as SparseDoubleArray).Multiply(shift) as SparseDoubleArray;
            var newxx = shift.T.Multiply(xx) as SparseDoubleArray;
            var newF = shift.T.Multiply(F) as SparseDoubleArray;

            var T = newMat.GetSliceDeep(0, L1 * 3 - 1, 0, L1 * 3 - 1);
            var D = newMat.GetSliceDeep(0, L1 * 3 - 1, L1 * 3, _listNode.Count * 3 - 1);
            var fx = newxx.GetSliceDeep(L1 * 3, _listNode.Count * 3 - 1, 0, 0);
            newF = newF.GetSliceDeep(0, L1 * 3 - 1, 0, 0);
            var solve = new SparseLU(T);
            //var solve = new SparseSVD(T);
            //var _U = solve.U;
            //var _V = solve.V;
            //var _D = solve.D;
            //double tol=0.00000000001;
            //for (int i = 0; i < L1*3; i++)
            //{
            //    if (_D[i, i] > tol) _D[i, i] = 1d / _D[i, i];
            //    else if (_D[i, i] < -tol) _D[i, i] = 1d / _D[i, i];
            //    else _D[i, i] = 0d;
            //}
            var df = D * fx as SparseDoubleArray;
            var b = DoubleArray.From((-newF - df));

            var sol=solve.Solve(b);
            //var sol = _V * _D * _U.T*b;
            var exSol = new SparseDoubleArray(sol.GetLength(0)+fx.GetLength(0),1);
            for (int i = 0; i < L1; i++)
            {
                exSol[i * 3 + 0, 0] = sol[i * 3 + 0, 0];
                exSol[i * 3 + 1, 0] = sol[i * 3 + 1, 0];
                exSol[i * 3 + 2, 0] = sol[i * 3 + 2, 0];
            }
            for (int i = L1; i < _listNode.Count; i++)
            {
                exSol[i * 3 + 0, 0] = fx[(i - L1) * 3 + 0, 0];
                exSol[i * 3 + 1, 0] = fx[(i - L1) * 3 + 1, 0];
                exSol[i * 3 + 2, 0] = fx[(i - L1) * 3 + 2, 0];
            }
            exSol = shift.Multiply(exSol) as SparseDoubleArray;
            foreach (var branch in _listBranch)
            {
                branch.shellCrv = branch.crv.Duplicate() as NurbsCurve;
                for (int i = 0; i < branch.N; i++)
                {
                    var P = branch.shellCrv.Points[i].Location;
                    branch.shellCrv.Points.SetPoint(i, new Point3d(exSol[branch.globalIndex[i] * 3 + 0, 0], exSol[branch.globalIndex[i] * 3 + 1, 0], exSol[branch.globalIndex[i] * 3 + 2, 0]));
                    //if you don't want to allow movements of x and y coordinates, use the following instead of the above.
                    //branch.shellCrv.Points.SetPoint(i, new Point3d(P.X, P.Y, exSol[branch.globalIndex[i] * 3 + 2, 0]));
                }
            }
            foreach (var leaf in _listLeaf)
            {
                leaf.shellSrf = leaf.srf.Duplicate() as NurbsSurface;
                for (int i = 0; i < leaf.nU; i++)
                {
                    for (int j = 0; j < leaf.nV; j++)
                    {
                        var P = leaf.shellSrf.Points.GetControlPoint(i, j).Location;
                        leaf.shellSrf.Points.SetControlPoint(i, j, new ControlPoint(exSol[leaf.globalIndex[i + j * leaf.nU] * 3 + 0, 0], exSol[leaf.globalIndex[i + j * leaf.nU] * 3 + 1, 0], exSol[leaf.globalIndex[i + j * leaf.nU] * 3 + 2, 0]));
                        //if you don't want to allow movements of x and y coordinates, use the following instead of the above.
                        //leaf.shellSrf.Points.SetControlPoint(i, j, new ControlPoint(P.X, P.Y, exSol[leaf.globalIndex[i + j * leaf.nU] * 3 + 2, 0]));
                    }
                }
            }
        }
Exemplo n.º 4
0
 public void Solve(double[] input, double[] result)
 {
     lu.Solve(input, result);
 }
Exemplo n.º 5
0
 /// <summary>
 /// See <see cref="ITriangulation.SolveLinearSystem(Vector, Vector)"/>.
 /// </summary>
 public void SolveLinearSystem(Vectors.Vector rhs, Vectors.Vector solution)
 => factorization.Solve(rhs.RawData, solution.RawData);
Exemplo n.º 6
0
 public void Solve(Complex[] input, Complex[] result)
 {
     lu.Solve(input, result);
 }