示例#1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UserQR"/> class. This object will compute the
        /// QR factorization when the constructor is called and cache it's factorization.
        /// </summary>
        /// <param name="matrix">The matrix to factor.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
        public UserQR(Matrix <double> matrix)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount < matrix.ColumnCount)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(matrix);
            }

            MatrixR = matrix.Clone();
            MatrixQ = matrix.CreateMatrix(matrix.RowCount, matrix.RowCount);

            for (var i = 0; i < matrix.RowCount; i++)
            {
                MatrixQ.At(i, i, 1.0);
            }

            var minmn = Math.Min(matrix.RowCount, matrix.ColumnCount);
            var u     = new double[minmn][];

            for (var i = 0; i < minmn; i++)
            {
                u[i] = GenerateColumn(MatrixR, i, i);
                ComputeQR(u[i], MatrixR, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.NumberOfParallelWorkerThreads);
            }

            for (var i = minmn - 1; i >= 0; i--)
            {
                ComputeQR(u[i], MatrixQ, i, matrix.RowCount, i, matrix.RowCount, Control.NumberOfParallelWorkerThreads);
            }
        }
示例#2
0
文件: Matrix.cs 项目: Swipes13/smad
        public double MaxEiganValue()
        {
            matrixq = new MatrixQ(matrix);
            var eiganVals = matrixq.Eigenvalues();

            return(((Complex)(((ArrayList)eiganVals.Values[0])[0])).Re);
        }
示例#3
0
文件: Matrix.cs 项目: Swipes13/smad
        public double MinEiganValue()
        {
            matrixq = new MatrixQ(matrix);
            var eiganVals = matrixq.Eigenvalues();

            return(((Complex)(((ArrayList)eiganVals.Values[eiganVals.RowCount - 1])[eiganVals.ColumnCount - 1])).Re);
        }
示例#4
0
文件: Matrix.cs 项目: Swipes13/smad
        public double[] EiganValues()
        {
            matrixq = new MatrixQ(matrix);
            var eiganVals = matrixq.Eigenvalues();

            double[] ret = new double[eiganVals.RowCount];

            for (int i = 0; i < eiganVals.RowCount; i++)
            {
                ret[i] = eiganVals[i + 1, 1].Re;
            }


            return(ret);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="UserGramSchmidt"/> class. This object creates an unitary matrix
        /// using the modified Gram-Schmidt method.
        /// </summary>
        /// <param name="matrix">The matrix to factor.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
        /// <exception cref="ArgumentException">If <paramref name="matrix"/> is rank deficient</exception>
        public UserGramSchmidt(Matrix <Complex32> matrix)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount < matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixDimensions);
            }

            MatrixQ = matrix.Clone();
            MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);

            for (var k = 0; k < MatrixQ.ColumnCount; k++)
            {
                var norm = MatrixQ.Column(k).Norm(2).Real;
                if (norm == 0.0f)
                {
                    throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);
                }

                MatrixR.At(k, k, norm);
                for (var i = 0; i < MatrixQ.RowCount; i++)
                {
                    MatrixQ.At(i, k, MatrixQ.At(i, k) / norm);
                }

                for (var j = k + 1; j < MatrixQ.ColumnCount; j++)
                {
                    var dot = Complex32.Zero;
                    for (int i = 0; i < MatrixQ.RowCount; i++)
                    {
                        dot += MatrixQ.Column(k)[i].Conjugate() * MatrixQ.Column(j)[i];
                    }

                    MatrixR.At(k, j, dot);
                    for (var i = 0; i < MatrixQ.RowCount; i++)
                    {
                        var value = MatrixQ.At(i, j) - (MatrixQ.At(i, k) * dot);
                        MatrixQ.At(i, j, value);
                    }
                }
            }
        }
示例#6
0
文件: Matrix.cs 项目: Swipes13/smad
        public Matrix Inverse()
        {
            matrixq = new MatrixQ(matrix);
            matrixq = matrixq.InverseLeverrier();

            Matrix retValue = new Matrix(this);

            for (int i = 0; i < LenghtX(); i++)
            {
                for (int j = 0; j < LenghtY(); j++)
                {
                    retValue[i, j] = ((Complex)(((ArrayList)matrixq.Values[i])[j])).Re;
                }
            }

            return(retValue);
        }
