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); }
public static void TestScalingMatrices() { #region Replace the next with hardcoded matrices and mocking objects // Run the analysis so that all objects are created // 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 DenseFetiDPSubdomainMatrixManager.Factory(); var cornerNodeSelection = new UsedDefinedCornerNodes(cornerNodes); var fetiSolverBuilder = new FetiDPSolver.Builder(cornerNodeSelection, fetiMatrices); fetiSolverBuilder.InterfaceProblemSolver = interfaceSolverBuilder.Build(); fetiSolverBuilder.ProblemIsHomogeneous = false; var preconditionerFactory = new DirichletPreconditioner.Factory(); fetiSolverBuilder.PreconditionerFactory = preconditionerFactory; 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(); #endregion // Access private fields of FetiDPSolver and DirichletPreconditioner.Factory using reflection FieldInfo fi = typeof(FetiDPSolver).GetField("lagrangeEnumerator", BindingFlags.NonPublic | BindingFlags.Instance); var lagrangeEnumerator = (FetiDPLagrangeMultipliersEnumerator)fi.GetValue(fetiSolver); fi = typeof(FetiDPSolver).GetField("dofSeparator", BindingFlags.NonPublic | BindingFlags.Instance); var dofSeparator = (FetiDPDofSeparator)fi.GetValue(fetiSolver); fi = typeof(FetiDPSolver).GetField("stiffnessDistribution", BindingFlags.NonPublic | BindingFlags.Instance); var stiffnessDistribution = (IStiffnessDistribution)fi.GetValue(fetiSolver); MethodInfo method = preconditionerFactory.GetType().GetMethod("CalcBoundaryPreconditioningBooleanMatrices", BindingFlags.NonPublic | BindingFlags.Instance); var Bpbr = (Dictionary <int, IMappingMatrix>)method.Invoke(preconditionerFactory, new object[] { stiffnessDistribution, dofSeparator, lagrangeEnumerator }); // Compare the mapping matrices against the expected ones var expectedBpbr = new Dictionary <int, Matrix>(); expectedBpbr[0] = Matrix.CreateFromArray(new double[, ] { { 0.5, 0, 0, 0 }, { 0, 0.5, 0, 0 }, { 0, 0, 0.5, 0 }, { 0, 0, 0, 0.5 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }); expectedBpbr[1] = Matrix.CreateFromArray(new double[, ] { { -0.5, 0, 0, 0 }, { 0, -0.5, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0.00990099009900990, 0 }, { 0, 0, 0, 0.00990099009900990 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }); expectedBpbr[2] = Matrix.CreateFromArray(new double[, ] { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { -0.5, 0, 0, 0 }, { 0, -0.5, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0.00990099009900990, 0 }, { 0, 0, 0, 0.00990099009900990 } }); expectedBpbr[3] = Matrix.CreateFromArray(new double[, ] { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { -0.990099009900990, 0, 0, 0 }, { 0, -0.990099009900990, 0, 0 }, { 0, 0, -0.990099009900990, 0 }, { 0, 0, 0, -0.990099009900990 } }); double tol = 1E-13; foreach (int s in expectedBpbr.Keys) { Matrix explicitBpr = Bpbr[s].MultiplyRight(Matrix.CreateIdentity(Bpbr[s].NumColumns)); Assert.True(expectedBpbr[s].Equals(explicitBpr, tol)); } }