Ejemplo n.º 1
0
        public static void TestSolver()
        {
            // Setup the model
            double stiffnessRatio = 1E-2; // Do not change this! The expected solution is taken for this value
            Model  model          = CreateModel(stiffnessRatio);
            Dictionary <int, HashSet <INode> > cornerNodes = Quads4x4MappingMatricesTests.DefineCornerNodes(model);

            // Setup solver
            var interfaceSolverBuilder = new FetiDPInterfaceProblemSolver.Builder();

            interfaceSolverBuilder.PcgConvergenceTolerance = 1E-7;
            //var fetiMatrices = new SkylineFetiDPSubdomainMatrixManager.Factory();
            var fetiMatrices        = new DenseFetiDPSubdomainMatrixManager.Factory();
            var cornerNodeSelection = new UsedDefinedCornerNodes(cornerNodes);
            var fetiSolverBuilder   = new FetiDPSolver.Builder(cornerNodeSelection, fetiMatrices);

            fetiSolverBuilder.InterfaceProblemSolver = interfaceSolverBuilder.Build();
            fetiSolverBuilder.ProblemIsHomogeneous   = false;
            fetiSolverBuilder.PreconditionerFactory  = new DirichletPreconditioner.Factory();
            FetiDPSolver fetiSolver = fetiSolverBuilder.BuildSolver(model);

            // Run the analysis
            var problem        = new ProblemStructural(model, fetiSolver);
            var linearAnalyzer = new LinearAnalyzer(model, fetiSolver, problem);
            var staticAnalyzer = new StaticAnalyzer(model, fetiSolver, problem, linearAnalyzer);

            staticAnalyzer.Initialize();
            staticAnalyzer.Solve();

            // Gather the global displacements
            var sudomainDisplacements = new Dictionary <int, IVectorView>();

            foreach (var ls in fetiSolver.LinearSystems)
            {
                sudomainDisplacements[ls.Key] = ls.Value.Solution;
            }
            Vector globalU = fetiSolver.GatherGlobalDisplacements(sudomainDisplacements);

            // Check against expected solution
            double tol             = 1E-7;
            var    globalUExpected = Vector.CreateFromArray(new double[]
            {
                17.623494584618864, 12.564560593215612, 31.832863897135404, 34.496634608059082, 40.255481382985629,
                66.49190654178912, 42.572002358887204, 99.798764204232072, 4.267568672307144, 9.00506902466324,
                9.100928263505315, 31.107370029452451, 12.1615036308774, 66.065492717632239, 11.510673148931499,
                102.06649895017948, -3.0529124682202156, 9.24107474483673, -7.8531777412741217, 26.728892403726846,
                -16.890006178831449, 70.602493468916791, -21.80233265288679, 109.39882637058051, -4.7311061272016808,
                10.030926199331375, -5.6722429958962142, 18.837815470700932, 146.94209278892487, 392.04674590737193,
                -35.619167413693908, 1407.200332011206, -9.9609496807814057, 10.46574373452243, -17.603838651152756,
                20.760800663270086, -843.13592713307355, 371.10700308359418, -1666.2547486301742, 3714.1637893447919
            });

            Assert.True(globalUExpected.Equals(globalU, tol));
        }
        private static (IVectorView globalDisplacements, SolverLogger logger) SolveModelWithSubdomains(double stiffnessRatio,
                                                                                                       Precond precond, Residual residualConvergence, double pcgConvergenceTolerance)
        {
            // Model
            Model multiSubdomainModel = CreateModel(stiffnessRatio);

            // Corner nodes
            double meshTol = 1E-6;
            var    cornerNodesOfEachSubdomain = new Dictionary <int, HashSet <INode> >();

            foreach (Subdomain subdomain in multiSubdomainModel.Subdomains)
            {
                subdomain.DefineNodesFromElements(); //TODO: This will also be called by the analyzer.
                INode[] corners     = CornerNodeUtilities.FindCornersOfRectangle2D(subdomain);
                var     cornerNodes = new HashSet <INode>();
                foreach (INode node in corners)
                {
                    if (node.Constraints.Count > 0)
                    {
                        continue;
                    }
                    if ((Math.Abs(node.X - domainLengthX) <= meshTol) && (Math.Abs(node.Y) <= meshTol))
                    {
                        continue;
                    }
                    if ((Math.Abs(node.X - domainLengthX) <= meshTol) && (Math.Abs(node.Y - domainLengthY) <= meshTol))
                    {
                        continue;
                    }
                    cornerNodes.Add(node);
                }
                cornerNodesOfEachSubdomain[subdomain.ID] = cornerNodes;
            }

            // Solver
            var fetiMatrices = new SkylineFetiDPSubdomainMatrixManager.Factory(new OrderingAmdSuiteSparse());
            //var fetiMatrices = new SkylineFetiDPSubdomainMatrixManager.Factory();
            //var fetiMatrices = new DenseFetiDPSubdomainMatrixManager.Factory();
            var cornerNodeSelection = new UsedDefinedCornerNodes(cornerNodesOfEachSubdomain);
            var solverBuilder       = new FetiDPSolver.Builder(cornerNodeSelection, fetiMatrices);

            solverBuilder.ProblemIsHomogeneous = stiffnessRatio == 1.0;
            //solverBuilder.ProblemIsHomogeneous = 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();
            }

            //TODO: This needs to be implemented for FETI-DP
            //// PCG may need to use the exact residual for the comparison with the expected values
            //bool residualIsExact = residualConvergence == Residual.Exact;
            //ExactPcpgConvergence.Factory exactResidualConvergence = null;
            //if (residualIsExact)
            //{
            //    exactResidualConvergence = new ExactPcpgConvergence.Factory(
            //        CreateSingleSubdomainModel(stiffnessRatio), solverBuilder.DofOrderer,
            //            (model, solver) => new ProblemStructural(model, solver));
            //}
            //if (residualIsExact) exactResidualConvergence.InterfaceProblemSolver = interfaceProblemSolver;

            // Specify solver for the interface problem
            var interfaceSolverBuilder = new FetiDPInterfaceProblemSolver.Builder();

            interfaceSolverBuilder.PcgConvergenceStrategyFactory = new ApproximateResidualConvergence.Factory();
            interfaceSolverBuilder.PcgConvergenceTolerance       = pcgConvergenceTolerance;
            solverBuilder.InterfaceProblemSolver = interfaceSolverBuilder.Build();

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

            return(globalDisplacements, fetiSolver.Logger);
        }