Пример #1
0
        public Matrix CalculateConstitutiveMatrixAt(NaturalPoint point, EvalInterpolation2D interpolation)
        {
            double eqE, eqV;

            if (IsMaterial1(point, interpolation))
            {
                eqE = EquivalentYoungModulus1;
                eqV = EquivalentPoissonRatio1;
            }
            else
            {
                eqE = EquivalentYoungModulus2;
                eqV = EquivalentPoissonRatio2;
            }

            double scalar = eqE / (1 - eqV * eqV);
            var    matrix = Matrix.CreateZero(3, 3);

            matrix[0, 0] = scalar;
            matrix[0, 1] = scalar * eqV;
            matrix[1, 0] = scalar * eqV;
            matrix[1, 1] = scalar;
            matrix[2, 2] = 0.5 * eqE / (1 + eqV);
            return(matrix);
        }
Пример #2
0
        public EvaluatedFunction2D[] EvaluateAllAt(NaturalPoint point, XContinuumElement2D element,
                                                   EvalInterpolation2D interpolation)
        {
            CartesianPoint cartesianPoint = interpolation.TransformPointNaturalToGlobalCartesian();
            double         signedDistance = crackDescription.SignedDistanceOf(point, element, interpolation);

            return(new EvaluatedFunction2D[] { enrichmentFunction.EvaluateAllAt(signedDistance) });
        }
Пример #3
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;
            }
        }
Пример #4
0
        public override EvaluatedFunction2D[] EvaluateAllAt(NaturalPoint point, XContinuumElement2D element,
                                                            EvalInterpolation2D interpolation)
        {
            CartesianPoint cartesianPoint = interpolation.TransformPointNaturalToGlobalCartesian();
            double         signedDistance = Discontinuity.SignedDistanceOf(cartesianPoint);
            Vector2        normalVector   = Discontinuity.NormalVectorThrough(cartesianPoint);

            return(new EvaluatedFunction2D[] { enrichmentFunction.EvaluateAllAt(signedDistance, normalVector) });
        }
        /// <summary>
        /// Warning: with narrow band this should throw an exception if the element/nodes are not tracked.
        /// </summary>
        /// <param name="point"></param>
        /// <param name="elementNodes"></param>
        /// <param name="interpolation"></param>
        /// <returns></returns>
        public double SignedDistanceOf(NaturalPoint point, XContinuumElement2D element,
                                       EvalInterpolation2D interpolation)
        {
            double signedDistance = 0.0;

            for (int nodeIdx = 0; nodeIdx < element.Nodes.Count; ++nodeIdx)
            {
                signedDistance += interpolation.ShapeFunctions[nodeIdx] * levelSetsBody[element.Nodes[nodeIdx]];
            }
            return(signedDistance);
        }
Пример #6
0
        public Tensor2D EvaluateAt(XContinuumElement2D element, NaturalPoint point,
                                   Vector standardDisplacements, Vector enrichedDisplacements)
        {
            EvalInterpolation2D evaluatedInterpolation = element.Interpolation.EvaluateAllAt(element.Nodes, point);
            Matrix2by2          displacementGradient   = element.CalculateDisplacementFieldGradient(
                point, evaluatedInterpolation, standardDisplacements, enrichedDisplacements);
            Matrix constitutive =
                element.Material.CalculateConstitutiveMatrixAt(point, evaluatedInterpolation);

            return(element.CalculateStressTensor(displacementGradient, constitutive));
        }