示例#7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UserGramSchmidt"/> class. This object creates an orthogonal matrix
        /// using the modified Gram-Schmidt method.
        /// </summary>
        /// <param name="matrix">The matrix to factor.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception>
        /// <exception cref="ArgumentException">If <paramref name="matrix"/> is rank deficient</exception>
        public UserGramSchmidt(Matrix <float> matrix)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount < matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixDimensions);
            }

            MatrixQ = matrix.Clone();
            MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);

            for (var k = 0; k < MatrixQ.ColumnCount; k++)
            {
                var norm = MatrixQ.Column(k).Norm(2);
                if (norm == 0.0)
                {
                    throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);
                }

                MatrixR.At(k, k, norm);
                for (var i = 0; i < MatrixQ.RowCount; i++)
                {
                    MatrixQ.At(i, k, MatrixQ.At(i, k) / norm);
                }

                for (var j = k + 1; j < MatrixQ.ColumnCount; j++)
                {
                    var dot = MatrixQ.Column(k).DotProduct(MatrixQ.Column(j));
                    MatrixR.At(k, j, dot);
                    for (var i = 0; i < MatrixQ.RowCount; i++)
                    {
                        var value = MatrixQ.At(i, j) - (MatrixQ.At(i, k) * dot);
                        MatrixQ.At(i, j, value);
                    }
                }
            }
        }
示例#8
0
        /// <summary>
        /// Solves a system of linear equations, <b>Ax = b</b>, with A QR factorized.
        /// </summary>
        /// <param name="input">The right hand side vector, <b>b</b>.</param>
        /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
        public override void Solve(Vector <double> input, Vector <double> result)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            // Ax=b where A is an m x n matrix
            // Check that b is a column vector with m entries
            if (MatrixR.RowCount != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            // Check that x is a column vector with n entries
            if (MatrixR.ColumnCount != result.Count)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(MatrixR, result);
            }

            var inputCopy = input.Clone();

            // Compute Y = transpose(Q)*B
            var column = new double[MatrixR.RowCount];

            for (var k = 0; k < MatrixR.RowCount; k++)
            {
                column[k] = inputCopy[k];
            }

            for (var i = 0; i < MatrixR.RowCount; i++)
            {
                double s = 0;
                for (var k = 0; k < MatrixR.RowCount; k++)
                {
                    s += MatrixQ.At(k, i) * column[k];
                }

                inputCopy[i] = s;
            }

            // Solve R*X = Y;
            for (var k = MatrixR.ColumnCount - 1; k >= 0; k--)
            {
                inputCopy[k] /= MatrixR.At(k, k);
                for (var i = 0; i < k; i++)
                {
                    inputCopy[i] -= inputCopy[k] * MatrixR.At(i, k);
                }
            }

            for (var i = 0; i < MatrixR.ColumnCount; i++)
            {
                result[i] = inputCopy[i];
            }
        }
示例#9
0
        /// <summary>
        /// Solves a system of linear equations, <b>AX = B</b>, with A QR factorized.
        /// </summary>
        /// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
        /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
        public override void Solve(Matrix <double> input, Matrix <double> result)
        {
            // Check for proper arguments.
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            // The solution X should have the same number of columns as B
            if (input.ColumnCount != result.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
            }

            // The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
            if (MatrixR.RowCount != input.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
            }

            // The solution X row dimension is equal to the column dimension of A
            if (MatrixR.ColumnCount != result.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
            }

            var inputCopy = input.Clone();

            // Compute Y = transpose(Q)*B
            var column = new double[MatrixR.RowCount];

            for (var j = 0; j < input.ColumnCount; j++)
            {
                for (var k = 0; k < MatrixR.RowCount; k++)
                {
                    column[k] = inputCopy.At(k, j);
                }

                for (var i = 0; i < MatrixR.RowCount; i++)
                {
                    double s = 0;
                    for (var k = 0; k < MatrixR.RowCount; k++)
                    {
                        s += MatrixQ.At(k, i) * column[k];
                    }

                    inputCopy.At(i, j, s);
                }
            }

            // Solve R*X = Y;
            for (var k = MatrixR.ColumnCount - 1; k >= 0; k--)
            {
                for (var j = 0; j < input.ColumnCount; j++)
                {
                    inputCopy.At(k, j, inputCopy.At(k, j) / MatrixR.At(k, k));
                }

                for (var i = 0; i < k; i++)
                {
                    for (var j = 0; j < input.ColumnCount; j++)
                    {
                        inputCopy.At(i, j, inputCopy.At(i, j) - (inputCopy.At(k, j) * MatrixR.At(i, k)));
                    }
                }
            }

            for (var i = 0; i < MatrixR.ColumnCount; i++)
            {
                for (var j = 0; j < inputCopy.ColumnCount; j++)
                {
                    result.At(i, j, inputCopy.At(i, j));
                }
            }
        }
