Beispiel #1
0
        public XCluster2D CreateSubdomains()
        {
            XCluster2D cluster = initialDecomposer.CreateSubdomains();

            initialDecomposer = null; // no longer needed and it might take up significant memory for large meshes.
            return(cluster);
        }
        /// <summary>
        /// Only standard free and standard constrained dofs.
        /// </summary>
        /// <param name="model"></param>
        /// <param name="cluster"></param>
        /// <returns></returns>
        public static XClusterDofOrderer CreateNodeMajor(Model2D_old model, XCluster2D cluster)
        {
            (int numConstrainedDofs, DofTable <StructuralDof> constrainedDofs) = OrderConstrainedDofs(model.Constraints);
            (int numStandardDofs, DofTable <StructuralDof> standardDofs)       = OrderStandardDofs(model);

            return(new XClusterDofOrderer(cluster, numConstrainedDofs, constrainedDofs, numStandardDofs, standardDofs));
        }
Beispiel #3
0
        private XSubdomain2D_old FindSubdomainWhereNodeEnrichmentIsNotSingular(XCluster2D cluster, XNode node,
                                                                               IEnrichmentItem2D enrichment)
        {
            foreach (XSubdomain2D_old subdomain in cluster.Subdomains)
            {
                if (subdomain.BoundaryNodes.Contains(node))
                {
                    bool isSingularityNode = subdomain.DofOrderer.SingularHeavisideEnrichments.TryGetValue(node,
                                                                                                           out HashSet <IEnrichmentItem2D> singularEnrichments);
                    if (!isSingularityNode)
                    {
                        return(subdomain);
                    }
                    else if (!singularEnrichments.Contains(enrichment))
                    {
                        return(subdomain);
                    }
                }
            }

            // This point should not be reached under normal circumstances
            if (SingularHeavisideEnrichments.ContainsKey(node))
            {
                throw new IncorrectDecompositionException(
                          $"Heaviside dofs of {node} are singular in all subdomains. Investigate further");
            }
            else
            {
                throw new ArgumentException(
                          $"In this subdomain, {node} is not a boundary node with singular Heaviside enrichment");
            }
        }
 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;
 }
        public XCluster2D CreateSubdomains()
        {
            XSubdomain2D_old[] subdomains = AssignNodesToSubdomains(nodes, regions);
            AddElementsToSubdomains(elements, subdomains);
            var cluster = new XCluster2D();

            cluster.AddSubdomains(subdomains);
            return(cluster);
        }
Beispiel #6
0
        public void UpdateSubdomains(XCluster2D cluster)
        {
            //TODO: this can be done without accessing the single crack. We just need to access the same tip element and nodes
            foreach (ISingleCrack singleCrack in crack.SingleCracks)
            {
                // Find the subdomain that contains the crack tip
                CartesianPoint      tip          = singleCrack.CrackTips[0];
                XContinuumElement2D tipElement   = singleCrack.CrackTipElements[tip][0]; // If there are more neighboring ones, we don't need them
                XSubdomain2D_old    tipSubdomain = cluster.FindSubdomainOfElement(tipElement);

                // Find all elements that have at least one tip enriched node
                //TODO: this can be merged with the next subtask
                var          tipEnrichedElements = new HashSet <XContinuumElement2D>();
                ISet <XNode> tipNodes            = singleCrack.CrackTipNodesNew[singleCrack.CrackTipEnrichments];
                foreach (XNode node in tipNodes)
                {
                    tipEnrichedElements.UnionWith(mesh.FindElementsWithNode(node));
                }

                // Find which of these elements must be removed and from which subdomains
                var removedElements = new Dictionary <XContinuumElement2D, XSubdomain2D_old>();
                foreach (var element in tipEnrichedElements)
                {
                    if (!tipSubdomain.Elements.Contains(element))
                    {
                        XSubdomain2D_old previousSubdomain = cluster.FindSubdomainOfElement(element);
                        removedElements.Add(element, previousSubdomain);
                    }
                }
                if (removedElements.Count == 0)
                {
                    continue;
                }

                // Find the old subdomains of the nodes of the elements to be removed, before moving the elements
                Dictionary <XNode, HashSet <XSubdomain2D_old> > oldNodeMembership = FindOldNodeMembership(cluster, removedElements);

                // Move these elements to the subdomain that contains the crack tip
                //var modifiedSubdomains = new HashSet<XSubdomain2D>();
                foreach (var elementSubdomainPair in removedElements)
                {
                    XContinuumElement2D element      = elementSubdomainPair.Key;
                    XSubdomain2D_old    oldSubdomain = elementSubdomainPair.Value;
                    oldSubdomain.Elements.Remove(element);
                    tipSubdomain.Elements.Add(element);
                    //modifiedSubdomains.Add(previousSubdomain);
                    //modifiedSubdomains.Add(tipSubdomain); //TODO: this only needs to be added once
                }

                // Move their nodes to their new subdomains, which also updates the boundaries.
                RemoveNodesFromSubdomains(oldNodeMembership);
                Dictionary <XNode, HashSet <XSubdomain2D_old> > newNodeMembership =
                    FindNewNodeMembership(cluster, oldNodeMembership.Keys);
                AddNodesToSubdomains(newNodeMembership);
            }
        }
