예제 #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;
     projection     = null;
     //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 (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();
        }