// Stiffness ratio = 1E-6 //[InlineData(1E-6, InterfaceSolver.Method1, Precond.Dirichlet, MatrixQ.Identity, Residual.Exact, 40)] // converges, stagnates almost before the tolerance and then diverges //[InlineData(1E-6, InterfaceSolver.Method2, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 9)] // converges, stagnates almost before the tolerance and then diverges //[InlineData(1E-6, InterfaceSolver.Method3, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 23)] //3 //[InlineData(1E-6, InterfaceSolver.Method4, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 9)] // converges, stagnates almost before the tolerance and then diverges //[InlineData(1E-6, InterfaceSolver.Default, Precond.Dirichlet, MatrixQ.Precond, Residual.Approximate, 9)] public static void Run(double stiffnessRatio, InterfaceSolver interfaceSolver, Precond precond, MatrixQ q, Residual convergence, int iterExpected) { //InterfaceSolver interfaceSolver = 0; double factorizationTol = 1E-3, pcpgConvergenceTol = 1E-5; IVectorView directDisplacements = SolveModelWithoutSubdomains(stiffnessRatio); (IVectorView ddDisplacements, SolverLogger logger, int numUniqueGlobalDofs, int numExtenedDomainDofs) = SolveModelWithSubdomains(stiffnessRatio, interfaceSolver, precond, q, convergence, factorizationTol, pcpgConvergenceTol); double normalizedError = directDisplacements.Subtract(ddDisplacements).Norm2() / directDisplacements.Norm2(); int analysisStep = 0; Assert.Equal(882, numUniqueGlobalDofs); // 882 includes constrained and free dofs Assert.Equal(1056, numExtenedDomainDofs); // 1056 includes constrained and free dofs Assert.Equal(190, logger.GetNumDofs(analysisStep, "Lagrange multipliers")); // The error is provided in the reference solution the, but it is almost impossible for two different codes run on // different machines to achieve the exact same accuracy. Assert.Equal(0.0, normalizedError, 5); // Allow a tolerance: It is ok if my solver is better or off by 1 iteration int pcgIterations = logger.GetNumIterationsOfIterativeAlgorithm(analysisStep); Assert.InRange(pcgIterations, 1, iterExpected + 1); // the upper bound is inclusive! }
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); }