Exemple #1
0
        public void UpdateGeometry(double localGrowthAngleStart, double growthLengthStart,
                                   double localGrowthAngleEnd, double growthLengthEnd)
        {
            // End tip
            double globalAngleEnd = MathUtilities.WrapAngle(localGrowthAngleEnd + endTipSystem.RotationAngle);
            double dxEnd          = growthLengthEnd * Math.Cos(globalAngleEnd);
            double dyEnd          = growthLengthEnd * Math.Sin(globalAngleEnd);
            var    oldEndTip      = Vertices.Last.Value;;
            var    newEndTip      = new CartesianPoint(oldEndTip.X + dxEnd, oldEndTip.Y + dyEnd);

            Vertices.AddLast(newEndTip);
            Segments.AddLast(new DirectedSegment2D(oldEndTip, newEndTip));
            Angles.AddLast(localGrowthAngleEnd); // These are independent of the global coordinate system
            endTipSystem = new TipCoordinateSystem(newEndTip, globalAngleEnd);

            //StartTip
            double globalAngleStart = MathUtilities.WrapAngle(localGrowthAngleStart + startTipSystem.RotationAngle);
            double dxStart          = growthLengthStart * Math.Cos(globalAngleStart);
            double dyStart          = growthLengthStart * Math.Sin(globalAngleStart);
            var    oldStartTip      = Vertices.First.Value;
            var    newStartTip      = new CartesianPoint(oldStartTip.X + dxEnd, oldStartTip.Y + dyEnd);

            Vertices.AddFirst(newStartTip);
            Segments.AddFirst(new DirectedSegment2D(newStartTip, oldStartTip));
            Angles.AddFirst(-localGrowthAngleEnd); // From new to old start segment, use the opposite angle
            endTipSystem = new TipCoordinateSystem(newStartTip, globalAngleStart);
        }
Exemple #2
0
        public AuxiliaryStatesTensors ComputeTensorsAt(CartesianPoint globalIntegrationPoint,
                                                       TipCoordinateSystem tipCoordinateSystem)
        {
            // Common calculations
            PolarPoint2D polarCoordinates =
                tipCoordinateSystem.TransformPointGlobalCartesianToLocalPolar(globalIntegrationPoint);
            var commonValues = new CommonValues(polarCoordinates.R, polarCoordinates.Theta);

            // Displacement field derivatives
            Matrix2by2   displacementGradientMode1, displacementGradientMode2;
            TipJacobians polarJacobians = tipCoordinateSystem.CalculateJacobiansAt(polarCoordinates);

            ComputeDisplacementDerivatives(polarJacobians, commonValues,
                                           out displacementGradientMode1, out displacementGradientMode2);

            // Strains
            Tensor2D strainTensorMode1 = ComputeStrainTensor(displacementGradientMode1);
            Tensor2D strainTensorMode2 = ComputeStrainTensor(displacementGradientMode2);

            // Stresses
            Tensor2D stressTensorMode1, stressTensorMode2;

            ComputeStressTensors(commonValues, out stressTensorMode1, out stressTensorMode2);

            return(new AuxiliaryStatesTensors(displacementGradientMode1, displacementGradientMode2,
                                              strainTensorMode1, strainTensorMode2, stressTensorMode1, stressTensorMode2));
        }
        public void InitializeGeometry(CartesianPoint crackMouth, CartesianPoint crackTip)
        {
            this.crackMouth = crackMouth;
            crackPath.Add(crackMouth);
            var segment = new DirectedSegment2D(crackMouth, crackTip);

            double tangentX     = crackTip.X - crackMouth.X;
            double tangentY     = crackTip.Y - crackMouth.Y;
            double length       = Math.Sqrt(tangentX * tangentX + tangentY * tangentY);
            double tangentSlope = Math.Atan2(tangentY, tangentX);

            this.crackTip = crackTip;
            crackPath.Add(crackTip);
            tipSystem = new TipCoordinateSystem(crackTip, tangentSlope);
            CrackTipEnrichments.TipSystem = tipSystem;

            tangentX /= length;
            tangentY /= length;

            foreach (XNode node in Mesh.Nodes)
            {
                levelSetsBody[node] = segment.SignedDistanceOf(node);
                levelSetsTip[node]  = (node.X - crackTip.X) * tangentX + (node.Y - crackTip.Y) * tangentY;
            }

            if (LevelSetLogger != null)
            {
                LevelSetLogger.InitialLog();                         //TODO: handle this with a NullLogger.
            }
        }
        //TODO: This should work for any IOpenCurve2D. Same for all ICrackGeometryDescriptions.
        //TODO: The tangent stuff should be done by the initial curve.
        public void InitializeGeometry(PolyLine2D initialCrack)
        {
            foreach (var vertex in initialCrack.Vertices)
            {
                crackPath.Add(vertex);
            }

            crackMouth = initialCrack.Start;
            var lastSegment = initialCrack.Segments[initialCrack.Segments.Count - 1];

            double tangentX     = lastSegment.End.X - lastSegment.Start.X;
            double tangentY     = lastSegment.End.Y - lastSegment.Start.Y;
            double length       = Math.Sqrt(tangentX * tangentX + tangentY * tangentY);
            double tangentSlope = Math.Atan2(tangentY, tangentX);

            this.crackTip = initialCrack.End;
            tipSystem     = new TipCoordinateSystem(crackTip, tangentSlope);
            CrackTipEnrichments.TipSystem = tipSystem;

            tangentX /= length;
            tangentY /= length;

            foreach (XNode node in Mesh.Nodes)
            {
                levelSetsBody[node] = initialCrack.SignedDistanceOf(node);
                levelSetsTip[node]  = (node.X - crackTip.X) * tangentX + (node.Y - crackTip.Y) * tangentY;
            }

            if (LevelSetLogger != null)
            {
                LevelSetLogger.InitialLog();                         //TODO: handle this with a NullLogger.
            }
        }
