コード例 #1
0
        /// <summary>
        /// If a fixed enrichment area is applied, all nodes inside a circle around the tip are enriched with tip
        /// functions. They can still be enriched with Heaviside functions, if they do not belong to the tip
        /// element(s).
        /// </summary>
        /// <param name="tipNodes"></param>
        /// <param name="tipElement"></param>
        private void ApplyFixedEnrichmentArea(CartesianPoint crackTip, XContinuumElement2D tipElement,
                                              HashSet <XNode> tipNodes, IEnrichmentItem2D tipEnrichments)
        {
            if (enrichmentRadiusOverElementSize > 0)
            {
                var    outline        = ConvexPolygon2D.CreateUnsafe(tipElement.Nodes);
                double elementArea    = outline.ComputeArea();
                double radius         = enrichmentRadiusOverElementSize * Math.Sqrt(elementArea);
                var    enrichmentArea = new Circle2D(crackTip, radius);

                foreach (var element in Mesh.FindElementsInsideCircle(enrichmentArea, tipElement))
                {
                    bool completelyInside = true;
                    foreach (var node in element.Nodes)
                    {
                        CirclePointPosition position = enrichmentArea.FindRelativePositionOfPoint(node);
                        if ((position == CirclePointPosition.Inside) || (position == CirclePointPosition.On))
                        {
                            tipNodes.Add(node);
                        }
                        else
                        {
                            completelyInside = false;
                        }
                    }

                    if (completelyInside)
                    {
                        element.EnrichmentItems.Add(tipEnrichments);
                    }
                }
            }
        }
コード例 #2
0
        private IReadOnlyDictionary <XContinuumElement2D, double[]> FindJintegralElementsAndNodalWeights(
            CartesianPoint crackTip, TipCoordinateSystem tipSystem, IReadOnlyList <XContinuumElement2D> tipElements)
        {
            Circle2D outerContour =
                new Circle2D(crackTip, ComputeRadiusOfJintegralOuterContour(tipSystem, tipElements));
            IReadOnlyList <XContinuumElement2D> intersectedElements =
                mesh.FindElementsIntersectedByCircle(outerContour, tipElements[0]);

            var elementsAndWeights = new Dictionary <XContinuumElement2D, double[]>();

            foreach (var element in intersectedElements)
            {
                // The relative position of the circle and the nodes was already calculated when checking the
                // circle-element intersection, but that method should be decoupled from assigning the nodal
                // weights, even at the cost of some duplicate operations. What could be done more efficiently is
                // caching the nodes and weights already processed by previous elements, but even then the cost of
                // processing each node will be increased by the lookup.
                double[] nodalWeights = new double[element.Nodes.Count];
                for (int nodeIdx = 0; nodeIdx < element.Nodes.Count; ++nodeIdx)
                {
                    CirclePointPosition pos = outerContour.FindRelativePositionOfPoint((CartesianPoint)element.Nodes[nodeIdx]);
                    if (pos == CirclePointPosition.Outside)
                    {
                        nodalWeights[nodeIdx] = 0.0;
                    }
                    else // Node lies inside or exactly on the circle
                    {
                        nodalWeights[nodeIdx] = 1.0;
                    }
                }
                elementsAndWeights.Add(element, nodalWeights);
            }
            return(elementsAndWeights);
        }
コード例 #3
0
        /// <summary>
        /// Shortcut method to avoid redundant checks
        /// </summary>
        /// <param name="circle"></param>
        /// <returns></returns>
        public bool IntersectsWithCircle(Circle2D circle)
        {
            int verticesOutsideCircle = 0;
            int verticesInsideCircle  = 0;

            foreach (CartesianPoint vertex in Vertices)
            {
                CirclePointPosition vertexPosition = circle.FindRelativePositionOfPoint(vertex);
                if (vertexPosition == CirclePointPosition.Outside)
                {
                    ++verticesOutsideCircle;
                }
                else if (vertexPosition == CirclePointPosition.Inside)
                {
                    ++verticesInsideCircle;
                }
            }
            int verticesOnCircle = Vertices.Count - verticesOutsideCircle - verticesInsideCircle;

            if (verticesOutsideCircle >= 1)
            {
                if ((verticesInsideCircle >= 1) || (verticesOnCircle >= 2))
                {
                    return(true);
                }
            }
            return(false);
        }
コード例 #4
0
        public IReadOnlyList <TNode> FindNodesInsideCircle(Circle2D circle,
                                                           bool findBoundaryNodes = true, TElement startingElement = null)
        {
            var selectedNodes = new List <TNode>();

            foreach (TNode node in Nodes) // O(nodesCount)
            {
                CirclePointPosition relativePosition = circle.FindRelativePositionOfPoint(new CartesianPoint(node.X, node.Y));
                if ((relativePosition == CirclePointPosition.Inside) ||
                    (findBoundaryNodes && (relativePosition == CirclePointPosition.On)))
                {
                    selectedNodes.Add(node);
                }
            }
            return(selectedNodes);
        }