Пример #7
0
        public Tensor2D EvaluateAt(XContinuumElement2D element, NaturalPoint point,
                                   Vector standardDisplacements, Vector enrichedDisplacements)
        {
            EvalInterpolation2D evaluatedInterpolation = element.Interpolation.EvaluateAllAt(element.Nodes, point);
            Matrix2by2          displacementGradient   = element.CalculateDisplacementFieldGradient(
                point, evaluatedInterpolation, standardDisplacements, enrichedDisplacements);

            double strainXX = displacementGradient[0, 0];
            double strainYY = displacementGradient[1, 1];
            double strainXY = 0.5 * (displacementGradient[0, 1] + displacementGradient[1, 0]);

            return(new Tensor2D(strainXX, strainYY, strainXY));
        }
        public Matrix CalculateConstitutiveMatrixAt(NaturalPoint point, EvalInterpolation2D interpolation)
        {
            var    matrix = Matrix.CreateZero(3, 3);
            double eqE    = HomogeneousEquivalentYoungModulus;
            double eqV    = HomogeneousEquivalentPoissonRatio;
            double scalar = eqE / (1 - eqV * eqV);

            matrix[0, 0] = scalar;
            matrix[0, 1] = scalar * eqV;
            matrix[1, 0] = scalar * eqV;
            matrix[1, 1] = scalar;
            matrix[2, 2] = 0.5 * eqE / (1 + eqV);
            return(matrix);
        }
        public EvaluatedFunction2D[] EvaluateAllAt(NaturalPoint point, XContinuumElement2D element,
                                                   EvalInterpolation2D interpolation)
        {
            PolarPoint2D polarPoint = TipSystem.TransformPointGlobalCartesianToLocalPolar(
                interpolation.TransformPointNaturalToGlobalCartesian());
            TipJacobians tipJacobians = TipSystem.CalculateJacobiansAt(polarPoint);

            var enrichments = new EvaluatedFunction2D[enrichmentFunctions.Count];

            for (int i = 0; i < enrichments.Length; ++i)
            {
                enrichments[i] = enrichmentFunctions[i].EvaluateAllAt(polarPoint, tipJacobians);
            }
            return(enrichments);
        }
Пример #10
0
        private (Tensor2D strain, Tensor2D stress) ComputeStrainStress(XContinuumElement2D element, NaturalPoint gaussPoint,
                                                                       EvalInterpolation2D evaluatedInterpolation, Vector standardNodalDisplacements,
                                                                       Vector enrichedNodalDisplacements)
        {
            Matrix constitutive =
                element.Material.CalculateConstitutiveMatrixAt(gaussPoint, evaluatedInterpolation);
            Matrix2by2 displacementGradient = element.CalculateDisplacementFieldGradient(gaussPoint, evaluatedInterpolation,
                                                                                         standardNodalDisplacements, enrichedNodalDisplacements);

            double strainXX       = displacementGradient[0, 0];
            double strainYY       = displacementGradient[1, 1];
            double strainXYtimes2 = displacementGradient[0, 1] + displacementGradient[1, 0];

            double stressXX = constitutive[0, 0] * strainXX + constitutive[0, 1] * strainYY;
            double stressYY = constitutive[1, 0] * strainXX + constitutive[1, 1] * strainYY;
            double stressXY = constitutive[2, 2] * strainXYtimes2;

            return(new Tensor2D(strainXX, strainYY, 0.5 * strainXYtimes2), new Tensor2D(stressXX, stressYY, stressXY));
        }
Пример #11
0
        }                               // Do nothing for elastic properties.

        private bool IsMaterial1(NaturalPoint point, EvalInterpolation2D interpolation)
        {
            //TODO: This should be done with the natural points and LSM.
            CartesianPoint cartesianPoint = interpolation.TransformPointNaturalToGlobalCartesian();

            MaterialInterface2D.Subdomain subdomain = bimaterialInterface.LocatePoint(cartesianPoint);
            if (subdomain == MaterialInterface2D.Subdomain.Positive)
            {
                return(true);
            }
            else if (subdomain == MaterialInterface2D.Subdomain.Negative)
            {
                return(false);
            }
            else
            {
                throw new ArgumentException("The point (xi, eta) = " + point + " - (x, y) = " + cartesianPoint +
                                            ", lies on the bi-material interface");
            }
        }
