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; projection = null; //stiffnessDistribution = null; //WARNING: do not dispose of this. It is updated when BuildGlobalMatrix() is called. }
public void Solve() { var watch = new Stopwatch(); foreach (ISingleSubdomainLinearSystem linearSystem in linearSystems.Values) { if (linearSystem.Solution == null) { linearSystem.SolutionConcrete = linearSystem.CreateZeroVectorConcrete(); } } // Calculate generalized inverses and rigid body modes of subdomains to assemble the interface flexibility matrix. if (isStiffnessModified) { // 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); // Invert each subdomain's Kff watch.Restart(); foreach (int s in subdomains.Keys) { if (subdomains[s].StiffnessModified) { Debug.WriteLine($"{this.GetType().Name}: Inverting the free-free stiffness matrix of subdomain {s}" + (factorizeInPlace ? " in place.": " using extra memory.")); matrixManagers[s].InvertKff(factorPivotTolerances[s], factorizeInPlace); } } watch.Stop(); Logger.LogTaskDuration("Matrix factorization", watch.ElapsedMilliseconds); watch.Restart(); BuildProjection(); flexibility = new Feti1FlexibilityMatrix(matrixManagers, lagrangeEnumerator); watch.Stop(); Logger.LogTaskDuration("Setting up interface problem", watch.ElapsedMilliseconds); watch.Reset(); isStiffnessModified = false; } // Calculate the rhs vectors of the interface system watch.Start(); Vector disconnectedDisplacements = CalcDisconnectedDisplacements(); Vector rbmWork = CalcRigidBodyModesWork(); double globalForcesNorm = CalcGlobalForcesNorm(); watch.Stop(); Logger.LogTaskDuration("Setting up interface problem", watch.ElapsedMilliseconds); // Solve the interface problem watch.Restart(); Vector lagranges = interfaceProblemSolver.CalcLagrangeMultipliers(flexibility, preconditioner, projection, disconnectedDisplacements, rbmWork, globalForcesNorm, Logger); watch.Stop(); Logger.LogTaskDuration("Solving interface problem", watch.ElapsedMilliseconds); // Calculate the displacements of each subdomain watch.Restart(); Vector rbmCoeffs = CalcRigidBodyModesCoefficients(disconnectedDisplacements, lagranges); Dictionary <int, Vector> actualDisplacements = CalcActualDisplacements(lagranges, rbmCoeffs); foreach (var idSystem in linearSystems) { idSystem.Value.SolutionConcrete = actualDisplacements[idSystem.Key]; } watch.Stop(); Logger.LogTaskDuration("Calculate displacements from lagrange multipliers", watch.ElapsedMilliseconds); Logger.IncrementAnalysisStep(); }