public void HandleMatrixWillBeSet() { isStiffnessModified = true; foreach (ISubdomain subdomain in subdomains.Values) { if (subdomain.StiffnessModified) { Debug.WriteLine($"{this.GetType().Name}: Clearing saved matrices of subdomain {subdomain.ID}."); matrixManagers[subdomain.ID].Clear(); } } flexibility = null; preconditioner = null; coarseProblemSolver.ClearCoarseProblemMatrix(); //stiffnessDistribution = null; //WARNING: do not dispose of this. It is updated when BuildGlobalMatrix() is called. }
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(); }