/// <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); } }
public double MaxEiganValue() { matrixq = new MatrixQ(matrix); var eiganVals = matrixq.Eigenvalues(); return(((Complex)(((ArrayList)eiganVals.Values[0])[0])).Re); }
public double MinEiganValue() { matrixq = new MatrixQ(matrix); var eiganVals = matrixq.Eigenvalues(); return(((Complex)(((ArrayList)eiganVals.Values[eiganVals.RowCount - 1])[eiganVals.ColumnCount - 1])).Re); }
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); } } } }
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); }
/// <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); } } } }
/// <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]; } }
/// <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)); } } }
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); }
// 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! }
/// <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); } } }
public double Determinant() { matrixq = new MatrixQ(matrix); return(matrixq.Determinant().Re); }
public double Trace() { matrixq = new MatrixQ(matrix); return(matrixq.Trace().Re); }