Пример #12
0
        // Computes stresses directly at the nodes. The other approach is to compute them at Gauss points and then extrapolate
        private IReadOnlyDictionary <XNode, Tensor2D> ComputeNodalStressesOfElement(XContinuumElement2D element,
                                                                                    Vector freeDisplacements, Vector constrainedDisplacements)
        {
            Vector standardDisplacements = dofOrderer.ExtractDisplacementVectorOfElementFromGlobal(element,
                                                                                                   freeDisplacements, constrainedDisplacements);
            Vector enrichedDisplacements =
                dofOrderer.ExtractEnrichedDisplacementsOfElementFromGlobal(element, freeDisplacements);

            IReadOnlyList <NaturalPoint> naturalNodes = element.Interpolation.NodalNaturalCoordinates;
            var nodalStresses = new Dictionary <XNode, Tensor2D>();

            for (int i = 0; i < element.Nodes.Count; ++i)
            {
                EvalInterpolation2D evaluatedInterpolation =
                    element.Interpolation.EvaluateAllAt(element.Nodes, naturalNodes[i]);
                Matrix2by2 displacementGradient = element.CalculateDisplacementFieldGradient(
                    naturalNodes[i], evaluatedInterpolation, standardDisplacements, enrichedDisplacements);
                Matrix constitutive =
                    element.Material.CalculateConstitutiveMatrixAt(naturalNodes[i], evaluatedInterpolation);
                nodalStresses[element.Nodes[i]] = element.CalculateStressTensor(displacementGradient, constitutive);
            }

            return(nodalStresses);
        }
        public Tuple <double, double> SignedDistanceGradientThrough(NaturalPoint point,
                                                                    IReadOnlyList <XNode> elementNodes, EvalInterpolation2D interpolation)
        {
            double gradientX = 0.0;
            double gradientY = 0.0;

            for (int nodeIdx = 0; nodeIdx < elementNodes.Count; ++nodeIdx)
            {
                double dNdx = interpolation.ShapeGradientsCartesian[nodeIdx, 0];
                double dNdy = interpolation.ShapeGradientsCartesian[nodeIdx, 1];

                double levelSet = levelSetsBody[elementNodes[nodeIdx]];
                gradientX += dNdx * levelSet;
                gradientY += dNdy * levelSet;
            }
            return(new Tuple <double, double>(gradientX, gradientY));
        }
        // 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);
        }
