Beispiel #1
0
        public void ReorderRemainderDofs(FetiDPDofSeparator dofSeparator, ISubdomain subdomain)
        {
            if (reordering == null)
            {
                return;                     // Use the natural ordering and do not modify any stored dof data
            }
            try
            {
                int   s             = subdomain.ID;
                int[] remainderDofs = dofSeparator.RemainderDofIndices[s];
                var   pattern       = linearSystem.Matrix.GetSubmatrixSymmetricPattern(remainderDofs);
                (int[] permutation, bool oldToNew) = reordering.FindPermutation(pattern);
                int[] newRemainderDofs = ReorderingUtilities.ReorderKeysOfDofIndicesMap(remainderDofs, permutation, oldToNew);

                // What if the dof separator gets added other state that needs to be updated?
                dofSeparator.RemainderDofIndices[s] = newRemainderDofs;
                dofSeparator.RemainderDofOrderings[s].Reorder(permutation, oldToNew);
            }
            catch (MatrixDataOverwrittenException)
            {
                throw new InvalidOperationException(
                          "The free-free stiffness matrix of this subdomain has been overwritten and cannot be used anymore."
                          + "Try calling this method before factorizing/inverting it.");
            }
        }
        public void ReorderCornerDofs(FetiDPDofSeparator dofSeparator)
        {
            if (reordering == null)
            {
                return;                     // Use the natural ordering and do not modify any stored dof data
            }
            var pattern = SparsityPatternSymmetric.CreateEmpty(dofSeparator.NumGlobalCornerDofs);

            for (int s = 0; s < subdomains.Count; ++s)
            {
                // Treat each subdomain as a superelement with only its corner nodes.
                var localCornerDofOrdering = dofSeparator.SubdomainCornerDofOrderings[s];
                int numLocalCornerDofs     = localCornerDofOrdering.EntryCount;
                var subdomainToGlobalDofs  = new int[numLocalCornerDofs];
                foreach ((INode node, IDofType dofType, int localIdx) in localCornerDofOrdering)
                {
                    int globalIdx = dofSeparator.GlobalCornerDofOrdering[node, dofType];
                    subdomainToGlobalDofs[localIdx] = globalIdx;
                }
                pattern.ConnectIndices(subdomainToGlobalDofs, false);
            }
            (int[] permutation, bool oldToNew) = reordering.FindPermutation(pattern);
            dofSeparator.GlobalCornerDofOrdering.Reorder(permutation, oldToNew);
            dofSeparator.GlobalCornerToFreeDofMap =
                ReorderingUtilities.ReorderKeysOfDofIndicesMap(dofSeparator.GlobalCornerToFreeDofMap, permutation, oldToNew);
        }
        //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());
        }
        public void CreateAndInvertCoarseProblemMatrix(Dictionary <int, HashSet <INode> > cornerNodesOfSubdomains,
                                                       FetiDPDofSeparator dofSeparator, Dictionary <int, IFetiDPSubdomainMatrixManager> matrixManagers)
        {
            SkylineMatrix globalKccStar = CreateGlobalKccStar(cornerNodesOfSubdomains, dofSeparator, matrixManagers);

            this.inverseGlobalKccStar = globalKccStar.FactorLdl(true);
        }
        private int[] FindSkylineColumnHeights(Dictionary <int, HashSet <INode> > cornerNodesOfSubdomains,
                                               FetiDPDofSeparator dofSeparator)
        {
            //only entries above the diagonal count towards the column height
            int[] colHeights = new int[dofSeparator.NumGlobalCornerDofs];
            for (int s = 0; s < subdomains.Count; ++s)
            {
                HashSet <INode> cornerNodes = cornerNodesOfSubdomains[s];

                // To determine the col height, first find the min of the dofs of this element. All these are
                // considered to interact with each other, even if there are 0.0 entries in the element stiffness matrix.
                int minDof = Int32.MaxValue;
                foreach (INode node in cornerNodes)
                {
                    foreach (int dof in dofSeparator.GlobalCornerDofOrdering.GetValuesOfRow(node))
                    {
                        minDof = Math.Min(dof, minDof);
                    }
                }

                // The height of each col is updated for all elements that engage the corresponding dof.
                // The max height is stored.
                foreach (INode node in cornerNodes)
                {
                    foreach (int dof in dofSeparator.GlobalCornerDofOrdering.GetValuesOfRow(node))
                    {
                        colHeights[dof] = Math.Max(colHeights[dof], dof - minDof);
                    }
                }
            }
            return(colHeights);
        }
        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);
        }
