//TODO: perhaps this should be done in Initialize(). Nope, Initialize is not called when using PCPG. private (IMatrixView globalStiffness, IVectorView globalForces) BuildGlobalLinearSystem() { // PcgSolver uses CSR matrices which are efficient for calculating f-K*u var pcgBuilder = new PcgAlgorithm.Builder(); pcgBuilder.MaxIterationsProvider = new FixedMaxIterationsProvider(1); // No need to solve though. var solverBuilder = new PcgSolver.Builder(); solverBuilder.DofOrderer = originalDofOrderer; solverBuilder.PcgAlgorithm = pcgBuilder.Build(); PcgSolver solver = solverBuilder.BuildSolver(singleSubdomainModel); // Let MSolve follow the usual analysis routine, to create all necessary data structures. IStaticProvider problemProvider = createProblemProvider(singleSubdomainModel, solver); var linearAnalyzer = new LinearAnalyzer(singleSubdomainModel, solver, problemProvider); var staticAnalyzer = new StaticAnalyzer(singleSubdomainModel, solver, problemProvider, linearAnalyzer); staticAnalyzer.Initialize(); try { staticAnalyzer.Solve(); } catch (IterativeSolverNotConvergedException) { } // Extract the global matrix and rhs ILinearSystem linearSystem = solver.LinearSystems.First().Value; return(linearSystem.Matrix, linearSystem.RhsVector); }
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 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); }); }
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); }
//[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}"); }
private static void TestQuad4LinearCantileverExample() { // Model & subdomains var model = new Model(); int subdomainID = 0; model.SubdomainsDictionary.Add(subdomainID, new Subdomain(subdomainID)); // Materials double youngModulus = 3.76; double poissonRatio = 0.3779; double thickness = 1.0; double nodalLoad = 500.0; var material = new ElasticMaterial2D(StressState2D.PlaneStress) { YoungModulus = youngModulus, PoissonRatio = poissonRatio }; // Nodes var nodes = new Node[] { new Node(id: 1, x: 0.0, y: 0.0, z: 0.0), new Node(id: 2, x: 10.0, y: 0.0, z: 0.0), new Node(id: 3, x: 10.0, y: 10.0, z: 0.0), new Node(id: 4, x: 0.0, y: 10.0, z: 0.0) }; for (int i = 0; i < nodes.Length; ++i) { model.NodesDictionary.Add(i, nodes[i]); } // Elements var factory = new ContinuumElement2DFactory(thickness, material, null); var elementWrapper = new Element() { ID = 0, ElementType = factory.CreateElement(CellType.Quad4, nodes) }; elementWrapper.AddNodes(nodes); model.ElementsDictionary.Add(elementWrapper.ID, elementWrapper); model.SubdomainsDictionary[subdomainID].Elements.Add(elementWrapper); //var a = quad.StiffnessMatrix(element); // Prescribed displacements model.NodesDictionary[0].Constraints.Add(new Constraint() { DOF = StructuralDof.TranslationX, Amount = 0.0 }); model.NodesDictionary[0].Constraints.Add(new Constraint() { DOF = StructuralDof.TranslationY, Amount = 0.0 }); model.NodesDictionary[3].Constraints.Add(new Constraint() { DOF = StructuralDof.TranslationX, Amount = 0.0 }); model.NodesDictionary[3].Constraints.Add(new Constraint() { DOF = StructuralDof.TranslationY, Amount = 0.0 }); // Nodal loads model.Loads.Add(new Load() { Amount = nodalLoad, Node = model.NodesDictionary[1], DOF = StructuralDof.TranslationX }); model.Loads.Add(new Load() { Amount = nodalLoad, Node = model.NodesDictionary[2], DOF = StructuralDof.TranslationX }); // Solver var pcgBuilder = new PcgAlgorithm.Builder(); pcgBuilder.ResidualTolerance = 1E-6; pcgBuilder.MaxIterationsProvider = new PercentageMaxIterationsProvider(0.5); var solverBuilder = new PcgSolver.Builder(); solverBuilder.PcgAlgorithm = pcgBuilder.Build(); PcgSolver solver = solverBuilder.BuildSolver(model); // Problem type var provider = new ProblemStructural(model, solver); // Analyzers var childAnalyzer = new LinearAnalyzer(model, solver, provider); var parentAnalyzer = new StaticAnalyzer(model, solver, provider, childAnalyzer); //NewmarkDynamicAnalyzer parentAnalyzer = new NewmarkDynamicAnalyzer(provider, childAnalyzer, linearSystems, 0.25, 0.5, 0.28, 3.36); // Request output childAnalyzer.LogFactories[subdomainID] = new LinearAnalyzerLogFactory(new int[] { 0 }); // Run the anlaysis parentAnalyzer.Initialize(); parentAnalyzer.Solve(); // Check output DOFSLog log = (DOFSLog)childAnalyzer.Logs[subdomainID][0]; //There is a list of logs for each subdomain and we want the first one Assert.Equal(253.132375961535, log.DOFValues[0], 8); }