//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());
        }
Exemplo n.º 2
0
        /// <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);
        }
Exemplo n.º 3
0
        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);
            }
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 7
0
        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();
        }