Exemple #5
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);
        }
Exemple #6
0
        public void UpdateGeometry(double localGrowthAngle, double growthLength)
        {
            double globalGrowthAngle = MathUtilities.WrapAngle(localGrowthAngle + tipSystem.RotationAngle);
            double dx     = growthLength * Math.Cos(globalGrowthAngle);
            double dy     = growthLength * Math.Sin(globalGrowthAngle);
            double unitDx = dx / growthLength;
            double unitDy = dy / growthLength;

            var oldTip = crackTip;
            var newTip = new CartesianPoint(oldTip.X + dx, oldTip.Y + dy);

            crackTip  = newTip;
            tipSystem = new TipCoordinateSystem(newTip, globalGrowthAngle);

            var newSegment = new DirectedSegment2D(oldTip, newTip);

            foreach (XNode node in Mesh.Nodes)
            {
                // Rotate the ALL tip level sets towards the new tip and then advance them
                double rotatedTipLevelSet = (node.X - crackTip.X) * unitDx + (node.Y - crackTip.Y) * unitDy;
                levelSetsTip[node] = rotatedTipLevelSet - newSegment.Length;

                if (rotatedTipLevelSet > 0.0) // Only some body level sets are updated (See Stolarska 2001)
                {
                    levelSetsBody[node] = newSegment.SignedDistanceOf(node);
                }
            }
        }
Exemple #7
0
        public void InitializeGeometry(CartesianPoint startTip, CartesianPoint endTip)
        {
            double dx           = endTip.X - startTip.X;
            double dy           = endTip.Y - startTip.Y;
            double tangentSlope = Math.Atan2(dy, dx);

            endTipSystem   = new TipCoordinateSystem(endTip, tangentSlope);
            startTipSystem = new TipCoordinateSystem(startTip, tangentSlope + Math.PI);

            Vertices.AddLast(startTip);
            Vertices.AddLast(endTip);
            Segments.AddLast(new DirectedSegment2D(startTip, endTip));
        }
Exemple #8
0
        public void UpdateGeometry(double localGrowthAngle, double growthLength)
        {
            double globalGrowthAngle = MathUtilities.WrapAngle(localGrowthAngle + tipSystem.RotationAngle);
            double dx = growthLength * Math.Cos(globalGrowthAngle);
            double dy = growthLength * Math.Sin(globalGrowthAngle);

            var oldTip = Vertices[Vertices.Count - 1];
            var newTip = new CartesianPoint(oldTip.X + dx, oldTip.Y + dy);

            Vertices.Add(newTip);
            Segments.Add(new DirectedSegment2D(oldTip, newTip));
            Angles.Add(localGrowthAngle); // These are independent of the global coordinate system
            tipSystem = new TipCoordinateSystem(newTip, globalGrowthAngle);
            CrackTipEnrichments.TipSystem = tipSystem;
        }