示例#10
0
        SolveModelWithSubdomains(double stiffnessRatio, InterfaceSolver interfaceSolver, Precond precond, MatrixQ q,
                                 Residual residualConvergence, double factorizationTolerance, double pcgConvergenceTolerance)
        {
            // Model
            Model multiSubdomainModel = CreateModel(stiffnessRatio);

            // Solver
            var factorizationTolerances = new Dictionary <int, double>();

            foreach (Subdomain s in multiSubdomainModel.Subdomains)
            {
                factorizationTolerances[s.ID] = factorizationTolerance;
            }
            //var fetiMatrices = new DenseFeti1SubdomainMatrixManager.Factory();
            //var fetiMatrices = new SkylineFeti1SubdomainMatrixManager.Factory();
            var fetiMatrices  = new SkylineFeti1SubdomainMatrixManager.Factory(new OrderingAmdCSparseNet());
            var solverBuilder = new Feti1Solver.Builder(fetiMatrices, factorizationTolerances);

            // Homogeneous/heterogeneous problem, matrix Q.
            solverBuilder.ProblemIsHomogeneous = stiffnessRatio == 1.0;
            if (q == MatrixQ.Identity)
            {
                solverBuilder.ProjectionMatrixQIsIdentity = true;
            }
            else
            {
                solverBuilder.ProjectionMatrixQIsIdentity = false;
            }

            // Preconditioner
            if (precond == Precond.Lumped)
            {
                solverBuilder.PreconditionerFactory = new LumpedPreconditioner.Factory();
            }
            else if (precond == Precond.DirichletDiagonal)
            {
                solverBuilder.PreconditionerFactory = new DiagonalDirichletPreconditioner.Factory();
            }
            else
            {
                solverBuilder.PreconditionerFactory = new DirichletPreconditioner.Factory();
            }

            // PCG may need to use the exact residual for the comparison with the expected values
            bool residualIsExact = residualConvergence == Residual.Exact;

            ExactFeti1PcgConvergence.Factory exactResidualConvergence = null;
            if (residualIsExact)
            {
                exactResidualConvergence = new ExactFeti1PcgConvergence.Factory(
                    CreateSingleSubdomainModel(stiffnessRatio), solverBuilder.DofOrderer,
                    (model, solver) => new ProblemStructural(model, solver));
            }

            // Lagrange separation method
            if (interfaceSolver == InterfaceSolver.Method1)
            {
                var interfaceProblemSolverBuilder = new Feti1UnprojectedInterfaceProblemSolver.Builder();
                interfaceProblemSolverBuilder.MaxIterationsProvider   = new FixedMaxIterationsProvider(maxIterations);
                interfaceProblemSolverBuilder.PcgConvergenceTolerance = pcgConvergenceTolerance;
                if (residualIsExact)
                {
                    interfaceProblemSolverBuilder.PcgConvergenceStrategyFactory = exactResidualConvergence;
                }
                Feti1UnprojectedInterfaceProblemSolver interfaceProblemSolver = interfaceProblemSolverBuilder.Build();
                solverBuilder.InterfaceProblemSolver = interfaceProblemSolver;
            }
            else
            {
                var interfaceProblemSolverBuilder = new Feti1ProjectedInterfaceProblemSolver.Builder();
                interfaceProblemSolverBuilder.MaxIterationsProvider   = new FixedMaxIterationsProvider(maxIterations);
                interfaceProblemSolverBuilder.PcgConvergenceTolerance = pcgConvergenceTolerance;
                if (residualIsExact)
                {
                    interfaceProblemSolverBuilder.PcgConvergenceStrategyFactory = exactResidualConvergence;
                }

                if (interfaceSolver == InterfaceSolver.Method2)
                {
                    interfaceProblemSolverBuilder.LagrangeSeparation           = Feti1ProjectedInterfaceProblemSolver.LagrangeMultiplierSeparation.Simple;
                    interfaceProblemSolverBuilder.ProjectionSideMatrix         = Feti1ProjectedInterfaceProblemSolver.ProjectionSide.Left;
                    interfaceProblemSolverBuilder.ProjectionSidePreconditioner = Feti1ProjectedInterfaceProblemSolver.ProjectionSide.Left;
                }
                else if (interfaceSolver == InterfaceSolver.Method3)
                {
                    interfaceProblemSolverBuilder.LagrangeSeparation           = Feti1ProjectedInterfaceProblemSolver.LagrangeMultiplierSeparation.WithProjection;
                    interfaceProblemSolverBuilder.ProjectionSideMatrix         = Feti1ProjectedInterfaceProblemSolver.ProjectionSide.Both;
                    interfaceProblemSolverBuilder.ProjectionSidePreconditioner = Feti1ProjectedInterfaceProblemSolver.ProjectionSide.None;
                }
                else if (interfaceSolver == InterfaceSolver.Method4)
                {
                    interfaceProblemSolverBuilder.LagrangeSeparation           = Feti1ProjectedInterfaceProblemSolver.LagrangeMultiplierSeparation.WithProjection;
                    interfaceProblemSolverBuilder.ProjectionSideMatrix         = Feti1ProjectedInterfaceProblemSolver.ProjectionSide.Both;
                    interfaceProblemSolverBuilder.ProjectionSidePreconditioner = Feti1ProjectedInterfaceProblemSolver.ProjectionSide.Left;
                }
                else                 // default
                {
                    interfaceProblemSolverBuilder.LagrangeSeparation           = Feti1ProjectedInterfaceProblemSolver.LagrangeMultiplierSeparation.WithProjection;
                    interfaceProblemSolverBuilder.ProjectionSideMatrix         = Feti1ProjectedInterfaceProblemSolver.ProjectionSide.Both;
                    interfaceProblemSolverBuilder.ProjectionSidePreconditioner = Feti1ProjectedInterfaceProblemSolver.ProjectionSide.Both;
                }

                Feti1ProjectedInterfaceProblemSolver interfaceProblemSolver = interfaceProblemSolverBuilder.Build();
                solverBuilder.InterfaceProblemSolver = interfaceProblemSolver;

                // Only needed in methods 2,3,4, default (where there is lagrange separation)
                if (residualIsExact)
                {
                    exactResidualConvergence.InterfaceProblemSolver = interfaceProblemSolver;
                }
            }

            Feti1Solver fetiSolver = solverBuilder.BuildSolver(multiSubdomainModel);

            if (residualIsExact)
            {
                exactResidualConvergence.FetiSolver = fetiSolver;
            }

            // Structural problem provider
            var provider = new ProblemStructural(multiSubdomainModel, fetiSolver);

            // Linear static analysis
            var childAnalyzer  = new LinearAnalyzer(multiSubdomainModel, fetiSolver, provider);
            var parentAnalyzer = new StaticAnalyzer(multiSubdomainModel, fetiSolver, provider, childAnalyzer);

            // Run the analysis
            parentAnalyzer.Initialize();
            parentAnalyzer.Solve();

            // Gather the global displacements
            var sudomainDisplacements = new Dictionary <int, IVectorView>();

            foreach (var ls in fetiSolver.LinearSystems)
            {
                sudomainDisplacements[ls.Key] = ls.Value.Solution;
            }
            Vector globalDisplacements = fetiSolver.GatherGlobalDisplacements(sudomainDisplacements);

            // Other stats
            int numUniqueGlobalDofs  = multiSubdomainModel.Nodes.Count * 2;
            int numExtenedDomainDofs = 0;

            foreach (var subdomain in multiSubdomainModel.Subdomains)
            {
                numExtenedDomainDofs += subdomain.Nodes.Count * 2;
            }

            return(globalDisplacements, fetiSolver.Logger, numUniqueGlobalDofs, numExtenedDomainDofs);
        }
