OrderUnconstrainedDofs(Model2D_old model) { ITable <XNode, StructuralDof, double> constraints = model.Constraints; var standardDofs = new DofTable <StructuralDof>(); var enrichedDofs = new DofTable <EnrichedDof>(); int dofCounter = 0; foreach (XNode node in model.Nodes) { // Standard free dofs. No rotational dofs. They can be X or Y. One or both of them may be constrained. if (!constraints.Contains(node, StructuralDof.TranslationX)) { standardDofs[node, StructuralDof.TranslationX] = dofCounter++; } if (!constraints.Contains(node, StructuralDof.TranslationY)) { standardDofs[node, StructuralDof.TranslationY] = dofCounter++; } // Enriched dofs. No rotational dofs. They cannot be constrained. foreach (IEnrichmentItem2D enrichment in node.EnrichmentItems.Keys) { foreach (EnrichedDof dofType in enrichment.Dofs) { enrichedDofs[node, dofType] = dofCounter++; } } } return(standardDofs, enrichedDofs); //TODO: Also return each table's count, by keeping separate counters. This avoids the O(numRows) Table.Count() }
private XClusterDofOrderer(XCluster2D cluster, int numConstrainedDofs, DofTable <StructuralDof> constrainedDofs, int numStandardDofs, DofTable <StructuralDof> standardDofs) { this.cluster = cluster; this.NumConstrainedDofs = numConstrainedDofs; this.constrainedDofs = constrainedDofs; this.NumStandardDofs = numStandardDofs; this.standardDofs = standardDofs; }
private XSubdomainDofOrderer(int numEnrichedDofs, DofTable <EnrichedDof> subdomainEnrichedDofs, Dictionary <XNode, HashSet <IEnrichmentItem2D> > singularHeavisideEnrichments, Dictionary <XNode, ISet <EnrichedDof> > boundaryDofs) { this.NumEnrichedDofs = numEnrichedDofs; this.subdomainEnrichedDofs = subdomainEnrichedDofs; this.SingularHeavisideEnrichments = singularHeavisideEnrichments; this.BoundaryDofs = boundaryDofs; }
protected DofOrdererBase(int constrainedDofsCount, DofTable <StructuralDof> constrainedDofs, int enrichedDofsCount, DofTable <EnrichedDof> enrichedDofs, int standardDofsCount, DofTable <StructuralDof> standardDofs) { this.NumConstrainedDofs = constrainedDofsCount; this.constrainedDofs = constrainedDofs; this.NumEnrichedDofs = enrichedDofsCount; this.enrichedDofs = enrichedDofs; this.NumStandardDofs = standardDofsCount; this.standardDofs = standardDofs; }
private static (int numConstrainedDofs, DofTable <StructuralDof> constrainedDofs) OrderConstrainedDofs( ITable <XNode, StructuralDof, double> constraints) { var constrainedDofs = new DofTable <StructuralDof>(); int counter = 0; foreach ((XNode node, StructuralDof dofType, double displacement) in constraints) { constrainedDofs[node, dofType] = counter++; } return(counter, constrainedDofs); }
/// <summary> /// </summary> /// <param name="element"></param> /// <param name="globalFreeVector">Both the free standard and enriched dofs.</param> /// <returns></returns> public Vector ExtractEnrichedDisplacementsOfElementFromGlobal(XContinuumElement2D element, Vector globalFreeVector) { DofTable <EnrichedDof> elementDofs = element.GetEnrichedDofs(); double[] elementVector = new double[elementDofs.EntryCount]; foreach ((XNode node, EnrichedDof dofType, int dofIdx) in elementDofs) { int globalEnrichedDof = enrichedDofs[node, dofType]; elementVector[dofIdx] = globalFreeVector[globalEnrichedDof]; } return(Vector.CreateFromArray(elementVector)); }
public static XSubdomainDofOrderer CreateNodeMajor(ICrackDescription crack, XSubdomain2D_old subdomain) //TODO: also add AMD reordering { // Handle nodes with singular Heaviside enrichment Dictionary <XNode, HashSet <IEnrichmentItem2D> > singularityHeavisideEnrichments = FindBoundaryNodesWithSingularHeaviside(crack, subdomain); if (singularityHeavisideEnrichments.Count > 0) { Console.Write($"WARNING: Subdomain {subdomain.ID} has boundary nodes that are enriched with Heaviside,"); Console.Write(" but that would lead to singular matrices, since the nodal support in this subdomain only"); Console.Write(" contains Gauss points with the same sign. It would be better to use another domain"); Console.Write(" decomposition. The nodes in question are: "); foreach (var node in singularityHeavisideEnrichments.Keys) { Console.Write(node + " "); } Console.WriteLine(); } var subdomainEnrichedDofs = new DofTable <EnrichedDof>(); var boundaryDofs = new Dictionary <XNode, ISet <EnrichedDof> >(); int dofCounter = 0; foreach (XNode node in subdomain.AllNodes) { bool isboundaryNode = subdomain.BoundaryNodes.Contains(node); if (isboundaryNode && node.IsEnriched) { boundaryDofs.Add(node, new HashSet <EnrichedDof>()); } bool isSingularityNode = singularityHeavisideEnrichments.TryGetValue(node, out HashSet <IEnrichmentItem2D> singularEnrichments); foreach (IEnrichmentItem2D enrichment in node.EnrichmentItems.Keys) { if (isSingularityNode && singularEnrichments.Contains(enrichment)) { continue; } foreach (EnrichedDof dof in enrichment.Dofs) { if (isboundaryNode) { boundaryDofs[node].Add(dof); } subdomainEnrichedDofs[node, dof] = dofCounter; ++dofCounter; } } } return(new XSubdomainDofOrderer(dofCounter, subdomainEnrichedDofs, singularityHeavisideEnrichments, boundaryDofs)); }
private static (int numStandardDofs, DofTable <StructuralDof> standardDofs) OrderStandardDofs(Model2D_old model) { ITable <XNode, StructuralDof, double> constraints = model.Constraints; var standardDofs = new DofTable <StructuralDof>(); int counter = 0; foreach (var node in model.Nodes) { if (!constraints.Contains(node, StructuralDof.TranslationX)) { standardDofs[node, StructuralDof.TranslationX] = counter++; } if (!constraints.Contains(node, StructuralDof.TranslationY)) { standardDofs[node, StructuralDof.TranslationY] = counter++; } } return(counter, standardDofs); }
// Each artificial dof has index that is node major, then enrichment item major, then enrichment function major and finally axis minor private static (int enrichedDofsCount, DofTable <EnrichedDof> enrichedDofs) OrderEnrichedDofs( IEnumerable <XNode> nodes, int standardDofsCount) { var enrichedDofs = new DofTable <EnrichedDof>(); int dofCounter = standardDofsCount; // This if I put everything in the same matrix //int dofCounter = 0; // This if I use different matrices foreach (XNode node in nodes) { foreach (IEnrichmentItem2D enrichment in node.EnrichmentItems.Keys) { foreach (EnrichedDof dofType in enrichment.Dofs) // Are dofs determined by the element type (e.g. structural) as well? { enrichedDofs[node, dofType] = dofCounter++; } } } return(dofCounter - standardDofsCount, enrichedDofs); }
//Node major ordering private static (int standardDofsCount, DofTable <StructuralDof> standardDofs) OrderStandardDofs( IDictionary <XNode, HashSet <StructuralDof> > nodalDofTypes, ITable <XNode, StructuralDof, double> constraints) { var standardDofs = new DofTable <StructuralDof>(); int counter = 0; foreach (var pair in nodalDofTypes) { XNode node = pair.Key; foreach (StructuralDof dofType in pair.Value) { if (!constraints.Contains(node, dofType)) { standardDofs[node, dofType] = counter++; } } } return(counter, standardDofs); }
/// <summary> /// TODO: Modify this method to extract any kind of vector, not only displacement, which means different /// handling of constrained dofs, if constrained dofs are defined in the first place. /// </summary> /// <param name="element"></param> /// <param name="globalFreeVector"></param> /// <param name="globalConstrainedVector"></param> /// <returns></returns> public Vector ExtractDisplacementVectorOfElementFromGlobal(XContinuumElement2D element, Vector globalFreeVector, Vector globalConstrainedVector) { DofTable <StructuralDof> elementDofs = element.GetStandardDofs(); double[] elementVector = new double[elementDofs.EntryCount]; foreach ((XNode node, StructuralDof dofType, int dofIdx) in elementDofs) { bool isStandard = this.standardDofs.TryGetValue(node, dofType, out int globalStandardDof); if (isStandard) { elementVector[dofIdx] = globalFreeVector[globalStandardDof]; } else { int globalConstrainedDof = this.constrainedDofs[node, dofType]; elementVector[dofIdx] = globalConstrainedVector[globalConstrainedDof]; } } return(Vector.CreateFromArray(elementVector)); }
/// <summary> /// </summary> /// <param name="element"></param> /// <param name="globalFreeVector">Both the free standard and enriched dofs.</param> /// <returns></returns> public Vector ExtractEnrichedDisplacementsOfElementFromGlobal(XCluster2D cluster, XContinuumElement2D element, Vector globalFreeVector) { // While Heaviside dofs on boundary nodes that would cause singular stiffness matrices are generally avoided, // the returned vector of this method must include them. Since H(x)-H(xNode)=0, it wouldn't be wrong to exclude // them in theory. However it would cause indexing problems if they are missing, since other XFEM classes (such as // XContinuumElement) have no concept of a node being enriched only for some elements. DofTable <EnrichedDof> elementDofs = element.GetEnrichedDofs(); double[] elementVector = new double[elementDofs.EntryCount]; foreach (XNode node in element.Nodes) { bool isSingularityNode = SingularHeavisideEnrichments.TryGetValue(node, out HashSet <IEnrichmentItem2D> singularEnrichments); foreach (IEnrichmentItem2D enrichment in node.EnrichmentItems.Keys) { XSubdomainDofOrderer correctOrderer = this; if (isSingularityNode && singularEnrichments.Contains(enrichment)) { // Find global dof index from other subdomain, sine it is not stored here correctOrderer = FindSubdomainWhereNodeEnrichmentIsNotSingular(cluster, node, enrichment).DofOrderer; } foreach (var dofType in enrichment.Dofs) { int elementDofIdx = elementDofs[node, dofType]; int globalDofIdx = correctOrderer.FirstGlobalDofIndex + correctOrderer.subdomainEnrichedDofs[node, dofType]; elementVector[elementDofIdx] = globalFreeVector[globalDofIdx]; } } } //foreach (Tuple<XNode2D, EnrichedDof, int> entry in elementDofs) //{ // int globalEnrichedDof = globalEnrichedDofs[entry.Item1, entry.Item2]; // elementVector[entry.Item3] = globalFreeVector[globalEnrichedDof]; //} return(Vector.CreateFromArray(elementVector)); }
/// <summary> /// Index i = element local dof. Dictionary[i] = global dof. /// </summary> /// <param name="element"></param> /// <returns></returns> public void MatchElementToGlobalStandardDofsOf(XContinuumElement2D element, out IReadOnlyDictionary <int, int> elementToGlobalStandardDofs, out IReadOnlyDictionary <int, int> elementToGlobalConstrainedDofs) { DofTable <StructuralDof> elementDofs = element.GetStandardDofs(); var globalStandardDofs = new Dictionary <int, int>(); var globalConstrainedDofs = new Dictionary <int, int>(); foreach ((XNode node, StructuralDof dofType, int dofIdx) in elementDofs) { bool isStandard = this.standardDofs.TryGetValue(node, dofType, out int standardGlobalDof); if (isStandard) { globalStandardDofs[dofIdx] = standardGlobalDof; } else { globalConstrainedDofs[dofIdx] = this.constrainedDofs[node, dofType]; } } elementToGlobalStandardDofs = globalStandardDofs; elementToGlobalConstrainedDofs = globalConstrainedDofs; }
private SeparateDofOrderer(int constrainedDofsCount, DofTable <StructuralDof> constrainedDofs, int enrichedDofsCount, DofTable <EnrichedDof> enrichedDofs, int standardDofsCount, DofTable <StructuralDof> standardDofs) : base(constrainedDofsCount, constrainedDofs, enrichedDofsCount, enrichedDofs, standardDofsCount, standardDofs) { }