예제 #1
0
        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);
        }
예제 #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);
        }
예제 #3
0
        public void TestEmptyFactorize()
        {
            var A = new SparseMatrix(0, 0, 0);

            var lu = SparseLU.Create(A, ColumnOrdering.MinimumDegreeAtPlusA, 1.0);

            Assert.NotNull(lu);
            Assert.IsTrue(lu.NonZerosCount == 0);
        }
예제 #4
0
        private double[] SolveSparseSystem(double[] h)
        {
            var    order     = ColumnOrdering.MinimumDegreeAtPlusA;
            double tolerance = 1.0;
            var    lu        = SparseLU.Create(Converter.ToCompressedColumnStorage(globalK), order, tolerance);

            lu.Solve(globalF, h);
            return(h);
        }
예제 #5
0
        public SparseLUSolver(int totalCases, double[,] matrix, double[] vector)
        {
            TotalCases = totalCases;
            CompressedColumnStorage <double> e = CompressedColumnStorage <double> .OfArray(matrix);

            SparseLUMatrix       = SparseLU.Create(e, CSparse.ColumnOrdering.MinimumDegreeAtPlusA, 1.0);
            SparseLUVector       = vector;
            SparseLUResultVector = Vector.Create(vector.Length, 1.0);
            SparseLUMethod();
        }
예제 #6
0
 /// <summary>
 /// Performs the LU factorization: A = L * U of a ssquare matrix A.  The matrix A is provided in 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="numNonZeros">The number of explicitly stored entries of the matrix before the factorization.</param>
 /// <param name="cscValues">
 /// Contains the non-zero entries of the upper triangle. Its length must be equal to <paramref name="numNonZeros"/>.
 /// 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="numNonZeros"/>.
 /// 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="numNonZeros"/>.
 /// </param>
 /// <param name="pivotTolerance">The partial pivoting tolerance (from 0.0 to 1.0).</param>
 /// <exception cref="SingularMatrixException">Thrown if the original matrix is not positive definite.</exception>
 public static LUCSparseNet Factorize(int order, int numNonZeros, double[] cscValues, int[] cscRowIndices,
                                      int[] cscColOffsets, double pivotTolerance = defaultPivotTolelance)
 {
     try
     {
         var matrixCSparse = new SparseMatrix(order, order, cscValues, cscRowIndices, cscColOffsets);
         var factorization = SparseLU.Create(matrixCSparse, ColumnOrdering.Natural, pivotTolerance);
         return(new LUCSparseNet(order, factorization));
     }
     catch (Exception ex) //TODO: how can I make sure this exception was thrown because of an indefinite matrix?
     {
         throw new SingularMatrixException(ex.Message);
     }
 }
예제 #7
0
        public void TestSolve()
        {
            // Load matrix from a file.
            var A = ResourceLoader.Get <Complex>("general-40x40.mat");

            // Create test data.
            var x = Helper.CreateTestVector(A.ColumnCount);
            var b = Helper.Multiply(A, x);
            var r = Vector.Clone(b);

            // Create LU factorization.
            var lu = SparseLU.Create(A, ColumnOrdering.MinimumDegreeAtPlusA, 1.0);

            // Solve Ax = b.
            lu.Solve(b, x);

            // Compute residual r = b - Ax.
            A.Multiply(-1.0, x, 1.0, r);

            Assert.IsTrue(Vector.Norm(r.Length, r) < EPS);
        }
예제 #8
0
        /// <inheritdoc />
        public void Initialize()
        {
            var matrix = A;
            var sp     = new Stopwatch();

            sp.Start();

            lu =
                SparseLU.Create(matrix, ColumnOrdering.MinimumDegreeAtPlusA, 0.01);


            IsInitialized = true;

            sp.Stop();

            if (Target != null)
            {
                Target.Trace.Write(TraceRecord.Create(BriefFiniteElementNet.Common.TraceLevel.Info,
                                                      string.Format(CultureInfo.CurrentCulture, "LU decomposition of matrix took about {0:#,##0} ms",
                                                                    sp.ElapsedMilliseconds)));
            }
        }
예제 #9
0
        public static Vector SolveLU(CompressedColumnStorage <double> A, Vector x, Vector b, out bool status, out string error)
        {
            var orderings = new[] { CSparse.ColumnOrdering.MinimumDegreeAtPlusA, CSparse.ColumnOrdering.MinimumDegreeAtA, CSparse.ColumnOrdering.MinimumDegreeStS, CSparse.ColumnOrdering.Natural };

            status = false;
            error  = null;
            try
            {
                status = true;
                if (A.RowCount == A.ColumnCount)
                {
                    var lu = SparseLU.Create(A, CSparse.ColumnOrdering.MinimumDegreeAtPlusA, 1.0);
                    lu.Solve(b.ToDouble(), x.ToDouble());
                    status = true;
                    return(x);
                }
            }
            catch (Exception e)
            {
                error  = e.Message;
                status = false;
            }
            return(x);
        }