Пример #15
0
        public void WriteOutputData(IDofOrderer dofOrderer, Vector freeDisplacements, Vector constrainedDisplacements, int step)
        {
            // TODO: guess initial capacities from previous steps or from the model
            var allPoints     = new List <VtkPoint>();
            var allCells      = new List <VtkCell>();
            var displacements = new List <double[]>();
            var strains       = new List <Tensor2D>();
            var stresses      = new List <Tensor2D>();
            int pointCounter  = 0;

            foreach (XContinuumElement2D element in model.Elements)
            {
                Vector standardDisplacements = dofOrderer.ExtractDisplacementVectorOfElementFromGlobal(element,
                                                                                                       freeDisplacements, constrainedDisplacements);
                Vector enrichedDisplacements =
                    dofOrderer.ExtractEnrichedDisplacementsOfElementFromGlobal(element, freeDisplacements);
                bool mustTriangulate = MustBeTriangulated(element, out ISingleCrack intersectingCrack);

                if (!mustTriangulate)
                {
                    // Mesh
                    var cellPoints = new VtkPoint[element.Nodes.Count];
                    for (int p = 0; p < cellPoints.Length; ++p)
                    {
                        cellPoints[p] = new VtkPoint(pointCounter++, element.Nodes[p]);
                        allPoints.Add(cellPoints[p]);
                    }
                    allCells.Add(new VtkCell(element.CellType, cellPoints));

                    // Displacements
                    for (int p = 0; p < cellPoints.Length; ++p)
                    {
                        displacements.Add(new double[] { standardDisplacements[2 * p], standardDisplacements[2 * p + 1] });
                    }

                    // Strains and stresses at Gauss points of element
                    // WARNING: do not use the quadrature object, since GPs are sorted differently.
                    IReadOnlyList <GaussPoint> gaussPoints = element.GaussPointExtrapolation.Quadrature.IntegrationPoints;
                    var strainsAtGPs  = new Tensor2D[gaussPoints.Count];
                    var stressesAtGPs = new Tensor2D[gaussPoints.Count];
                    for (int gp = 0; gp < gaussPoints.Count; ++gp)
                    {
                        EvalInterpolation2D evalInterpol =
                            element.Interpolation.EvaluateAllAt(element.Nodes, gaussPoints[gp]);
                        (Tensor2D strain, Tensor2D stress) = ComputeStrainStress(element, gaussPoints[gp],
                                                                                 evalInterpol, standardDisplacements, enrichedDisplacements);
                        strainsAtGPs[gp]  = strain;
                        stressesAtGPs[gp] = stress;
                    }

                    // Extrapolate strains and stresses to element nodes. This is exact, since the element is not enriched
                    IReadOnlyList <Tensor2D> strainsAtNodes = element.GaussPointExtrapolation.
                                                              ExtrapolateTensorFromGaussPointsToNodes(strainsAtGPs, element.Interpolation);
                    IReadOnlyList <Tensor2D> stressesAtNodes = element.GaussPointExtrapolation.
                                                               ExtrapolateTensorFromGaussPointsToNodes(stressesAtGPs, element.Interpolation);
                    for (int p = 0; p < cellPoints.Length; ++p)
                    {
                        strains.Add(strainsAtNodes[p]);
                        stresses.Add(stressesAtNodes[p]);
                    }
                }
                else
                {
                    // Triangulate and then operate on each triangle
                    SortedSet <CartesianPoint> triangleVertices            = intersectingCrack.FindTriangleVertices(element);
                    IReadOnlyList <Triangle2D <CartesianPoint> > triangles = triangulator.CreateMesh(triangleVertices);

                    foreach (Triangle2D <CartesianPoint> triangle in triangles)
                    {
                        // Mesh
                        int numTriangleNodes = 3;
                        var cellPoints       = new VtkPoint[numTriangleNodes];
                        for (int p = 0; p < numTriangleNodes; ++p)
                        {
                            CartesianPoint point = triangle.Vertices[p];
                            cellPoints[p] = new VtkPoint(pointCounter++, point.X, point.Y, point.Z);
                            allPoints.Add(cellPoints[p]);
                        }
                        allCells.Add(new VtkCell(CellType.Tri3, cellPoints));

                        // Displacements, strains and stresses are not defined on the crack, thus they must be evaluated at GPs
                        // and extrapolated to each point of interest. However how should I choose the Gauss points? Here I take
                        // the Gauss points of the subtriangles.
                        IGaussPointExtrapolation2D    extrapolation = ExtrapolationGaussTriangular3Points.UniqueInstance;
                        IIsoparametricInterpolation2D interpolation = InterpolationTri3.UniqueInstance;

                        // Find the Gauss points of the triangle in the natural system of the element
                        IInverseInterpolation2D inverseMapping = element.Interpolation.CreateInverseMappingFor(element.Nodes);
                        var triangleNodesNatural = new NaturalPoint[numTriangleNodes];
                        for (int p = 0; p < numTriangleNodes; ++p)
                        {
                            triangleNodesNatural[p] = inverseMapping.TransformPointCartesianToNatural(cellPoints[p]);
                        }
                        NaturalPoint[] triangleGPsNatural =
                            FindTriangleGPsNatural(triangleNodesNatural, extrapolation.Quadrature.IntegrationPoints);

                        // Find the field values at the Gauss points of the triangle (their coordinates are in the natural
                        // system of the element)
                        var displacementsAtGPs = new double[triangleGPsNatural.Length][];
                        var strainsAtGPs       = new Tensor2D[triangleGPsNatural.Length];
                        var stressesAtGPs      = new Tensor2D[triangleGPsNatural.Length];
                        for (int gp = 0; gp < triangleGPsNatural.Length; ++gp)
                        {
                            EvalInterpolation2D evalInterpol =
                                element.Interpolation.EvaluateAllAt(element.Nodes, triangleGPsNatural[gp]);
                            displacementsAtGPs[gp] = element.CalculateDisplacementField(triangleGPsNatural[gp],
                                                                                        evalInterpol, standardDisplacements, enrichedDisplacements).CopyToArray();
                            (Tensor2D strain, Tensor2D stress) = ComputeStrainStress(element, triangleGPsNatural[gp],
                                                                                     evalInterpol, standardDisplacements, enrichedDisplacements);
                            strainsAtGPs[gp]  = strain;
                            stressesAtGPs[gp] = stress;
                        }

                        // Extrapolate the field values to the triangle nodes. We need their coordinates in the auxiliary
                        // system of the triangle. We could use the inverse interpolation of the triangle to map the natural
                        // (element local) coordinates of the nodes to the auxiliary system of the triangle. Fortunately they
                        // can be accessed by the extrapolation object directly.
                        IReadOnlyList <double[]> displacementsAtTriangleNodes =
                            extrapolation.ExtrapolateVectorFromGaussPointsToNodes(displacementsAtGPs, interpolation);
                        IReadOnlyList <Tensor2D> strainsAtTriangleNodes =
                            extrapolation.ExtrapolateTensorFromGaussPointsToNodes(strainsAtGPs, interpolation);
                        IReadOnlyList <Tensor2D> stressesAtTriangleNodes =
                            extrapolation.ExtrapolateTensorFromGaussPointsToNodes(stressesAtGPs, interpolation);
                        for (int p = 0; p < numTriangleNodes; ++p)
                        {
                            displacements.Add(displacementsAtTriangleNodes[p]);
                            strains.Add(strainsAtTriangleNodes[p]);
                            stresses.Add(stressesAtTriangleNodes[p]);
                        }
                    }
                }
            }

            using (var writer = new VtkFileWriter($"{pathNoExtension}_{step}.vtk"))
            {
                writer.WriteMesh(allPoints, allCells);
                writer.WriteVector2DField("displacement", displacements);
                writer.WriteTensor2DField("strain", strains);
                writer.WriteTensor2DField("stress", stresses);
            }
        }
 public double GetThicknessAt(NaturalPoint point, EvalInterpolation2D interpolation)
 => HomogeneousThickness;
