コード例 #1
0
 public IntegrationWithSubtriangles(TriangleQuadratureSymmetricGaussian triangleIntegrationRule, ISingleCrack crack,
                                    ITriangulator2D <NaturalPoint> triangulator, double triangleOverElementArea = double.PositiveInfinity)
 {
     this.triangleIntegrationRule = triangleIntegrationRule;
     this.crack                   = crack;
     this.triangulator            = triangulator;
     this.triangleOverElementArea = triangleOverElementArea;
 }
コード例 #2
0
 public CrackBodyEnrichment2D(ISingleCrack crackDescription, IHeavisideFunction2D enrichmentFunction)
 {
     this.crackDescription   = crackDescription;
     this.enrichmentFunction = enrichmentFunction;
     this.Dofs = new EnrichedDof[] {
         new EnrichedDof(enrichmentFunction, StructuralDof.TranslationX),
         new EnrichedDof(enrichmentFunction, StructuralDof.TranslationY)
     };
 }
コード例 #3
0
 public CrackTipEnrichments2D(ISingleCrack crackDescription, CrackTipPosition tipPosition) :
     this(crackDescription, tipPosition, new ITipFunction[]
 {
     new IsotropicBrittleTipFunctions2D.Func1(),
     new IsotropicBrittleTipFunctions2D.Func2(),
     new IsotropicBrittleTipFunctions2D.Func3(),
     new IsotropicBrittleTipFunctions2D.Func4()
 })
 {
 }
コード例 #4
0
        /// <summary>
        /// Given a set of Heaviside enriched nodes, find which of them must not be enriched, in order to avoid the global
        /// stiffness matrix being singular.
        /// </summary>
        /// <param name="mesh"></param>
        /// <param name="heavisideNodes">They will not be altered.</param>
        /// <returns></returns>
        public ISet <XNode> FindHeavisideNodesToRemove(ISingleCrack crack, IReadOnlyList <XNode> heavisideNodes,
                                                       IReadOnlyList <ISet <XContinuumElement2D> > nodalSupports)
        {
            var processedElements = new Dictionary <XContinuumElement2D, Tuple <double, double> >();
            var nodesToRemove     = new HashSet <XNode>();

            for (int i = 0; i < heavisideNodes.Count; ++i)
            {
                XNode  node             = heavisideNodes[i];
                double nodePositiveArea = 0.0;
                double nodeNegativeArea = 0.0;

                foreach (var element in nodalSupports[i])
                {
                    bool alreadyProcessed = processedElements.TryGetValue(element, out Tuple <double, double> elementPosNegAreas);
                    if (!alreadyProcessed)
                    {
                        (double elementPosArea, double elementNegArea) = FindSignedAreasOfElement(crack, element);
                        elementPosNegAreas         = new Tuple <double, double>(elementPosArea, elementNegArea);
                        processedElements[element] = elementPosNegAreas;
                    }
                    nodePositiveArea += elementPosNegAreas.Item1;
                    nodeNegativeArea += elementPosNegAreas.Item2;
                }

                if (crack.SignedDistanceOf(node) >= 0.0)
                {
                    double negativeAreaRatio = nodeNegativeArea / (nodePositiveArea + nodeNegativeArea);
                    if (negativeAreaRatio < relativeAreaTolerance)
                    {
                        nodesToRemove.Add(node);
                    }
                }
                else
                {
                    double positiveAreaRatio = nodePositiveArea / (nodePositiveArea + nodeNegativeArea);
                    if (positiveAreaRatio < relativeAreaTolerance)
                    {
                        nodesToRemove.Add(node);
                    }
                }
            }

            return(nodesToRemove);
        }
