private Vector CreateInterfaceProblemRhs(FetiDPFlexibilityMatrix flexibility,
                                                 IFetiDPCoarseProblemSolver coarseProblemSolver, Vector globalFcStar, Vector dr)
        {
            // rhs = dr - FIrc * inv(KccStar) * fcStar
            Vector rhs = coarseProblemSolver.MultiplyInverseCoarseProblemMatrixTimes(globalFcStar);

            rhs = flexibility.MultiplyFIrc(rhs);
            rhs = dr - rhs;
            return(rhs);
        }
 internal InterfaceProblemMatrix(FetiDPFlexibilityMatrix flexibility, IFetiDPCoarseProblemSolver coarseProblemSolver)
 {
     this.flexibility         = flexibility;
     this.coarseProblemSolver = coarseProblemSolver;
 }
        public (Vector lagrangeMultipliers, Vector cornerDisplacements) SolveInterfaceProblem(FetiDPFlexibilityMatrix flexibility,
                                                                                              IFetiPreconditioner preconditioner, IFetiDPCoarseProblemSolver coarseProblemSolver,
                                                                                              Vector globalFcStar, Vector dr, double globalForcesNorm, SolverLogger logger)
        {
            int systemOrder = flexibility.Order;

            // Matrix, preconditioner & rhs
            var    pcgMatrix         = new InterfaceProblemMatrix(flexibility, coarseProblemSolver);
            var    pcgPreconditioner = new InterfaceProblemPreconditioner(preconditioner);
            Vector pcgRhs            = CreateInterfaceProblemRhs(flexibility, coarseProblemSolver, globalFcStar, dr);

            // 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(); //TODO: perhaps use the pcg from the previous analysis if it has reorthogonalization.
            var                 lagranges = Vector.CreateZero(systemOrder);
            IterativeStatistics stats     = pcg.Solve(pcgMatrix, pcgPreconditioner, pcgRhs, lagranges, true,
                                                      () => Vector.CreateZero(systemOrder));

            // Log statistics about PCG execution
            if (!stats.HasConverged)
            {
                throw new IterativeSolverNotConvergedException(FetiDPSolver.name + " did not converge to a solution. PCG"
                                                               + $" algorithm run for {stats.NumIterationsRequired} iterations and the residual norm ratio was"
                                                               + $" {stats.ResidualNormRatioEstimation}");
            }
            logger.LogIterativeAlgorithm(stats.NumIterationsRequired, stats.ResidualNormRatioEstimation);

            // Calculate corner displacements: uc = inv(KccStar) * (fcStar + FIrc^T * lagranges)
            Vector uc = flexibility.MultiplyTransposedFIrc(lagranges);

            uc.AddIntoThis(globalFcStar);
            uc = coarseProblemSolver.MultiplyInverseCoarseProblemMatrixTimes(uc);

            return(lagranges, uc);
        }
Example #4
0
        private FetiDPSolver(IModel model, ICornerNodeSelection cornerNodeSelection,
                             IFetiDPSubdomainMatrixManagerFactory matrixManagerFactory, IDofOrderer dofOrderer,
                             IFetiPreconditionerFactory preconditionerFactory, bool problemIsHomogeneous,
                             IFetiDPInterfaceProblemSolver interfaceProblemSolver)
        {
            // Model
            if (model.Subdomains.Count == 1)
            {
                throw new InvalidSolverException(
                          $"{name} cannot be used if there is only 1 subdomain");
            }
            this.model = model;
            this.cornerNodeSelection = cornerNodeSelection;

            // Subdomains
            subdomains = new Dictionary <int, ISubdomain>();
            foreach (ISubdomain subdomain in model.Subdomains)
            {
                subdomains[subdomain.ID] = subdomain;
            }

            // Matrix managers and linear systems
            matrixManagers        = new Dictionary <int, IFetiDPSubdomainMatrixManager>();
            matrixManagersGeneral = new Dictionary <int, IFetiSubdomainMatrixManager>();
            this.linearSystems    = new Dictionary <int, ISingleSubdomainLinearSystem>();
            var externalLinearSystems = new Dictionary <int, ILinearSystem>();

            foreach (ISubdomain subdomain in model.Subdomains)
            {
                int s             = subdomain.ID;
                var matrixManager = matrixManagerFactory.CreateMatricesManager(subdomain);
                matrixManagers[s]        = matrixManager;
                matrixManagersGeneral[s] = matrixManager;
                this.linearSystems[s]    = matrixManager.LinearSystem;
                externalLinearSystems[s] = matrixManager.LinearSystem;

                //TODO: This will call HandleMatrixWillBeSet() once for each subdomain. For now I will clear the data when
                //      BuildMatrices() is called. Redesign this.
                //matrixManager.LinearSystem.MatrixObservers.Add(this);
            }
            LinearSystems = externalLinearSystems;

            this.dofOrderer            = dofOrderer;
            this.dofSeparator          = new FetiDPDofSeparator();
            this.preconditionerFactory = preconditionerFactory;

            // Interface problem
            this.coarseProblemSolver    = matrixManagerFactory.CreateCoarseProblemSolver(model.Subdomains);
            this.interfaceProblemSolver = interfaceProblemSolver;

            // Homogeneous/heterogeneous problems
            this.problemIsHomogeneous = problemIsHomogeneous;
            if (problemIsHomogeneous)
            {
                this.stiffnessDistribution = new HomogeneousStiffnessDistribution(model, dofSeparator);
            }
            else
            {
                this.stiffnessDistribution = new HeterogeneousStiffnessDistribution(model, dofSeparator);
            }
        }