示例#11
0
        // Stiffness ratio = 1E-6
        //[InlineData(1E-6, InterfaceSolver.Method1, Precond.Dirichlet, MatrixQ.Identity, Residual.Exact, 40)] // converges, stagnates almost before the tolerance and then diverges
        //[InlineData(1E-6, InterfaceSolver.Method2, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 9)] // converges, stagnates almost before the tolerance and then diverges
        //[InlineData(1E-6, InterfaceSolver.Method3, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 23)] //3
        //[InlineData(1E-6, InterfaceSolver.Method4, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 9)] // converges, stagnates almost before the tolerance and then diverges
        //[InlineData(1E-6, InterfaceSolver.Default, Precond.Dirichlet, MatrixQ.Precond, Residual.Approximate, 9)]
        public static void Run(double stiffnessRatio, InterfaceSolver interfaceSolver, Precond precond, MatrixQ q,
                               Residual convergence, int iterExpected)
        {
            //InterfaceSolver interfaceSolver = 0;
            double      factorizationTol = 1E-3, pcpgConvergenceTol = 1E-5;
            IVectorView directDisplacements = SolveModelWithoutSubdomains(stiffnessRatio);

            (IVectorView ddDisplacements, SolverLogger logger, int numUniqueGlobalDofs, int numExtenedDomainDofs) =
                SolveModelWithSubdomains(stiffnessRatio, interfaceSolver, precond, q, convergence,
                                         factorizationTol, pcpgConvergenceTol);
            double normalizedError = directDisplacements.Subtract(ddDisplacements).Norm2() / directDisplacements.Norm2();

            int analysisStep = 0;

            Assert.Equal(882, numUniqueGlobalDofs);               // 882 includes constrained and free dofs
            Assert.Equal(1056, numExtenedDomainDofs);             // 1056 includes constrained and free dofs
            Assert.Equal(190, logger.GetNumDofs(analysisStep, "Lagrange multipliers"));

            // The error is provided in the reference solution the, but it is almost impossible for two different codes run on
            // different machines to achieve the exact same accuracy.
            Assert.Equal(0.0, normalizedError, 5);

            // Allow a tolerance: It is ok if my solver is better or off by 1 iteration
            int pcgIterations = logger.GetNumIterationsOfIterativeAlgorithm(analysisStep);

            Assert.InRange(pcgIterations, 1, iterExpected + 1);             // the upper bound is inclusive!
        }
