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); }
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(); }
public void ReorderRemainderDofs(FetiDPDofSeparator dofSeparator, ISubdomain subdomain) { // Do nothing, since the sparsity pattern is irrelevant for dense matrices. }
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)); } }
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]); } }
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)); } }