Beispiel #7
0
        public void ReorderInternalDofs(FetiDPDofSeparator dofSeparator, ISubdomain subdomain)
        {
            if (reordering == null)
            {
                return;                     // Use the natural ordering and do not modify any stored dof data
            }
            try
            {
                int[] internalDofs = dofSeparator.InternalDofIndices[subdomain.ID];
                var   pattern      = Krr.GetSubmatrixSymmetricPattern(internalDofs);
                (int[] permutation, bool oldToNew) = reordering.FindPermutation(pattern);
                int[] newInternalDofs = ReorderingUtilities.ReorderKeysOfDofIndicesMap(internalDofs, permutation, oldToNew);

                // What if the dof separator gets added other state that needs to be updated?
                dofSeparator.InternalDofIndices[subdomain.ID] = newInternalDofs;
            }
            catch (MatrixDataOverwrittenException)
            {
                throw new InvalidOperationException(
                          "The remainder-remainder stiffness submatrix of this subdomain has been already been calculated and"
                          + " then overwritten and cannot be used anymore. Try calling this method before"
                          + " factorizing/inverting it.");
            }
        }
        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);
        }
 public void ReorderCornerDofs(FetiDPDofSeparator dofSeparator)
 {
     // Do nothing, since the sparsity pattern is irrelevant for dense matrices.
 }
 public void CreateAndInvertCoarseProblemMatrix(Dictionary <int, HashSet <INode> > cornerNodesOfSubdomains,
                                                FetiDPDofSeparator dofSeparator, Dictionary <int, IFetiDPSubdomainMatrixManager> matrixManagers)
 {
     this.inverseGlobalKccStar = CreateGlobalKccStar(dofSeparator, matrixManagers);
     inverseGlobalKccStar.InvertInPlace();
 }
Beispiel #11
0
 public void ReorderRemainderDofs(FetiDPDofSeparator dofSeparator, ISubdomain subdomain)
 {
     // Do nothing, since the sparsity pattern is irrelevant for dense matrices.
 }
Beispiel #12
0
        public static void TestSignedBooleanMatrices()
        {
            // Expected results
            int expectedNumLagrangeMultipliers = 8;
            var expectedBr = new Dictionary <int, Matrix>();

            expectedBr[0]       = Matrix.CreateZero(8, 8);
            expectedBr[0][0, 4] = +1;
            expectedBr[0][1, 5] = +1;
            expectedBr[0][2, 6] = +1;
            expectedBr[0][3, 7] = +1;

            expectedBr[1]        = Matrix.CreateZero(8, 12);
            expectedBr[1][0, 4]  = -1;
            expectedBr[1][1, 5]  = -1;
            expectedBr[1][4, 10] = +1;
            expectedBr[1][5, 11] = +1;

            expectedBr[2]       = Matrix.CreateZero(8, 8);
            expectedBr[2][2, 0] = -1;
            expectedBr[2][3, 1] = -1;
            expectedBr[2][6, 4] = +1;
            expectedBr[2][7, 5] = +1;

            expectedBr[3]       = Matrix.CreateZero(8, 12);
            expectedBr[3][4, 0] = -1;
            expectedBr[3][5, 1] = -1;
            expectedBr[3][6, 2] = -1;
            expectedBr[3][7, 3] = -1;

            // Create model
            Model model = CreateModel();
            Dictionary <int, HashSet <INode> > cornerNodes = DefineCornerNodes(model);

            model.ConnectDataStructures();

            // Order free dofs.
            var dofOrderer = new DofOrderer(new NodeMajorDofOrderingStrategy(), new NullReordering());
            IGlobalFreeDofOrdering globalOrdering = dofOrderer.OrderFreeDofs(model);

            model.GlobalDofOrdering = globalOrdering;
            foreach (ISubdomain subdomain in model.Subdomains)
            {
                subdomain.FreeDofOrdering = globalOrdering.SubdomainDofOrderings[subdomain];
            }

            // Separate dofs
            var dofSeparator = new FetiDPDofSeparator();

            dofSeparator.DefineGlobalBoundaryDofs(model, cornerNodes);
            foreach (ISubdomain subdomain in model.Subdomains)
            {
                int s = subdomain.ID;
                IEnumerable <INode> remainderNodes = subdomain.Nodes.Except(cornerNodes[s]);
                dofSeparator.SeparateCornerRemainderDofs(subdomain, cornerNodes[s], remainderNodes);
                dofSeparator.SeparateBoundaryInternalDofs(subdomain, remainderNodes);
            }

            // Enumerate lagranges
            var crosspointStrategy = new FullyRedundantConstraints();
            var lagrangeEnumerator = new FetiDPLagrangeMultipliersEnumerator(crosspointStrategy, dofSeparator);

            lagrangeEnumerator.DefineBooleanMatrices(model);

            // Check
            double tolerance = 1E-13;

            Assert.Equal(expectedNumLagrangeMultipliers, lagrangeEnumerator.NumLagrangeMultipliers);
            for (int id = 0; id < 4; ++id)
            {
                Matrix Br = lagrangeEnumerator.BooleanMatrices[id].CopyToFullMatrix(false);
                Assert.True(expectedBr[id].Equals(Br, tolerance));
            }
        }
