private PcgMatrix DefinePcgMatrix(Feti1FlexibilityMatrix flexibility, Feti1Projection projection) { //TODO: projection.ProjectVector() overwrites the rhs vector passed in. However that is not clear by the method. // I should either always return the resulting vector (negating any optimizations) or set the convention that // vectors passed in as results will always be overwritten. The latter forces the method that accepts them to // clear them (if the method needs to), which is not needed if the resulting vector has just be initialized to 0. if (projectionSideMatrix == ProjectionSide.Left) { // A * x = (P^T * F) * x = P^T * (F * x) return(new PcgMatrix(flexibility.Order, (x, y) => projection.ProjectVector(flexibility.Multiply(x), y, true))); } else if (projectionSideMatrix == ProjectionSide.Both) { // A * x = (P^T * F * P) * x = P^T * (F * (P * x)) return(new PcgMatrix(flexibility.Order, (x, y) => { var temp = Vector.CreateZero(flexibility.Order); projection.ProjectVector(x, temp, false); projection.ProjectVector(flexibility.Multiply(temp), y, true); })); } else { throw new ArgumentException("The FETI-1 flexibility matrix can be multiplied from the left or both sides."); } }
private readonly Vector lagrangesParticular; // only needed when separating the lagranges during PCG public ExactFeti1PcgConvergence(IMatrixView globalStiffness, IVectorView globalForces, double globalForcesNorm, Feti1Solver fetiSolver, Feti1ProjectedInterfaceProblemSolver interfaceProblemSolver, Feti1Projection projection, Vector lagrangesParticular) { this.globalStiffness = globalStiffness; this.globalForces = globalForces; this.globalForcesNorm = globalForcesNorm; this.fetiSolver = fetiSolver; this.interfaceProblemSolver = interfaceProblemSolver; this.projection = projection; this.lagrangesParticular = lagrangesParticular; }
private void BuildProjection() { if (!projectionMatrixQIsIdentity) // Previously (pde == PdeOrder.Fourth) || (!problemIsHomogeneous) { // Q = preconditioner projection = new Feti1Projection(lagrangeEnumerator.BooleanMatrices, matrixManagers, new PreconditionerAsMatrixQ(preconditioner)); } else { // Q = indentity projection = new Feti1Projection(lagrangeEnumerator.BooleanMatrices, matrixManagers, new IdentityMatrixQ()); } projection.InvertCoarseProblemMatrix(); }
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 Vector CalcLagrangeMultipliers(Feti1FlexibilityMatrix flexibility, IFetiPreconditioner preconditioner, Feti1Projection projection, Vector disconnectedDisplacements, Vector rigidBodyModesWork, double globalForcesNorm, SolverLogger logger) { int systemOrder = flexibility.Order; PcgMatrix pcgMatrix = DefinePcgMatrix(flexibility, projection); PcgPreconditioner pcgPreconditioner = DefinePcgPreconditioner(preconditioner, projection); // λ0 = Q * G * inv(G^T * Q * G) * e Vector lagrangesParticular = projection.CalcParticularLagrangeMultipliers(rigidBodyModesWork); // Calculate rhs of the projected interface system: rhs = P^T * (d - F * λ0) var r0 = flexibility.Multiply(lagrangesParticular); r0.LinearCombinationIntoThis(-1.0, disconnectedDisplacements, 1.0); var pcgRhs = Vector.CreateZero(systemOrder); projection.ProjectVector(r0, pcgRhs, true); // Solve the interface problem using PCG algorithm var pcgBuilder = new PcgAlgorithm.Builder(); pcgBuilder.MaxIterationsProvider = maxIterationsProvider; pcgBuilder.ResidualTolerance = pcgConvergenceTolerance; pcgBuilder.Convergence = pcgConvergenceStrategyFactory.CreateConvergenceStrategy(globalForcesNorm); PcgAlgorithm pcg = pcgBuilder.Build(); var lagrangesBar = Vector.CreateZero(systemOrder); IterativeStatistics stats = pcg.Solve(pcgMatrix, pcgPreconditioner, pcgRhs, lagrangesBar, true, () => Vector.CreateZero(systemOrder)); if (!stats.HasConverged) { throw new IterativeSolverNotConvergedException(Feti1Solver.name + " did not converge to a solution. PCG" + $" algorithm run for {stats.NumIterationsRequired} iterations and the residual norm ratio was" + $" {stats.ResidualNormRatioEstimation}"); } // Calculate the actual lagrange multipliers from the separation formula: λ = λ0 + P * λbar var lagranges = Vector.CreateZero(systemOrder); projection.ProjectVector(lagrangesBar, lagranges, false); lagranges.AddIntoThis(lagrangesParticular); // Log statistics about PCG execution logger.LogIterativeAlgorithm(stats.NumIterationsRequired, stats.ResidualNormRatioEstimation); return(lagranges); }
public Vector CalcLagrangeMultipliers(Feti1FlexibilityMatrix flexibility, IFetiPreconditioner preconditioner, Feti1Projection projection, Vector disconnectedDisplacements, Vector rigidBodyModesWork, double globalForcesNorm, SolverLogger logger) { // PCPG starts from the particular lagrange multipliers: λ0 = Q * G * inv(G^T * Q * G) * e Vector lagranges = projection.CalcParticularLagrangeMultipliers(rigidBodyModesWork); IFetiPcgConvergence pcpgConvergenceStrategy = pcgConvergenceStrategyFactory.CreateConvergenceStrategy(globalForcesNorm); var pcpg = new PcpgAlgorithm(maxIterationsProvider, pcpgConvergenceTolerance, pcpgConvergenceStrategy); IterativeStatistics stats = pcpg.Solve(flexibility, preconditioner, projection, disconnectedDisplacements, lagranges); if (!stats.HasConverged) { throw new IterativeSolverNotConvergedException(Feti1Solver.name + " did not converge to a solution. PCPG" + $" algorithm run for {stats.NumIterationsRequired} iterations and the residual norm ratio was" + $" {stats.ResidualNormRatioEstimation}"); } // Log statistics about PCG execution logger.LogIterativeAlgorithm(stats.NumIterationsRequired, stats.ResidualNormRatioEstimation); return(lagranges); }
private PcgPreconditioner DefinePcgPreconditioner(IFetiPreconditioner preconditioner, Feti1Projection projection) { if (projectionSidePreconditioner == ProjectionSide.None) { // x = prec(A) * y => x = prec(F) * y return(new PcgPreconditioner((x, y) => preconditioner.SolveLinearSystem(y, x))); } else if (projectionSidePreconditioner == ProjectionSide.Left) { // x = prec(A) * y => x = (P * prec(F)) * y => x = P * (prec(F) * y) return(new PcgPreconditioner((y, x) => { int order = y.Length; var temp = Vector.CreateZero(order); preconditioner.SolveLinearSystem(y, temp); projection.ProjectVector(temp, x, false); })); } else if (projectionSidePreconditioner == ProjectionSide.Both) { // x = prec(A) * y => x = (P * prec(F) * P^T) * y => x = P * (prec(F) * (P^T * y)) return(new PcgPreconditioner((y, x) => { int order = y.Length; var temp1 = Vector.CreateZero(order); projection.ProjectVector(y, temp1, true); var temp2 = Vector.CreateZero(order); preconditioner.SolveLinearSystem(temp1, temp2); projection.ProjectVector(temp2, x, false); })); } else { throw new ArgumentException( "The FETI-1 preconditioner can be multiplied from the left side, both sides or not at all."); } }
/// <summary> /// Calculates the actual lagrange multipliers depending on the separation formula. /// </summary> internal Vector CombineLagrangeMultipliers(Vector lagrangesParticular, Vector lagrangesBar, Feti1Projection projection) { if (lagrangeSeparation == LagrangeMultiplierSeparation.Simple) { // λ = λ0 + P * λbar return(lagrangesBar + lagrangesParticular); } else if (lagrangeSeparation == LagrangeMultiplierSeparation.WithProjection) { // λ = λ0 + P * λbar var lagranges = Vector.CreateZero(lagrangesBar.Length); projection.ProjectVector(lagrangesBar, lagranges, false); lagranges.AddIntoThis(lagrangesParticular); return(lagranges); } else { throw new ArgumentException("The lagrange separation can only be: a) λ = λ0 + λbar or b) λ = λ0 + P * λbar"); } }