コード例 #5
0
 public CrackTipEnrichments2D(ISingleCrack crackDescription, CrackTipPosition tipPosition,
                              IReadOnlyList <ITipFunction> enrichmentFunctions)
 {
     this.crackDescription    = crackDescription;
     this.tipPosition         = tipPosition;
     this.enrichmentFunctions = enrichmentFunctions;
     this.Dofs = new EnrichedDof[]
     {
         new EnrichedDof(enrichmentFunctions[0], StructuralDof.TranslationX),
         new EnrichedDof(enrichmentFunctions[0], StructuralDof.TranslationY),
         new EnrichedDof(enrichmentFunctions[1], StructuralDof.TranslationX),
         new EnrichedDof(enrichmentFunctions[1], StructuralDof.TranslationY),
         new EnrichedDof(enrichmentFunctions[2], StructuralDof.TranslationX),
         new EnrichedDof(enrichmentFunctions[2], StructuralDof.TranslationY),
         new EnrichedDof(enrichmentFunctions[3], StructuralDof.TranslationX),
         new EnrichedDof(enrichmentFunctions[3], StructuralDof.TranslationY),
     };
 }
コード例 #6
0
        /// <summary>
        /// Given a set of Heaviside enriched nodes, find which of them must not be enriched, in order to avoid the global
        /// stiffness matrix being singular.
        /// </summary>
        /// <param name="mesh"></param>
        /// <param name="heavisideNodes">They will not be altered.</param>
        /// <returns></returns>
        public ISet <XNode> FindHeavisideNodesToRemove(ISingleCrack crack, IMesh2D <XNode, XContinuumElement2D> mesh,
                                                       ISet <XNode> heavisideNodes)
        {
            var processedElements = new Dictionary <XContinuumElement2D, Tuple <double, double> >();
            var nodesToRemove     = new HashSet <XNode>();

            foreach (var node in heavisideNodes)
            {
                double nodePositiveArea = 0.0;
                double nodeNegativeArea = 0.0;

                foreach (var element in mesh.FindElementsWithNode(node))
                {
                    bool alreadyProcessed = processedElements.TryGetValue(element, out Tuple <double, double> elementPosNegAreas);
                    if (!alreadyProcessed)
                    {
                        (double elementPosArea, double elementNegArea) = FindSignedAreasOfElement(crack, element);
                        elementPosNegAreas         = new Tuple <double, double>(elementPosArea, elementNegArea);
                        processedElements[element] = elementPosNegAreas;
                    }
                    nodePositiveArea += elementPosNegAreas.Item1;
                    nodeNegativeArea += elementPosNegAreas.Item2;
                }

                if (crack.SignedDistanceOf(node) >= 0.0)
                {
                    double negativeAreaRatio = nodeNegativeArea / (nodePositiveArea + nodeNegativeArea);
                    if (negativeAreaRatio < relativeAreaTolerance)
                    {
                        nodesToRemove.Add(node);
                    }
                }
                else
                {
                    double positiveAreaRatio = nodePositiveArea / (nodePositiveArea + nodeNegativeArea);
                    if (positiveAreaRatio < relativeAreaTolerance)
                    {
                        nodesToRemove.Add(node);
                    }
                }
            }

            return(nodesToRemove);
        }
コード例 #7
0
 public CrackBodyEnrichment2D(ISingleCrack crackDescription) : this(crackDescription, new SignFunction2D())
 {
 }
コード例 #8
0
        private bool MustBeTriangulated(XContinuumElement2D element, out ISingleCrack intersectingCrack)
        {
            bool isTipEnrichedOrBlending = false;


            var enrichments = new HashSet <IEnrichmentItem2D>();

            foreach (XNode node in element.Nodes)
            {
                foreach (IEnrichmentItem2D enrichment in node.EnrichmentItems.Keys)
                {
                    enrichments.Add(enrichment);
                    if (enrichment is CrackTipEnrichments2D)
                    {
                        isTipEnrichedOrBlending = true;
                    }
                }
            }

            if (enrichments.Count == 0)
            {
                intersectingCrack = null;
                return(false);
            }

            var singleCracks = new List <ISingleCrack>();

            foreach (ISingleCrack crack in crackGeometry.SingleCracks)
            {
                if (enrichments.Contains(crack.CrackBodyEnrichment) || enrichments.Contains(crack.CrackTipEnrichments))
                {
                    singleCracks.Add(crack);
                }
            }

            if (singleCracks.Count == 1)
            {
                if (isTipEnrichedOrBlending)
                {
                    intersectingCrack = singleCracks[0];
                    return(true);
                }
                else
                {
                    int positiveNodes = 0;
                    int negativeNodes = 0;
                    foreach (XNode node in element.Nodes)
                    {
                        if (singleCracks[0].SignedDistanceOf(node) > 0.0)
                        {
                            ++positiveNodes;
                        }
                        else if (singleCracks[0].SignedDistanceOf(node) < 0.0)
                        {
                            ++negativeNodes;
                        }
                        else
                        {
                            ++positiveNodes;
                            ++negativeNodes;
                        }
                    }

                    if ((positiveNodes > 0) && (negativeNodes > 0))
                    {
                        intersectingCrack = singleCracks[0];
                        return(true);
                    }
                    else
                    {
                        intersectingCrack = null;;
                        return(false);
                    }
                }
            }
            else
            {
                throw new Exception($"This element must be intersected by exactly 1 crack, but {singleCracks.Count} were found");
            }
        }