Beispiel #13
0
        public static void TestDofSeparation()
        {
            //TODO: These should be available from properties
            int[][] cornerDofsExpected            = new int[4][];
            int[][] remainderDofsExpected         = new int[4][];
            int[][] boundaryRemainderDofsExpected = new int[4][];
            int[][] internalRemainderDofsExpected = new int[4][];

            // Subdomain 0
            cornerDofsExpected[0]            = new int[] { 2, 3, 10, 11 };
            remainderDofsExpected[0]         = new int[] { 0, 1, 4, 5, 6, 7, 8, 9 };
            boundaryRemainderDofsExpected[0] = new int[] { 4, 5, 6, 7 };
            internalRemainderDofsExpected[0] = new int[] { 0, 1, 2, 3 };

            // Subdomain 1
            cornerDofsExpected[1]            = new int[] { 0, 1, 12, 13, 16, 17 };
            remainderDofsExpected[1]         = new int[] { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15 };
            boundaryRemainderDofsExpected[1] = new int[] { 4, 5, 10, 11 };
            internalRemainderDofsExpected[1] = new int[] { 0, 1, 2, 3, 6, 7, 8, 9 };

            // Subdomain 2
            cornerDofsExpected[2]            = new int[] { 2, 3, 10, 11 };
            remainderDofsExpected[2]         = new int[] { 0, 1, 4, 5, 6, 7, 8, 9 };
            boundaryRemainderDofsExpected[2] = new int[] { 0, 1, 4, 5 };
            internalRemainderDofsExpected[2] = new int[] { 2, 3, 6, 7 };

            // Subdomain 3
            cornerDofsExpected[3]            = new int[] { 0, 1, 4, 5, 12, 13 };
            remainderDofsExpected[3]         = new int[] { 2, 3, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17 };
            boundaryRemainderDofsExpected[3] = new int[] { 0, 1, 2, 3 };
            internalRemainderDofsExpected[3] = new int[] { 4, 5, 6, 7, 8, 9, 10, 11 };

            // Create model
            Model model = CreateModel();
            Dictionary <int, HashSet <INode> > cornerNodes = DefineCornerNodes(model);

            model.ConnectDataStructures();

            // Order free dofs.
            var dofOrderer = new DofOrderer(new NodeMajorDofOrderingStrategy(), new NullReordering());
            IGlobalFreeDofOrdering globalOrdering = dofOrderer.OrderFreeDofs(model);

            model.GlobalDofOrdering = globalOrdering;
            foreach (ISubdomain subdomain in model.Subdomains)
            {
                subdomain.FreeDofOrdering = globalOrdering.SubdomainDofOrderings[subdomain];
            }

            // Separate dofs
            var dofSeparator = new FetiDPDofSeparator();

            foreach (ISubdomain subdomain in model.Subdomains)
            {
                int s = subdomain.ID;
                IEnumerable <INode> remainderNodes = subdomain.Nodes.Except(cornerNodes[s]);
                dofSeparator.SeparateCornerRemainderDofs(subdomain, cornerNodes[s], remainderNodes);
                dofSeparator.SeparateBoundaryInternalDofs(subdomain, remainderNodes);
            }

            // Check
            for (int s = 0; s < 4; ++s)
            {
                Utilities.CheckEqual(cornerDofsExpected[s], dofSeparator.CornerDofIndices[s]);
                Utilities.CheckEqual(remainderDofsExpected[s], dofSeparator.RemainderDofIndices[s]);
                Utilities.CheckEqual(boundaryRemainderDofsExpected[s], dofSeparator.BoundaryDofIndices[s]);
                Utilities.CheckEqual(internalRemainderDofsExpected[s], dofSeparator.InternalDofIndices[s]);
            }
        }