Пример #17
0
 public double GetThicknessAt(NaturalPoint point, EvalInterpolation2D interpolation)
 => IsMaterial1(point, interpolation) ? Thickness1 : Thickness2;
Пример #18
0
 public double GetEquivalentPoissonRatioAt(NaturalPoint point, EvalInterpolation2D interpolation)
 => IsMaterial1(point, interpolation) ? EquivalentPoissonRatio1 : EquivalentPoissonRatio2;
Пример #19
0
        private void FindSignedAreasOfElement(XContinuumElement2D element,
                                              out double positiveArea, out double negativeArea)
        {
            SortedSet <CartesianPoint> triangleVertices            = FindTriangleVertices(element);
            IReadOnlyList <Triangle2D <CartesianPoint> > triangles = triangulator.CreateMesh(triangleVertices);

            positiveArea = 0.0;
            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)
                {
                    if (vertex is XNode)
                    {
                        sign = Math.Sign(levelSetsBody[(XNode)vertex]);
                        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(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");
                }
            }
        }
 public abstract EvaluatedFunction2D[] EvaluateAllAt(NaturalPoint point, XContinuumElement2D element,
                                                     EvalInterpolation2D interpolation);
 public double GetEquivalentPoissonRatioAt(NaturalPoint point, EvalInterpolation2D interpolation)
 => HomogeneousEquivalentPoissonRatio;
Пример #22
0
 public double SignedDistanceOf(NaturalPoint point, XContinuumElement2D element,
                                EvalInterpolation2D interpolation)
 {
     return(SignedDistanceOfPoint(interpolation.TransformPointNaturalToGlobalCartesian()));
 }
Пример #23
0
 public double GetEquivalentYoungModulusAt(NaturalPoint point, EvalInterpolation2D interpolation)
 => IsMaterial1(point, interpolation) ? EquivalentYoungModulus1 : EquivalentYoungModulus2;
 public double GetEquivalentYoungModulusAt(NaturalPoint point, EvalInterpolation2D interpolation)
 => HomogeneousEquivalentYoungModulus;