Exemple #9
0
        public void InitializeGeometry(CartesianPoint crackMouth, CartesianPoint crackTip)
        {
            CrackMouth = crackMouth;

            double dx           = crackTip.X - crackMouth.X;
            double dy           = crackTip.Y - crackMouth.Y;
            double tangentSlope = Math.Atan2(dy, dx);

            tipSystem = new TipCoordinateSystem(crackTip, tangentSlope);
            CrackTipEnrichments.TipSystem = tipSystem;

            Vertices.Add(crackMouth);
            Vertices.Add(crackTip);
            Segments.Add(new DirectedSegment2D(crackMouth, crackTip));
        }
Exemple #10
0
        // TODO: This method should directly return the elements and take care of cases near the domain boundaries (see Ahmed)
        // TODO: The J-integral radius should not exceed the last crack segment's length
        public double ComputeRadiusOfJintegralOuterContour(TipCoordinateSystem tipSystem,
                                                           IReadOnlyList <XContinuumElement2D> tipElements)
        {
            double maxTipElementArea = -1.0;

            foreach (var element in tipElements)
            {
                var    outline     = ConvexPolygon2D.CreateUnsafe(element.Nodes.Select(node => (CartesianPoint)node).ToArray());
                double elementArea = outline.ComputeArea();
                if (elementArea > maxTipElementArea)
                {
                    maxTipElementArea = elementArea;
                }
            }
            return(magnificationOfJintegralRadius * Math.Sqrt(maxTipElementArea));
        }
        //TODO: make this private
        public void UpdateGeometry(double localGrowthAngle, double growthLength)
        {
            double globalGrowthAngle = MathUtilities.WrapAngle(localGrowthAngle + tipSystem.RotationAngle);
            double dx     = growthLength * Math.Cos(globalGrowthAngle);
            double dy     = growthLength * Math.Sin(globalGrowthAngle);
            var    oldTip = crackTip;
            var    newTip = new CartesianPoint(oldTip.X + dx, oldTip.Y + dy);

            crackTip = newTip;
            crackPath.Add(newTip);
            tipSystem = new TipCoordinateSystem(newTip, globalGrowthAngle);
            CrackTipEnrichments.TipSystem = tipSystem;

            //TODO: it is inconsistent that the modified body nodes are updated here, while the other in UpdateEnrichments();
            crackBodyNodesModified = levelSetUpdater.Update(oldTip, localGrowthAngle, growthLength, dx, dy, Mesh.Nodes,
                                                            crackBodyNodesAll, levelSetsBody, levelSetsTip);

            if (LevelSetLogger != null)
            {
                LevelSetLogger.Log();                         //TODO: handle this with a NullLogger.
            }
        }
Exemple #12
0
        public void InitializeGeometry(CartesianPoint crackMouth, CartesianPoint crackTip)
        {
            CrackMouth = crackMouth;
            var segment = new DirectedSegment2D(crackMouth, crackTip);

            double tangentX     = crackTip.X - crackMouth.X;
            double tangentY     = crackTip.Y - crackMouth.Y;
            double length       = Math.Sqrt(tangentX * tangentX + tangentY * tangentY);
            double tangentSlope = Math.Atan2(tangentY, tangentX);

            this.crackTip = crackTip;
            tipSystem     = new TipCoordinateSystem(crackTip, tangentSlope);

            tangentX /= length;
            tangentY /= length;

            foreach (XNode node in Mesh.Nodes)
            {
                levelSetsBody[node] = segment.SignedDistanceOf(node);
                levelSetsTip[node]  = (node.X - crackTip.X) * tangentX + (node.Y - crackTip.Y) * tangentY;
            }
        }