예제 #10
0
        private void Solve()
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            double[] h            = new double[Codend.dof];
            double   PrevTowSpeed = Codend.towSpeed;
            int      PrevCatch    = Codend.GetMeshesBlocked();

            SparseLU LU;
            var      LUorder     = ColumnOrdering.MinimumDegreeAtPlusA;
            double   LUtolerance = 1.0;

            bool hasConverged    = false;                       // convergence flag
            bool correctSolution = false;                       // correctness of solution flag
            bool hasDiverged     = false;                       // restart flag
            bool usePrecalc      = CheckPrecalc();
            int  restartsCount   = 0;
            int  iter            = 0;

            double hNorm     = 1;
            double addStiff  = SolverSettings.DiagStiffness;
            double addStiff0 = SolverSettings.DiagStiffness;
            double tolStiff  = SolverSettings.StiffnessTol;

            //=============================
            // Start calculation
            //=============================

            for (int stage = 1; stage <= 2; stage++)
            {
                //===========================
                // Restarts loop
                //===========================

                while (!correctSolution)
                {
                    // Set initial shape depending on whether it is precalculated from previous stage or not
                    Codend.ClearState();

                    SetStageInitialShape(stage);

                    Codend.UpdateTotalForces(IncludeBC: true);
                    Codend.UpdateResidual();

                    if (addStiff0 == 0 && restartsCount > 0)  // if the scheme doesnt work without extra stiffness
                    {
                        addStiff0 = 1;
                    }
                    addStiff = addStiff0;
                    tolStiff = SolverSettings.StiffnessTol;
                    //===========================
                    // Newton-Raphson loop
                    //===========================

                    while (!hasConverged)
                    {
                        // check if diverged
                        if (Codend.R > SolverSettings.ResidualMax)
                        {
                            hasDiverged = true;
                            break;
                        }

                        // check whether to add less diagonal stiffness
                        if (Codend.R < tolStiff)
                        {
                            addStiff *= SolverSettings.ReduceStiffnessBy;
                            tolStiff *= SolverSettings.ReduceStiffnessBy;
                        }

                        // check if converged and no stiffness is added
                        if (Codend.R < SolverSettings.ResidualTol && hNorm < SolverSettings.DisplacementTol)
                        {
                            break;
                        }

                        Codend.UpdateTotalJacobian(kDiag: -addStiff, IncludeBC: true);

                        LU = SparseLU.Create(Codend.J, LUorder, LUtolerance);
                        LU.Solve(Codend.F, h);

                        hNorm = DisplacmentNorm(h);
                        Codend.UpdatePosition(h, 1);

                        Codend.UpdateTotalForces(IncludeBC: true);
                        Codend.UpdateResidual();

                        iter++;                                                   // display iteration status
                        Console.WriteLine(
                            PrintIter(iter, 0, addStiff, Codend.R, hNorm));
                    }

                    //===================
                    // Restart routine
                    //===================

                    if (hasDiverged || IsIncorrectSolution())
                    {
                        restartsCount += 1;
                        addStiff0     *= SolverSettings.IncreaseStiffnessBy;
                        ReportRestartCause(hasDiverged);
                        hasDiverged = false;
                    }
                    else
                    {
                        correctSolution = true; // correct solution found
                        Console.WriteLine("\nConvergence acheived in {0} iterations and {1} restarts in {2} [ms]\n",
                                          iter, restartsCount, stopwatch.ElapsedMilliseconds);
                    }
                }


                if (usePrecalc)
                {
                    Codend.X.CopyTo(precalcX, 0);
                    Codend.ApplyCatch(PrevCatch);
                    Codend.ApplyTowing(PrevTowSpeed);

                    Console.WriteLine("\nInitial shape is precalculated. Moiving to and actual case.\n");
                    correctSolution = false;
                    usePrecalc      = false;
                    hasConverged    = false;
                }
                else
                {
                    break;
                }
            }
        }
예제 #11
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]));
                    }
                }
            }
        }
예제 #12
0
 public DisposableSparseLU(SparseMatrix matrix)
 {
     lu = SparseLU.Create(matrix, ColumnOrdering.MinimumDegreeAtPlusA, 0.1);
 }
예제 #13
0
 private LUCSparseNet(int order, SparseLU factorization)
 {
     this.Order         = order;
     this.factorization = factorization;
 }