示例#12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UserQR"/> class. This object will compute the
        /// QR factorization when the constructor is called and cache it's factorization.
        /// </summary>
        /// <param name="matrix">The matrix to factor.</param>
        /// <param name="method">The QR factorization method to use.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
        public UserQR(Matrix <Complex32> matrix, QRMethod method = QRMethod.Full)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount < matrix.ColumnCount)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(matrix);
            }

            QrMethod = method;
            var minmn = Math.Min(matrix.RowCount, matrix.ColumnCount);
            var u     = new Complex32[minmn][];

            if (method == QRMethod.Full)
            {
                MatrixR = matrix.Clone();
                MatrixQ = matrix.CreateMatrix(matrix.RowCount, matrix.RowCount);

                for (var i = 0; i < matrix.RowCount; i++)
                {
                    MatrixQ.At(i, i, 1.0f);
                }

                for (var i = 0; i < minmn; i++)
                {
                    u[i] = GenerateColumn(MatrixR, i, i);
                    ComputeQR(u[i], MatrixR, i, matrix.RowCount, i + 1, matrix.ColumnCount,
                              Control.NumberOfParallelWorkerThreads);
                }

                for (var i = minmn - 1; i >= 0; i--)
                {
                    ComputeQR(u[i], MatrixQ, i, matrix.RowCount, i, matrix.RowCount,
                              Control.NumberOfParallelWorkerThreads);
                }
            }
            else
            {
                MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
                MatrixQ = matrix.Clone();

                for (var i = 0; i < minmn; i++)
                {
                    u[i] = GenerateColumn(MatrixQ, i, i);
                    ComputeQR(u[i], MatrixQ, i, matrix.RowCount, i + 1, matrix.ColumnCount,
                              Control.NumberOfParallelWorkerThreads);
                }

                MatrixR = MatrixQ.SubMatrix(0, matrix.ColumnCount, 0, matrix.ColumnCount);
                MatrixQ.Clear();

                for (var i = 0; i < matrix.ColumnCount; i++)
                {
                    MatrixQ.At(i, i, 1.0f);
                }

                for (var i = minmn - 1; i >= 0; i--)
                {
                    ComputeQR(u[i], MatrixQ, i, matrix.RowCount, i, matrix.ColumnCount,
                              Control.NumberOfParallelWorkerThreads);
                }
            }
        }
示例#13
0
文件: Matrix.cs 项目: Swipes13/smad
 public double Determinant()
 {
     matrixq = new MatrixQ(matrix);
     return(matrixq.Determinant().Re);
 }
示例#14
0
文件: Matrix.cs 项目: Swipes13/smad
 public double Trace()
 {
     matrixq = new MatrixQ(matrix);
     return(matrixq.Trace().Re);
 }