Exemple #13
0
        //public FixedPropagator CreateFromPath(IReadOnlyList<CartesianPoint> knownCrackPath, Propagator actualPropagator = null)
        //{
        //    int growthSteps = knownCrackPath.Count - 2; // The first 2 vertices are the initial crack.
        //    double[] angles = new double[growthSteps];
        //    double[] lengths = new double[growthSteps];
        //    for (int i = 0; i < growthSteps; ++i)
        //    {
        //        CartesianPoint previousTip = knownCrackPath[i];
        //        CartesianPoint currentTip = knownCrackPath[i+1];
        //        CartesianPoint nextTip = knownCrackPath[i+2];
        //        var oldSegment = new DirectedSegment2D(previousTip, currentTip);
        //        var newSegment = new DirectedSegment2D(currentTip, nextTip);
        //        lengths[i] = newSegment.Length;
        //        CartesianPoint local = oldSegment.TransformGlobalToLocalPoint(nextTip);
        //        angles[i] = Math.Atan2(local.Y, local.X);
        //    }
        //    return new FixedPropagator(angles, lengths, actualPropagator);
        //}


        public (double growthAngle, double growthLength) Propagate(Dictionary <int, Vector> totalFreeDisplacements,
                                                                   CartesianPoint crackTip, TipCoordinateSystem tipSystem, IReadOnlyList <XContinuumElement2D> tipElements)
        {
            if (iteration >= Logger.GrowthLengths.Count)
            {
                throw new IndexOutOfRangeException(
                          $"Only {Logger.GrowthLengths.Count} iterations have been recorder.");
            }
            double angle  = Logger.GrowthAngles[iteration];
            double length = Logger.GrowthLengths[iteration];

            if (checkPropagation)
            {
                actualPropagator.Propagate(totalFreeDisplacements, crackTip, tipSystem, tipElements);
                Console.Write($"Growth angle: expected = {angle}");
                Console.WriteLine($"   -   computed = {actualPropagator.Logger.GrowthAngles[iteration]}");
                Console.Write($"Growth length: expected = {length}");
                Console.WriteLine($"   -   computed = {actualPropagator.Logger.GrowthLengths[iteration]}");
            }

            ++iteration;
            return(angle, length);
        }
Exemple #14
0
        private (double sifMode1, double sifMode2) ComputeSIFS(Dictionary <int, Vector> totalFreeDisplacements,
                                                               CartesianPoint crackTip, TipCoordinateSystem tipSystem, IReadOnlyList <XContinuumElement2D> tipElements)
        {
            double interactionIntegralMode1 = 0.0, interactionIntegralMode2 = 0.0;
            IReadOnlyDictionary <XContinuumElement2D, double[]> elementWeights =
                FindJintegralElementsAndNodalWeights(crackTip, tipSystem, tipElements);

            foreach (var pair in elementWeights)
            {
                XContinuumElement2D element      = pair.Key;
                double[]            nodalWeights = pair.Value;

                //TODO: This needs refactoring ASAP.
                XSubdomain subdomain            = element.Subdomain;
                double[]   elementDisplacements =
                    subdomain.CalculateElementDisplacements(element, totalFreeDisplacements[subdomain.ID]);
                (double[] standardElementDisplacements, double[] enrichedElementDisplacements) =
                    element.SeparateStdEnrVector(elementDisplacements);

                //Vector standardElementDisplacements = dofOrderer.ExtractDisplacementVectorOfElementFromGlobal(
                //    element, totalFreeDisplacements, totalConstrainedDisplacements);
                //Vector enrichedElementDisplacements = dofOrderer.ExtractEnrichedDisplacementsOfElementFromGlobal(
                //    element, totalFreeDisplacements);

                double partialIntegralMode1, partialIntegralMode2;
                ComputeInteractionIntegrals(element, Vector.CreateFromArray(standardElementDisplacements),
                                            Vector.CreateFromArray(enrichedElementDisplacements), nodalWeights, tipSystem,
                                            out partialIntegralMode1, out partialIntegralMode2);

                interactionIntegralMode1 += partialIntegralMode1;
                interactionIntegralMode2 += partialIntegralMode2;
            }

            double sifMode1 = sifCalculationStrategy.CalculateSIF(interactionIntegralMode1);
            double sifMode2 = sifCalculationStrategy.CalculateSIF(interactionIntegralMode2);

            Logger.InteractionIntegralsMode1.Add(interactionIntegralMode1);
            Logger.InteractionIntegralsMode2.Add(interactionIntegralMode2);
            Logger.SIFsMode1.Add(sifMode1);
            Logger.SIFsMode2.Add(sifMode2);

            return(sifMode1, sifMode2);
        }
