private static (IVectorView U, SolverLogger logger) SolveModelWithSubdomains(int numElementsX, int numElementsY,
                                                                                     double factorizationTolerance)
        {
            Model multiSubdomainModel = CreateModel(numElementsX, numElementsY);

            // 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);

            //solverBuilder.PreconditionerFactory = new LumpedPreconditioner.Factory();
            solverBuilder.PreconditionerFactory = new DirichletPreconditioner.Factory();
            solverBuilder.ProblemIsHomogeneous  = true;
            Feti1Solver fetiSolver = solverBuilder.BuildSolver(multiSubdomainModel);

            // Linear static analysis
            var provider       = new ProblemStructural(multiSubdomainModel, fetiSolver);
            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;
            }
            return(fetiSolver.GatherGlobalDisplacements(sudomainDisplacements), fetiSolver.Logger);
        }
Exemple #2
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);
        }