コード例 #9
0
        // TODO: I should really cache these somehow, so that they can be accessible from the crack object. They are used at various points.
        private (double positiveArea, double negativeArea) FindSignedAreasOfElement(ISingleCrack crack,
                                                                                    XContinuumElement2D element)
        {
            SortedSet <CartesianPoint> triangleVertices            = crack.FindTriangleVertices(element);
            IReadOnlyList <Triangle2D <CartesianPoint> > triangles = triangulator.CreateMesh(triangleVertices);

            double positiveArea = 0.0;
            double negativeArea = 0.0;

            foreach (var triangle in triangles)
            {
                CartesianPoint v0   = triangle.Vertices[0];
                CartesianPoint v1   = triangle.Vertices[1];
                CartesianPoint v2   = triangle.Vertices[2];
                double         area = 0.5 * Math.Abs(v0.X * (v1.Y - v2.Y) + v1.X * (v2.Y - v0.Y) + v2.X * (v0.Y - v1.Y));

                // The sign of the area can be derived from any node with body level set != 0
                int sign = 0;
                foreach (var vertex in triangle.Vertices)
                {
                    XNode vertexAsNode = null;
                    foreach (var node in element.Nodes) // TODO: find a faster way to do this
                    {
                        if ((vertex.X == node.X) && (vertex.Y == node.Y))
                        {
                            vertexAsNode = node;
                            break;
                        }
                    }
                    if (vertexAsNode != null)
                    {
                        double distance = crack.SignedDistanceOf(vertexAsNode);
                        if (Math.Abs(distance) <= zeroDistanceTolerance)
                        {
                            sign = 0;
                        }
                        else
                        {
                            sign = Math.Sign(distance);
                        }
                        if (sign != 0)
                        {
                            break;
                        }
                    }
                }

                // If no node with non-zero body level set is found, then find the body level set of its centroid
                if (sign == 0)
                {
                    // Report this instance in DEBUG messages. It should not happen with linear level sets and only 1 crack.
                    //if (reports)
                    //{
                    //    Console.WriteLine("--- DEBUG: Triangulation resulted in a triangle where no vertex is an element node. ---");
                    //}


                    var          centroid        = new CartesianPoint((v0.X + v1.X + v2.X) / 3.0, (v0.Y + v1.Y + v2.Y) / 3.0);
                    NaturalPoint centroidNatural = element.Interpolation.
                                                   CreateInverseMappingFor(element.Nodes).TransformPointCartesianToNatural(centroid);
                    EvalInterpolation2D centroidInterpolation =
                        element.Interpolation.EvaluateAllAt(element.Nodes, centroidNatural);
                    sign = Math.Sign(crack.SignedDistanceOf(centroidNatural, element, centroidInterpolation));
                }

                if (sign > 0)
                {
                    positiveArea += area;
                }
                else if (sign < 0)
                {
                    negativeArea += area;
                }
                else
                {
                    throw new Exception(
                              "Even after finding the signed distance of its centroid, the sign of the area is unidentified");
                }
            }

            return(positiveArea, negativeArea);
        }
コード例 #10
0
 public ISet <XNode> FindHeavisideNodesToRemove(ISingleCrack crack, IReadOnlyList <XNode> heavisideNodes, IReadOnlyList <ISet <XContinuumElement2D> > nodalSupports)
 {
     throw new NotImplementedException();
 }