示例#1
0
            //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);
            }
示例#2
0
        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);
        }
示例#3
0
        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);
        }