Пример #1
0
        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.
        }
Пример #2
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();
        }