public override void Solve() { var watch = new Stopwatch(); if (linearSystem == null) { linearSystem.SolutionConcrete = linearSystem.CreateZeroVectorConcrete(); } else { linearSystem.SolutionConcrete.Clear(); } watch.Start(); IterativeStatistics stats = gmresAlgorithm.Solve(linearSystem.Matrix, linearSystem.RhsConcrete, linearSystem.SolutionConcrete, true, () => linearSystem.CreateZeroVector()); if (!stats.HasConverged) { throw new IterativeSolverNotConvergedException("Gmres did not converge"); } watch.Stop(); Logger.LogTaskDuration("Iterative algorithm", watch.ElapsedMilliseconds); Logger.LogIterativeAlgorithm(stats.NumIterationsRequired, stats.ResidualNormRatioEstimation); Logger.IncrementAnalysisStep(); }
private static void TestIndefiniteSystem(LinearAlgebraProviderChoice providers) { TestSettings.RunMultiproviderTest(providers, delegate() { (Matrix A, Vector b, Vector xExpected, IPreconditioner M) = DiagonalIndefinite.BuildIndefiniteSystem(20); var builder = new CGAlgorithm.Builder(); builder.ResidualTolerance = 1E-6; builder.MaxIterationsProvider = new PercentageMaxIterationsProvider(1.0); var cg = builder.Build(); Vector xComputed = Vector.CreateZero(A.NumRows); IterativeStatistics stats = cg.Solve(A, b, xComputed, true); Assert.False(comparer.AreEqual(xExpected, xComputed)); }); }
protected override Matrix InverseSystemMatrixTimesOtherMatrix(IMatrixView otherMatrix) { //TODO: Use a reorthogonalizetion approach when solving multiple rhs vectors. It would be even better if the CG // algorithm exposed a method for solving for multiple rhs vectors. var watch = new Stopwatch(); // Preconditioning if (mustUpdatePreconditioner) { watch.Start(); preconditioner = preconditionerFactory.CreatePreconditionerFor(linearSystem.Matrix); watch.Stop(); Logger.LogTaskDuration("Calculating preconditioner", watch.ElapsedMilliseconds); watch.Reset(); mustUpdatePreconditioner = false; } // Iterative algorithm watch.Start(); int systemOrder = linearSystem.Matrix.NumColumns; int numRhs = otherMatrix.NumColumns; var solutionVectors = Matrix.CreateZero(systemOrder, numRhs); Vector solutionVector = linearSystem.CreateZeroVectorConcrete(); // Solve each linear system for (int j = 0; j < numRhs; ++j) { if (j != 0) { solutionVector.Clear(); } //TODO: we should make sure this is the same type as the vectors used by this solver, otherwise vector operations // in CG will be slow. Vector rhsVector = otherMatrix.GetColumn(j); IterativeStatistics stats = pcgAlgorithm.Solve(linearSystem.Matrix, preconditioner, rhsVector, solutionVector, true, () => linearSystem.CreateZeroVector()); solutionVectors.SetSubcolumn(j, solutionVector); } watch.Stop(); Logger.LogTaskDuration("Iterative algorithm", watch.ElapsedMilliseconds); Logger.IncrementAnalysisStep(); return(solutionVectors); }
public Vector CalcLagrangeMultipliers(Feti1FlexibilityMatrix flexibility, IFetiPreconditioner preconditioner, Feti1Projection projection, Vector disconnectedDisplacements, Vector rigidBodyModesWork, double globalForcesNorm, SolverLogger logger) { int systemOrder = flexibility.Order; PcgMatrix pcgMatrix = DefinePcgMatrix(flexibility, projection); PcgPreconditioner pcgPreconditioner = DefinePcgPreconditioner(preconditioner, projection); // λ0 = Q * G * inv(G^T * Q * G) * e Vector lagrangesParticular = projection.CalcParticularLagrangeMultipliers(rigidBodyModesWork); // Calculate rhs of the projected interface system: rhs = P^T * (d - F * λ0) var r0 = flexibility.Multiply(lagrangesParticular); r0.LinearCombinationIntoThis(-1.0, disconnectedDisplacements, 1.0); var pcgRhs = Vector.CreateZero(systemOrder); projection.ProjectVector(r0, pcgRhs, true); // Solve the interface problem using PCG algorithm var pcgBuilder = new PcgAlgorithm.Builder(); pcgBuilder.MaxIterationsProvider = maxIterationsProvider; pcgBuilder.ResidualTolerance = pcgConvergenceTolerance; pcgBuilder.Convergence = pcgConvergenceStrategyFactory.CreateConvergenceStrategy(globalForcesNorm); PcgAlgorithm pcg = pcgBuilder.Build(); var lagrangesBar = Vector.CreateZero(systemOrder); IterativeStatistics stats = pcg.Solve(pcgMatrix, pcgPreconditioner, pcgRhs, lagrangesBar, true, () => Vector.CreateZero(systemOrder)); if (!stats.HasConverged) { throw new IterativeSolverNotConvergedException(Feti1Solver.name + " did not converge to a solution. PCG" + $" algorithm run for {stats.NumIterationsRequired} iterations and the residual norm ratio was" + $" {stats.ResidualNormRatioEstimation}"); } // Calculate the actual lagrange multipliers from the separation formula: λ = λ0 + P * λbar var lagranges = Vector.CreateZero(systemOrder); projection.ProjectVector(lagrangesBar, lagranges, false); lagranges.AddIntoThis(lagrangesParticular); // Log statistics about PCG execution logger.LogIterativeAlgorithm(stats.NumIterationsRequired, stats.ResidualNormRatioEstimation); return(lagranges); }
private static void TestSparseSystem(LinearAlgebraProviderChoice providers) { TestSettings.RunMultiproviderTest(providers, delegate() { var A = Matrix.CreateFromArray(SparsePosDef10by10.Matrix); var b = Vector.CreateFromArray(SparsePosDef10by10.Rhs); var xExpected = Vector.CreateFromArray(SparsePosDef10by10.Lhs); var builder = new CGAlgorithm.Builder(); builder.ResidualTolerance = 1E-7; builder.MaxIterationsProvider = new PercentageMaxIterationsProvider(1.0); var cg = builder.Build(); var xComputed = Vector.CreateZero(A.NumRows); IterativeStatistics stats = cg.Solve(A, b, xComputed, true); comparer.AssertEqual(xExpected, xComputed); }); }
private static void TestPosDefSparseSystem() { var A = Matrix.CreateFromArray(SparsePosDef10by10.Matrix); var b = Vector.CreateFromArray(SparsePosDef10by10.Rhs); var xExpected = Vector.CreateFromArray(SparsePosDef10by10.Lhs); var builder = new ReorthogonalizedPcg.Builder(); builder.ResidualTolerance = 1E-7; builder.MaxIterationsProvider = new PercentageMaxIterationsProvider(1.0); var pcg = builder.Build(); var M = new JacobiPreconditioner(A.GetDiagonalAsArray()); Vector xComputed = Vector.CreateZero(A.NumRows); IterativeStatistics stats = pcg.Solve(A, M, b, xComputed, true, () => Vector.CreateZero(b.Length)); comparer.AssertEqual(xExpected, xComputed); }
private static void TestPosDefSparseSystem(LinearAlgebraProviderChoice providers) { TestSettings.RunMultiproviderTest(providers, delegate() { var A = Matrix.CreateFromArray(SparsePosDef10by10.Matrix); var b = Vector.CreateFromArray(SparsePosDef10by10.Rhs); var xExpected = Vector.CreateFromArray(SparsePosDef10by10.Lhs); var builder = new PcgAlgorithm.Builder(); builder.ResidualTolerance = 1E-7; builder.MaxIterationsProvider = new PercentageMaxIterationsProvider(1.0); var pcg = builder.Build(); var M = new JacobiPreconditioner(A.GetDiagonalAsArray()); Vector xComputed = Vector.CreateZero(A.NumRows); IterativeStatistics stats = pcg.Solve(A, M, b, xComputed, true, () => Vector.CreateZero(b.Length)); comparer.AssertEqual(xExpected, xComputed); }); }
private static void TestNearbyProblems(double noiseWidth, int maxIterations, int numRhsVectors) { int order = SymmPosDef10by10.Order; var A = Matrix.CreateFromArray(SymmPosDef10by10.Matrix); var builder = new ReorthogonalizedPcg.Builder(); builder.ResidualTolerance = 1E-6; builder.MaxIterationsProvider = new PercentageMaxIterationsProvider(1.0); builder.Convergence = new RhsNormalizedConvergence(); var pcg = builder.Build(); var M = new JacobiPreconditioner(A.GetDiagonalAsArray()); // Initial run Vector x0 = Vector.CreateWithValue(order, 1); Vector x0Expected = x0.Copy(); Vector b0 = A * x0Expected; Vector x0Computed = Vector.CreateZero(A.NumRows); IterativeStatistics stats0 = pcg.Solve(A, M, b0, x0Computed, true, () => Vector.CreateZero(order)); Debug.WriteLine($"Initial run: iterations = {stats0.NumIterationsRequired}"); comparer.AssertEqual(x0Expected, x0Computed); // Subsequent runs int seed = 345; for (int i = 0; i < numRhsVectors; ++i) { Vector dx = Vector.CreateFromArray(RandomMatrices.CreateRandomVector(order, seed)); Vector xExpected = x0 + noiseWidth * dx; Vector b = A * xExpected; pcg.Clear(); //TODO: preferably do not call this. //pcg.ReorthoCache.Clear(); Vector xComputed = Vector.CreateZero(A.NumRows); IterativeStatistics stats = pcg.Solve(A, M, b, xComputed, true, () => Vector.CreateZero(b.Length)); Debug.WriteLine($"Subsequent run: iterations = {stats.NumIterationsRequired}"); comparer.AssertEqual(xExpected, xComputed); Assert.InRange(stats.NumIterationsRequired, 1, maxIterations); } }
/// <summary> /// Solves the linear system with PCG method. If the matrix has been modified, a new preconditioner will be computed. /// </summary> public override void Solve() { var watch = new Stopwatch(); if (linearSystem.SolutionConcrete == null) { linearSystem.SolutionConcrete = linearSystem.CreateZeroVectorConcrete(); } else { linearSystem.SolutionConcrete.Clear(); } // Preconditioning if (mustUpdatePreconditioner) { watch.Start(); preconditioner = preconditionerFactory.CreatePreconditionerFor(linearSystem.Matrix); watch.Stop(); Logger.LogTaskDuration("Calculating preconditioner", watch.ElapsedMilliseconds); watch.Reset(); mustUpdatePreconditioner = false; } // Iterative algorithm watch.Start(); IterativeStatistics stats = pcgAlgorithm.Solve(linearSystem.Matrix, preconditioner, linearSystem.RhsConcrete, linearSystem.SolutionConcrete, true, () => linearSystem.CreateZeroVector()); //TODO: This way, we don't know that x0=0, which will result in an extra b-A*0 if (!stats.HasConverged) { throw new IterativeSolverNotConvergedException(Name + " did not converge to a solution. PCG algorithm run for" + $" {stats.NumIterationsRequired} iterations and the residual norm ratio was" + $" {stats.ResidualNormRatioEstimation}"); } watch.Stop(); Logger.LogTaskDuration("Iterative algorithm", watch.ElapsedMilliseconds); Logger.LogIterativeAlgorithm(stats.NumIterationsRequired, stats.ResidualNormRatioEstimation); Logger.IncrementAnalysisStep(); }
public (Vector lagrangeMultipliers, Vector cornerDisplacements) SolveInterfaceProblem(FetiDPFlexibilityMatrix flexibility, IFetiPreconditioner preconditioner, IFetiDPCoarseProblemSolver coarseProblemSolver, Vector globalFcStar, Vector dr, double globalForcesNorm, SolverLogger logger) { int systemOrder = flexibility.Order; // Matrix, preconditioner & rhs var pcgMatrix = new InterfaceProblemMatrix(flexibility, coarseProblemSolver); var pcgPreconditioner = new InterfaceProblemPreconditioner(preconditioner); Vector pcgRhs = CreateInterfaceProblemRhs(flexibility, coarseProblemSolver, globalFcStar, dr); // Solve the interface problem using PCG algorithm var pcgBuilder = new PcgAlgorithm.Builder(); pcgBuilder.MaxIterationsProvider = maxIterationsProvider; pcgBuilder.ResidualTolerance = pcgConvergenceTolerance; pcgBuilder.Convergence = pcgConvergenceStrategyFactory.CreateConvergenceStrategy(globalForcesNorm); PcgAlgorithm pcg = pcgBuilder.Build(); //TODO: perhaps use the pcg from the previous analysis if it has reorthogonalization. var lagranges = Vector.CreateZero(systemOrder); IterativeStatistics stats = pcg.Solve(pcgMatrix, pcgPreconditioner, pcgRhs, lagranges, true, () => Vector.CreateZero(systemOrder)); // Log statistics about PCG execution if (!stats.HasConverged) { throw new IterativeSolverNotConvergedException(FetiDPSolver.name + " did not converge to a solution. PCG" + $" algorithm run for {stats.NumIterationsRequired} iterations and the residual norm ratio was" + $" {stats.ResidualNormRatioEstimation}"); } logger.LogIterativeAlgorithm(stats.NumIterationsRequired, stats.ResidualNormRatioEstimation); // Calculate corner displacements: uc = inv(KccStar) * (fcStar + FIrc^T * lagranges) Vector uc = flexibility.MultiplyTransposedFIrc(lagranges); uc.AddIntoThis(globalFcStar); uc = coarseProblemSolver.MultiplyInverseCoarseProblemMatrixTimes(uc); return(lagranges, uc); }
public Vector CalcLagrangeMultipliers(Feti1FlexibilityMatrix flexibility, IFetiPreconditioner preconditioner, Feti1Projection projection, Vector disconnectedDisplacements, Vector rigidBodyModesWork, double globalForcesNorm, SolverLogger logger) { // PCPG starts from the particular lagrange multipliers: λ0 = Q * G * inv(G^T * Q * G) * e Vector lagranges = projection.CalcParticularLagrangeMultipliers(rigidBodyModesWork); IFetiPcgConvergence pcpgConvergenceStrategy = pcgConvergenceStrategyFactory.CreateConvergenceStrategy(globalForcesNorm); var pcpg = new PcpgAlgorithm(maxIterationsProvider, pcpgConvergenceTolerance, pcpgConvergenceStrategy); IterativeStatistics stats = pcpg.Solve(flexibility, preconditioner, projection, disconnectedDisplacements, lagranges); if (!stats.HasConverged) { throw new IterativeSolverNotConvergedException(Feti1Solver.name + " did not converge to a solution. PCPG" + $" algorithm run for {stats.NumIterationsRequired} iterations and the residual norm ratio was" + $" {stats.ResidualNormRatioEstimation}"); } // Log statistics about PCG execution logger.LogIterativeAlgorithm(stats.NumIterationsRequired, stats.ResidualNormRatioEstimation); return(lagranges); }
//[Fact] private static void InvestigateNoiseStagnation() { double noiseWidth = 100; int order = 100; //var A = Matrix.CreateFromArray(MultiDiagonalMatrices.CreateSymmetric(order, new int[] { 0, 1, 5, 7, 12 })); var valueOfEachDiagonal = new Dictionary <int, double>(); valueOfEachDiagonal[0] = 10.0; valueOfEachDiagonal[1] = 4.0; valueOfEachDiagonal[5] = 3.0; var A = Matrix.CreateFromArray(MultiDiagonalMatrices.CreateSymmetric(order, valueOfEachDiagonal)); var M = new IdentityPreconditioner(); //var M = new JacobiPreconditioner(A.GetDiagonalAsArray()); // Method A: Regular PCG var pcgBuilder = new PcgAlgorithm.Builder(); pcgBuilder.ResidualTolerance = 1E-15; pcgBuilder.MaxIterationsProvider = new FixedMaxIterationsProvider(50); var pcg = pcgBuilder.Build(); // Method B: Reorthogonalized PCG, but without keeping direction vectors from previous solutions. var pcgReorthoRestartBuilder = new ReorthogonalizedPcg.Builder(); pcgReorthoRestartBuilder.ResidualTolerance = 1E-15; pcgReorthoRestartBuilder.MaxIterationsProvider = new FixedMaxIterationsProvider(50); var pcgReorthoRestart = pcgReorthoRestartBuilder.Build(); // Method C: Reorthogonalized PCG, where the second solution will reuse direction vectors from the first var pcgReorthoBuilder = new ReorthogonalizedPcg.Builder(); pcgReorthoBuilder.ResidualTolerance = 1E-15; pcgReorthoBuilder.MaxIterationsProvider = new FixedMaxIterationsProvider(50); var pcgReortho = pcgReorthoBuilder.Build(); // Initial rhs Vector x0 = Vector.CreateWithValue(order, 1); Vector x0Expected = x0.Copy(); Vector b0 = A * x0Expected; Vector xA = Vector.CreateZero(A.NumRows); IterativeStatistics statsA = pcg.Solve(A, M, b0, xA, true, () => Vector.CreateZero(order)); Debug.WriteLine($"Initial run - method A: iterations = {statsA.NumIterationsRequired}"); Vector xB = Vector.CreateZero(A.NumRows); IterativeStatistics statsB = pcgReorthoRestart.Solve(A, M, b0, xB, true, () => Vector.CreateZero(order)); Debug.WriteLine($"Initial run - method B iterations = {statsB.NumIterationsRequired}"); Vector xC = Vector.CreateZero(A.NumRows); IterativeStatistics statsC = pcgReortho.Solve(A, M, b0, xC, true, () => Vector.CreateZero(order)); Debug.WriteLine($"Initial run - method C: iterations = {statsC.NumIterationsRequired}"); // Perturbed rhs int seed = 345; Vector dx = Vector.CreateFromArray(RandomMatrices.CreateRandomVector(order, seed)); Vector x1Expected = x0 + noiseWidth * dx; Vector b1 = A * x1Expected; xA = Vector.CreateZero(A.NumRows); statsA = pcg.Solve(A, M, b1, xA, true, () => Vector.CreateZero(order)); Debug.WriteLine($"2nd run, noise = {noiseWidth} - method A: iterations = {statsA.NumIterationsRequired}"); xB = Vector.CreateZero(A.NumRows); pcgReorthoRestart.ReorthoCache.Clear(); statsB = pcgReorthoRestart.Solve(A, M, b1, xB, true, () => Vector.CreateZero(order)); Debug.WriteLine($"2nd run, noise = {noiseWidth} - method B iterations = {statsB.NumIterationsRequired}"); xC = Vector.CreateZero(A.NumRows); statsC = pcgReortho.Solve(A, M, b1, xC, true, () => Vector.CreateZero(order)); Debug.WriteLine($"2nd run, noise = {noiseWidth} - method C: iterations = {statsC.NumIterationsRequired}"); }
//[Fact] private static void InvestigatePFetiDPCoarseProblem2D() { int order = PFetiDPCoarseProblem2D.Order; var A = Matrix.CreateFromArray(PFetiDPCoarseProblem2D.MatrixScc); var M = new IdentityPreconditioner(); // Method A: Regular PCG var pcgBuilder = new PcgAlgorithm.Builder(); pcgBuilder.ResidualTolerance = 1E-20; pcgBuilder.MaxIterationsProvider = new FixedMaxIterationsProvider(50); var pcg = pcgBuilder.Build(); // Method B: Reorthogonalized PCG, but without keeping direction vectors from previous solutions. var pcgReorthoRestartBuilder = new ReorthogonalizedPcg.Builder(); pcgReorthoRestartBuilder.ResidualTolerance = 1E-20; pcgReorthoRestartBuilder.MaxIterationsProvider = new FixedMaxIterationsProvider(50); var pcgReorthoRestart = pcgReorthoRestartBuilder.Build(); // Method C: Reorthogonalized PCG, where the second solution will reuse direction vectors from the first var pcgReorthoBuilder = new ReorthogonalizedPcg.Builder(); pcgReorthoBuilder.ResidualTolerance = 1E-20; pcgReorthoBuilder.MaxIterationsProvider = new FixedMaxIterationsProvider(50); var pcgReortho = pcgReorthoBuilder.Build(); // Initial rhs var b = Vector.CreateFromArray(PFetiDPCoarseProblem2D.RhsVectors[0]); var xExpected = Vector.CreateFromArray(PFetiDPCoarseProblem2D.SolutionVectors[0]); Vector xA = Vector.CreateZero(A.NumRows); IterativeStatistics statsA = pcg.Solve(A, M, b, xA, true, () => Vector.CreateZero(order)); Assert.True(xExpected.Equals(xA, 1E-10)); Debug.WriteLine($"Initial run - method A: iterations = {statsA.NumIterationsRequired}"); Vector xB = Vector.CreateZero(A.NumRows); IterativeStatistics statsB = pcgReorthoRestart.Solve(A, M, b, xB, true, () => Vector.CreateZero(order)); Assert.True(xExpected.Equals(xB, 1E-10)); Debug.WriteLine($"Initial run - method B iterations = {statsB.NumIterationsRequired}"); Vector xC = Vector.CreateZero(A.NumRows); IterativeStatistics statsC = pcgReortho.Solve(A, M, b, xC, true, () => Vector.CreateZero(order)); Assert.True(xExpected.Equals(xC, 1E-10)); Debug.WriteLine($"Initial run - method C: iterations = {statsC.NumIterationsRequired}"); // Next rhs b = Vector.CreateFromArray(PFetiDPCoarseProblem2D.RhsVectors[1]); xExpected = Vector.CreateFromArray(PFetiDPCoarseProblem2D.SolutionVectors[1]); xA = Vector.CreateZero(A.NumRows); statsA = pcg.Solve(A, M, b, xA, true, () => Vector.CreateZero(order)); Assert.True(xExpected.Equals(xA, 1E-10)); Debug.WriteLine($"Initial run - method A: iterations = {statsA.NumIterationsRequired}"); xB = Vector.CreateZero(A.NumRows); pcgReorthoRestart.ReorthoCache.Clear(); statsB = pcgReorthoRestart.Solve(A, M, b, xB, true, () => Vector.CreateZero(order)); Assert.True(xExpected.Equals(xB, 1E-10)); Debug.WriteLine($"Initial run - method B iterations = {statsB.NumIterationsRequired}"); xC = Vector.CreateZero(A.NumRows); statsC = pcgReortho.Solve(A, M, b, xC, true, () => Vector.CreateZero(order)); Assert.True(xExpected.Equals(xC, 1E-10)); Debug.WriteLine($"Initial run - method C: iterations = {statsC.NumIterationsRequired}"); }