Beispiel #14
0
        public static void TestUnsignedBooleanMatrices()
        {
            // Expected results
            int expectedNumCornerDofs = 8;
            var expectedLc            = new Dictionary <int, Matrix>();

            expectedLc[0]       = Matrix.CreateZero(4, 8);
            expectedLc[0][0, 0] = 1;
            expectedLc[0][1, 1] = 1;
            expectedLc[0][2, 2] = 1;
            expectedLc[0][3, 3] = 1;

            expectedLc[1]       = Matrix.CreateZero(6, 8);
            expectedLc[1][0, 0] = 1;
            expectedLc[1][1, 1] = 1;
            expectedLc[1][2, 2] = 1;
            expectedLc[1][3, 3] = 1;
            expectedLc[1][4, 4] = 1;
            expectedLc[1][5, 5] = 1;

            expectedLc[2]       = Matrix.CreateZero(4, 8);
            expectedLc[2][0, 2] = 1;
            expectedLc[2][1, 3] = 1;
            expectedLc[2][2, 6] = 1;
            expectedLc[2][3, 7] = 1;

            expectedLc[3]       = Matrix.CreateZero(6, 8);
            expectedLc[3][0, 2] = 1;
            expectedLc[3][1, 3] = 1;
            expectedLc[3][2, 4] = 1;
            expectedLc[3][3, 5] = 1;
            expectedLc[3][4, 6] = 1;
            expectedLc[3][5, 7] = 1;

            // Create model
            Model model = CreateModel();
            Dictionary <int, HashSet <INode> > cornerNodes = DefineCornerNodes(model);

            model.ConnectDataStructures();

            // Order free dofs.
            var dofOrderer = new DofOrderer(new NodeMajorDofOrderingStrategy(), new NullReordering());
            IGlobalFreeDofOrdering globalOrdering = dofOrderer.OrderFreeDofs(model);

            model.GlobalDofOrdering = globalOrdering;
            foreach (ISubdomain subdomain in model.Subdomains)
            {
                subdomain.FreeDofOrdering = globalOrdering.SubdomainDofOrderings[subdomain];
            }

            // Separate dofs
            var dofSeparator = new FetiDPDofSeparator();

            dofSeparator.DefineGlobalCornerDofs(model, cornerNodes);
            foreach (ISubdomain subdomain in model.Subdomains)
            {
                int s = subdomain.ID;
                IEnumerable <INode> remainderAndConstrainedNodes = subdomain.Nodes.Where(node => !cornerNodes[s].Contains(node));
                dofSeparator.SeparateCornerRemainderDofs(subdomain, cornerNodes[s], remainderAndConstrainedNodes);
                dofSeparator.SeparateBoundaryInternalDofs(subdomain, remainderAndConstrainedNodes);
            }
            dofSeparator.CalcCornerMappingMatrices(model, cornerNodes);

            // Check
            double tolerance = 1E-13;

            Assert.Equal(expectedNumCornerDofs, dofSeparator.NumGlobalCornerDofs);
            for (int id = 0; id < 4; ++id)
            {
                UnsignedBooleanMatrix Lc = dofSeparator.CornerBooleanMatrices[id];
                Assert.True(expectedLc[id].Equals(Lc, tolerance));
            }
        }