Exemple #15
0
        public (double growthAngle, double growthLength) Propagate(Dictionary <int, Vector> totalFreeDisplacements,
                                                                   CartesianPoint crackTip, TipCoordinateSystem tipSystem, IReadOnlyList <XContinuumElement2D> tipElements)
        {
            // TODO: Also check if the sifs do not violate the material toughness
            (double sifMode1, double sifMode2) = ComputeSIFS(totalFreeDisplacements, crackTip, tipSystem, tipElements);
            double growthAngle  = growthDirectionLaw.ComputeGrowthAngle(sifMode1, sifMode2);
            double growthLength = growthLengthLaw.ComputeGrowthLength(sifMode1, sifMode2);

            Logger.GrowthAngles.Add(growthAngle);
            Logger.GrowthLengths.Add(growthLength);
            return(growthAngle, growthLength);
        }
Exemple #16
0
        private void ComputeInteractionIntegrals(XContinuumElement2D element, Vector standardNodalDisplacements,
                                                 Vector enrichedNodalDisplacements, double[] nodalWeights, TipCoordinateSystem tipSystem,
                                                 out double integralMode1, out double integralMode2)
        {
            integralMode1 = 0.0;
            integralMode2 = 0.0;
            foreach (GaussPoint naturalGP in element.JintegralStrategy.GenerateIntegrationPoints(element))
            {
                // Nomenclature: global = global cartesian system, natural = element natural system,
                // local = tip local cartesian system

                EvalInterpolation2D evaluatedInterpolation =
                    element.Interpolation.EvaluateAllAt(element.Nodes, naturalGP);
                CartesianPoint globalGP     = evaluatedInterpolation.TransformPointNaturalToGlobalCartesian();
                Matrix         constitutive =
                    element.Material.CalculateConstitutiveMatrixAt(naturalGP, evaluatedInterpolation);

                // State 1
                Matrix2by2 globalDisplacementGradState1 = element.CalculateDisplacementFieldGradient(
                    naturalGP, evaluatedInterpolation, standardNodalDisplacements, enrichedNodalDisplacements);
                Tensor2D   globalStressState1          = element.CalculateStressTensor(globalDisplacementGradState1, constitutive);
                Matrix2by2 localDisplacementGradState1 = tipSystem.
                                                         TransformVectorFieldDerivativesGlobalCartesianToLocalCartesian(globalDisplacementGradState1);
                Tensor2D localStressTensorState1 = tipSystem.
                                                   TransformTensorGlobalCartesianToLocalCartesian(globalStressState1);

                // Weight Function
                // TODO: There should be a method InterpolateScalarGradient(double[] nodalValues) in EvaluatedInterpolation
                // TODO: Rewrite this as a shapeGradients (matrix) * nodalWeights (vector) operation.
                var globalWeightGradient = Vector2.CreateZero();
                for (int nodeIdx = 0; nodeIdx < element.Nodes.Count; ++nodeIdx)
                {
                    globalWeightGradient.AxpyIntoThis(
                        evaluatedInterpolation.ShapeGradientsCartesian.GetRow(nodeIdx), // Previously: GetGlobalCartesianDerivativesOf(element.Nodes[nodeIdx])
                        nodalWeights[nodeIdx]);
                }
                Vector2 localWeightGradient = tipSystem.
                                              TransformScalarFieldDerivativesGlobalCartesianToLocalCartesian(globalWeightGradient);

                // State 2
                // TODO: XContinuumElement shouldn't have to pass tipCoordinate system to auxiliaryStates.
                // It would be better to have CrackTip handle this and the coordinate transformations. That would also
                // obey LoD, but a lot of wrapper methods would be required.
                AuxiliaryStatesTensors auxiliary = auxiliaryStatesStrategy.ComputeTensorsAt(globalGP, tipSystem);

                // Interaction integrals
                double integrandMode1 = ComputeJIntegrand(localWeightGradient, localDisplacementGradState1,
                                                          localStressTensorState1, auxiliary.DisplacementGradientMode1,
                                                          auxiliary.StrainTensorMode1, auxiliary.StressTensorMode1);
                double integrandMode2 = ComputeJIntegrand(localWeightGradient, localDisplacementGradState1,
                                                          localStressTensorState1, auxiliary.DisplacementGradientMode2,
                                                          auxiliary.StrainTensorMode2, auxiliary.StressTensorMode2);

                integralMode1 += integrandMode1 * evaluatedInterpolation.Jacobian.DirectDeterminant * naturalGP.Weight;
                integralMode2 += integrandMode2 * evaluatedInterpolation.Jacobian.DirectDeterminant * naturalGP.Weight;
            }
        }