//TODO: Use Skyline assembler private SkylineMatrix CreateGlobalKccStar(Dictionary <int, HashSet <INode> > cornerNodesOfSubdomains, FetiDPDofSeparator dofSeparator, Dictionary <int, IFetiDPSubdomainMatrixManager> matrixManagers) { int[] skylineColHeights = FindSkylineColumnHeights(cornerNodesOfSubdomains, dofSeparator); var skylineBuilder = SkylineBuilder.Create(dofSeparator.NumGlobalCornerDofs, skylineColHeights); for (int s = 0; s < subdomains.Count; ++s) { IFetiDPSubdomainMatrixManager matrices = matrixManagers[s]; // KccStar[s] = Kcc[s] - Krc[s]^T * inv(Krr[s]) * Krc[s] if (subdomains[s].StiffnessModified) { Debug.WriteLine($"{this.GetType().Name}: Calculating Schur complement of remainder dofs" + " for the stiffness of subdomain {s}"); matrices.CalcSchurComplementOfRemainderDofs(); //TODO: At this point Kcc and Krc can be cleared. Maybe Krr too. } int[] subdomainToGlobalIndices = dofSeparator.CornerBooleanMatrices[s].GetRowsToColumnsMap(); IMatrixView subdomainMatrix = matrices.SchurComplementOfRemainderDofs; skylineBuilder.AddSubmatrixSymmetric(subdomainMatrix, subdomainToGlobalIndices); } return(skylineBuilder.BuildSkylineMatrix()); }
/// <summary> /// Does not mutate this object. /// </summary> internal Dictionary <int, Vector> CalcActualDisplacements(Vector lagranges, Vector cornerDisplacements, Dictionary <int, Vector> fr) { var freeDisplacements = new Dictionary <int, Vector>(); foreach (int s in subdomains.Keys) { IFetiDPSubdomainMatrixManager matrices = matrixManagers[s]; // ur[s] = inv(Krr[s]) * (fr[s] - Br[s]^T * lagranges - Krc[s] * Lc[s] * uc) Vector BrLambda = lagrangeEnumerator.BooleanMatrices[s].Multiply(lagranges, true); Vector KrcLcUc = dofSeparator.CornerBooleanMatrices[s].Multiply(cornerDisplacements); KrcLcUc = matrices.MultiplyKrcTimes(KrcLcUc); Vector temp = fr[s].Copy(); temp.SubtractIntoThis(BrLambda); temp.SubtractIntoThis(KrcLcUc); Vector ur = matrices.MultiplyInverseKrrTimes(temp); // uf[s] = union(ur[s], ubc[s]) // Remainder dofs var uf = Vector.CreateZero(subdomains[s].FreeDofOrdering.NumFreeDofs); int[] remainderDofs = dofSeparator.RemainderDofIndices[s]; uf.CopyNonContiguouslyFrom(remainderDofs, ur); // Corner dofs: ubc[s] = Bc[s] * uc Vector ubc = dofSeparator.CornerBooleanMatrices[s].Multiply(cornerDisplacements); int[] cornerDofs = dofSeparator.CornerDofIndices[s]; uf.CopyNonContiguouslyFrom(cornerDofs, ubc); freeDisplacements[s] = uf; } return(freeDisplacements); }
public void MultiplyFIrr(Vector lhs, Vector rhs) { Preconditions.CheckMultiplicationDimensions(Order, lhs.Length); Preconditions.CheckSystemSolutionDimensions(Order, rhs.Length); // FIrr[s] * x = sum_over_s( Br[s] * (inv(Krr[s]) * (Br[s]^T * x)) ) rhs.Clear(); foreach (int s in Br.Keys) { IFetiDPSubdomainMatrixManager matrices = matrixManagers[s]; Vector temp = Br[s].Multiply(lhs, true); temp = matrices.MultiplyInverseKrrTimes(temp); temp = Br[s].Multiply(temp); rhs.AddIntoThis(temp); } }
public Vector MultiplyTransposedFIrc(Vector vector) { Preconditions.CheckMultiplicationDimensions(Order, vector.Length); // FIrc[s]^T * x = sum_over_s( Lc[s]^T * (Krc[s]^T * (inv(Krr[s]) * (Br[s]^T * x))) ) var result = Vector.CreateZero(numCornerDofs); foreach (int s in Br.Keys) { IFetiDPSubdomainMatrixManager matrices = matrixManagers[s]; Vector temp = Br[s].Multiply(vector, true); temp = matrices.MultiplyInverseKrrTimes(temp); temp = matrices.MultiplyKcrTimes(temp); temp = Lc[s].Multiply(temp, true); result.AddIntoThis(temp); } return(result); }
public Vector CreateCoarseProblemRhs(FetiDPDofSeparator dofSeparator, Dictionary <int, IFetiDPSubdomainMatrixManager> matrixManagers, Dictionary <int, Vector> fr, Dictionary <int, Vector> fbc) { // Static condensation for the force vectors var globalFcStar = Vector.CreateZero(dofSeparator.NumGlobalCornerDofs); for (int s = 0; s < subdomains.Count; ++s) { IFetiDPSubdomainMatrixManager matrices = matrixManagers[s]; // fcStar[s] = fbc[s] - Krc[s]^T * inv(Krr[s]) * fr[s] // globalFcStar = sum_over_s(Lc[s]^T * fcStar[s]) UnsignedBooleanMatrix Lc = dofSeparator.CornerBooleanMatrices[s]; Vector temp = matrices.MultiplyInverseKrrTimes(fr[s]); temp = matrices.MultiplyKcrTimes(temp); Vector fcStar = fbc[s] - temp; globalFcStar.AddIntoThis(Lc.Multiply(fcStar, true)); } return(globalFcStar); }
private Matrix CreateGlobalKccStar(FetiDPDofSeparator dofSeparator, Dictionary <int, IFetiDPSubdomainMatrixManager> matrixManagers) { // Static condensation of remainder dofs (Schur complement). var globalKccStar = Matrix.CreateZero(dofSeparator.NumGlobalCornerDofs, dofSeparator.NumGlobalCornerDofs); for (int s = 0; s < subdomains.Count; ++s) { IFetiDPSubdomainMatrixManager matrices = matrixManagers[s]; // KccStar[s] = Kcc[s] - Krc[s]^T * inv(Krr[s]) * Krc[s] if (subdomains[s].StiffnessModified) { Debug.WriteLine($"{this.GetType().Name}: Calculating Schur complement of remainder dofs" + " for the stiffness of subdomain {s}"); matrices.CalcSchurComplementOfRemainderDofs(); //TODO: At this point Kcc and Krc can be cleared. Maybe Krr too. } // globalKccStar = sum_over_s(Lc[s]^T * KccStar[s] * Lc[s]) UnsignedBooleanMatrix Lc = dofSeparator.CornerBooleanMatrices[s]; globalKccStar.AddIntoThis(Lc.ThisTransposeTimesOtherTimesThis(matrices.SchurComplementOfRemainderDofs)); } return(globalKccStar); }
public void Solve() { var watch = new Stopwatch(); foreach (var linearSystem in linearSystems.Values) { if (linearSystem.SolutionConcrete == null) { linearSystem.SolutionConcrete = linearSystem.CreateZeroVectorConcrete(); } } // Separate the force vector watch.Start(); var fr = new Dictionary <int, Vector>(); var fbc = new Dictionary <int, Vector>(); foreach (int s in subdomains.Keys) { int[] remainderDofs = dofSeparator.RemainderDofIndices[s]; int[] cornerDofs = dofSeparator.CornerDofIndices[s]; Vector f = linearSystems[s].RhsConcrete; fr[s] = f.GetSubvector(remainderDofs); fbc[s] = f.GetSubvector(cornerDofs); } watch.Stop(); Logger.LogTaskDuration("Separating vectors & matrices", watch.ElapsedMilliseconds); watch.Reset(); if (isStiffnessModified) { // Separate the stiffness matrix watch.Start(); foreach (int s in subdomains.Keys) { if (!subdomains[s].StiffnessModified) { continue; } IFetiDPSubdomainMatrixManager matrices = matrixManagers[s]; int[] remainderDofs = dofSeparator.RemainderDofIndices[s]; int[] cornerDofs = dofSeparator.CornerDofIndices[s]; matrices.ExtractKrr(remainderDofs); matrices.ExtractKcrKrc(cornerDofs, remainderDofs); matrices.ExtractKcc(cornerDofs); } watch.Stop(); Logger.LogTaskDuration("Separating vectors & matrices", watch.ElapsedMilliseconds); // Reorder internal dofs if needed by the preconditioner. TODO: Should I have done this previously in Initialize()? watch.Start(); if (preconditionerFactory.ReorderInternalDofsForFactorization) { foreach (ISubdomain subdomain in model.Subdomains) { if (subdomain.ConnectivityModified) { Debug.WriteLine($"{this.GetType().Name}: Reordering internal dofs of subdomain {subdomain.ID}."); matrixManagers[subdomain.ID].ReorderInternalDofs(dofSeparator, subdomain); } } } // Calculate the preconditioner before factorizing each subdomain's Kff preconditioner = preconditionerFactory.CreatePreconditioner(model, stiffnessDistribution, dofSeparator, lagrangeEnumerator, matrixManagersGeneral); watch.Stop(); Logger.LogTaskDuration("Calculating preconditioner", watch.ElapsedMilliseconds); // Factorize each subdomain's Krr watch.Restart(); foreach (int s in subdomains.Keys) { if (!subdomains[s].StiffnessModified) { continue; } //TODO: If I can reuse Krr, I can also reuse its factorization. Therefore this must be inPlace. In contrast, FETI-1 needs Kff intact for Stiffness distribution, in the current design). Debug.WriteLine( $"{this.GetType().Name}: Inverting the remainder-remainder stiffness matrix of subdomain {s} in place."); matrixManagers[s].InvertKrr(true); } watch.Stop(); Logger.LogTaskDuration("Matrix factorization", watch.ElapsedMilliseconds); // Define FETI-DP flexibility matrices watch.Restart(); flexibility = new FetiDPFlexibilityMatrix(dofSeparator, lagrangeEnumerator, matrixManagers); // Static condensation of remainder dofs (Schur complement). coarseProblemSolver.CreateAndInvertCoarseProblemMatrix(CornerNodesOfSubdomains, dofSeparator, matrixManagers); watch.Stop(); Logger.LogTaskDuration("Setting up interface problem", watch.ElapsedMilliseconds); watch.Reset(); isStiffnessModified = false; } // Static condensation for the force vectors watch.Start(); Vector globalFcStar = coarseProblemSolver.CreateCoarseProblemRhs(dofSeparator, matrixManagers, fr, fbc); // Calculate the rhs vectors of the interface system Vector dr = CalcDisconnectedDisplacements(fr); double globalForcesNorm = CalcGlobalForcesNorm(); watch.Stop(); Logger.LogTaskDuration("Setting up interface problem", watch.ElapsedMilliseconds); // Solve the interface problem watch.Restart(); (Vector lagranges, Vector uc) = interfaceProblemSolver.SolveInterfaceProblem(flexibility, preconditioner, coarseProblemSolver, globalFcStar, dr, globalForcesNorm, Logger); watch.Stop(); Logger.LogTaskDuration("Solving interface problem", watch.ElapsedMilliseconds); // Calculate the displacements of each subdomain watch.Restart(); Dictionary <int, Vector> actualDisplacements = CalcActualDisplacements(lagranges, uc, fr); foreach (var idSystem in linearSystems) { idSystem.Value.SolutionConcrete = actualDisplacements[idSystem.Key]; } watch.Stop(); Logger.LogTaskDuration("Calculate displacements from lagrange multipliers", watch.ElapsedMilliseconds); Logger.IncrementAnalysisStep(); }