Beispiel #7
0
        public XCluster2D CreateSubdomains()
        {
            HashSet <XNode>[] internalNodes, boundaryNodes;
            (internalNodes, boundaryNodes) = PartitionNodes();
            HashSet <XContinuumElement2D>[] subdomains = PartitionElements(internalNodes, boundaryNodes);
            (internalNodes, boundaryNodes) = RepartitionNodes(subdomains);

            var cluster = new XCluster2D();

            for (int i = 0; i < numRegions; ++i)
            {
                cluster.AddSubdomain(new XSubdomain2D_old(i, subdomains[i], internalNodes[i], boundaryNodes[i]));
            }
            return(cluster);
        }
Beispiel #8
0
        /// <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));
        }
Beispiel #9
0
 public void UpdateSubdomains(XCluster2D cluster)
 {
     // Do nothing
 }
Beispiel #10
0
        private Dictionary <XNode, HashSet <XSubdomain2D_old> > FindNewNodeMembership(XCluster2D cluster, IEnumerable <XNode> nodes)
        {
            var nodeMembership    = new Dictionary <XNode, HashSet <XSubdomain2D_old> >();
            var elementMembership = new Dictionary <XContinuumElement2D, XSubdomain2D_old>(); // cache each element for all its nodes

            foreach (var node in nodes)
            {
                var nodeSubdomains = new HashSet <XSubdomain2D_old>();
                foreach (var element in mesh.FindElementsWithNode(node))
                {
                    // Find the subdomain of this element efficiently
                    bool isProccessed = elementMembership.TryGetValue(element, out XSubdomain2D_old subdomain);
                    if (!isProccessed)
                    {
                        subdomain = cluster.FindSubdomainOfElement(element);
                        elementMembership.Add(element, subdomain);
                    }
                    nodeSubdomains.Add(subdomain);
                }
                nodeMembership.Add(node, nodeSubdomains);
            }
            return(nodeMembership);
        }
Beispiel #11
0
        //TODO: perhaps the node membership should be stored in Cluster for all nodes of the model and updated whenever sth changes
        private Dictionary <XNode, HashSet <XSubdomain2D_old> > FindOldNodeMembership(XCluster2D cluster,
                                                                                      Dictionary <XContinuumElement2D, XSubdomain2D_old> removedElements)
        {
            var nodeMembership = new Dictionary <XNode, HashSet <XSubdomain2D_old> >();

            foreach (var elementSubdomainPair in removedElements)
            {
                foreach (var node in elementSubdomainPair.Key.Nodes)
                {
                    if (nodeMembership.ContainsKey(node))
                    {
                        continue;                                   // Avoid nodes that were processed in previous elements
                    }
                    var nodeSubdomains = new HashSet <XSubdomain2D_old>();
                    foreach (var nodeElement in mesh.FindElementsWithNode(node))
                    {
                        // Find the subdomain of this element efficiently
                        //TODO: cache the searched elements for other nodes
                        bool isRemoved = removedElements.TryGetValue(nodeElement, out XSubdomain2D_old previousSubdomain);
                        if (isRemoved)
                        {
                            nodeSubdomains.Add(previousSubdomain);
                        }
                        else
                        {
                            nodeSubdomains.Add(cluster.FindSubdomainOfElement(nodeElement));
                        }
                    }
                    nodeMembership.Add(node, nodeSubdomains);
                }
            }
            return(nodeMembership);
        }