コード例 #5
0
        public CirclePolygonPosition FindRelativePositionOfCircle(Circle2D circle)
        {
            int verticesOutsideCircle = 0;
            int verticesInsideCircle  = 0;

            foreach (CartesianPoint vertex in Vertices)
            {
                CirclePointPosition vertexPosition = circle.FindRelativePositionOfPoint(vertex);
                if (vertexPosition == CirclePointPosition.Outside)
                {
                    ++verticesOutsideCircle;
                }
                else if (vertexPosition == CirclePointPosition.Inside)
                {
                    ++verticesInsideCircle;
                }
            }
            int verticesOnCircle = Vertices.Count - verticesOutsideCircle - verticesInsideCircle;

            if (verticesOutsideCircle == Vertices.Count)
            {
                if (IsPointInsidePolygon(circle.Center))
                {
                    return(CirclePolygonPosition.CircleInsidePolygon);
                }
                else
                {
                    return(CirclePolygonPosition.Disjoint);
                }
            }
            else if (verticesOutsideCircle == 0)
            {
                return(CirclePolygonPosition.PolygonInsideCircle);
            }
            else if ((verticesOnCircle == 1) && (verticesInsideCircle == 0))
            {
                return(CirclePolygonPosition.Disjoint);
            }
            else
            {
                return(CirclePolygonPosition.Intersecting);
            }
        }
コード例 #6
0
        /// <summary>
        /// If a fixed enrichment area is applied, all nodes inside a circle around the tip are enriched with tip
        /// functions. They can still be enriched with Heaviside functions, if they do not belong to the tip
        /// element(s).
        /// </summary>
        /// <param name="tipElement"></param>
        private void ApplyFixedEnrichmentArea(XContinuumElement2D tipElement)
        {
            if (tipEnrichmentAreaRadius > 0)
            {
                var enrichmentArea = new Circle2D(crackTip, tipEnrichmentAreaRadius);
                foreach (var element in Mesh.FindElementsInsideCircle(enrichmentArea, tipElement))
                {
                    bool completelyInside = true;
                    foreach (var node in element.Nodes)
                    {
                        CirclePointPosition position = enrichmentArea.FindRelativePositionOfPoint(node);
                        if ((position == CirclePointPosition.Inside) || (position == CirclePointPosition.On))
                        {
                            crackTipNodesNew.Add(node);
                        }
                        else
                        {
                            completelyInside = false;
                        }
                    }

                    //TODO: I tried an alternative approach, ie elements access their enrichments from their nodes.
                    //      My original thought that this approach (storing enrichments in elements, unless they are standard /
                    //      blending) wouldn't work for blending elements, was incorrect, as elements with 0 enrichments
                    //      were then examined and separated into standard / blending.
                    if (completelyInside)
                    {
                        element.EnrichmentItems.Add(CrackTipEnrichments);
                    }
                }

                #region alternatively

                /* // If there wasn't a need to enrich the elements, this is more performant
                 * foreach (var node in mesh.FindNodesInsideCircle(enrichmentArea, true, tipElement))
                 * {
                 *  tipNodes.Add(node); // Nodes of tip element(s) will not be included twice
                 * } */
                #endregion
            }
        }
コード例 #7
0
        /// <summary>
        /// If a fixed enrichment area is applied, all nodes inside a circle around the tip are enriched with tip
        /// functions. They can still be enriched with Heaviside functions, if they do not belong to the tip
        /// element(s).
        /// </summary>
        /// <param name="tipNodes"></param>
        /// <param name="tipElement"></param>
        private void ApplyFixedEnrichmentArea(HashSet <XNode> tipNodes, XContinuumElement2D tipElement)
        {
            if (tipEnrichmentAreaRadius > 0)
            {
                var enrichmentArea = new Circle2D(crackTip, tipEnrichmentAreaRadius);
                foreach (var element in Mesh.FindElementsInsideCircle(enrichmentArea, tipElement))
                {
                    bool completelyInside = true;
                    foreach (var node in element.Nodes)
                    {
                        CirclePointPosition position = enrichmentArea.FindRelativePositionOfPoint(node);
                        if ((position == CirclePointPosition.Inside) || (position == CirclePointPosition.On))
                        {
                            tipNodes.Add(node);
                        }
                        else
                        {
                            completelyInside = false;
                        }
                    }
                    if (completelyInside)
                    {
                        element.EnrichmentItems.Add(CrackTipEnrichments);
                    }
                }

                #region alternatively

                /* // If there wasn't a need to enrich the elements, this is more performant
                 * foreach (var node in mesh.FindNodesInsideCircle(enrichmentArea, true, tipElement))
                 * {
                 *  tipNodes.Add(node); // Nodes of tip element(s) will not be included twice
                 * } */
                #endregion
            }
        }