コード例 #1
0
 private InterpolationHexa8() : base(8)
 {
     NodalNaturalCoordinates = new NaturalPoint[]
     {
         new NaturalPoint(-1, -1, -1),
         new NaturalPoint(1, -1, -1),
         new NaturalPoint(1, 1, -1),
         new NaturalPoint(-1, 1, -1),
         new NaturalPoint(-1, -1, 1),
         new NaturalPoint(1, -1, 1),
         new NaturalPoint(1, 1, 1),
         new NaturalPoint(-1, 1, 1),
     };
 }
コード例 #2
0
        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 levelSet = levelSetsBody[elementNodes[nodeIdx]];
                gradientX += interpolation.ShapeGradientsCartesian[nodeIdx, 0] * levelSet;
                gradientY += interpolation.ShapeGradientsCartesian[nodeIdx, 1] * levelSet;
            }
            return(new Tuple <double, double>(gradientX, gradientY));
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        /// <summary>
        /// Calculates a vector quantity at a given point by extrapolating (or interpolating) its known values at
        /// the integration points.
        /// </summary>
        /// <param name="vectorsAtGaussPoints">Their order must be the same as the order of integration points defined by
        ///     <see cref="Quadrature"/>.</param>
        /// <param name="naturalPoint">The point where the tensor will be computed. Its coordinates are expressed in the natural
        ///     (element local) system, instead of the coordinate system defined by the integration points.</param>
        /// <returns></returns>
        public double[] ExtrapolateVectorFromGaussPoints(IReadOnlyList <double[]> vectorsAtGaussPoints,
                                                         NaturalPoint naturalPoint)
        {
            double[] extrapolationFunctions = EvaluateExtrapolationFunctionsAt(naturalPoint);
            var      vector = new double[3];

            for (int gp = 0; gp < Quadrature.IntegrationPoints.Count; gp++)
            {
                vector[0] += extrapolationFunctions[gp] * vectorsAtGaussPoints[gp][0];
                vector[1] += extrapolationFunctions[gp] * vectorsAtGaussPoints[gp][1];
                vector[2] += extrapolationFunctions[gp] * vectorsAtGaussPoints[gp][1];
            }

            return(vector);
        }
コード例 #5
0
 private InterpolationShell8() : base(8)
 {
     NodalNaturalCoordinates = new NaturalPoint[]
     {
         //TODO: validate this
         new NaturalPoint(1, 1, 0),
         new NaturalPoint(-1, 1, 0),
         new NaturalPoint(-1, -1, 0),
         new NaturalPoint(1, -1, 0),
         new NaturalPoint(0, 1, 0),
         new NaturalPoint(-1, 0, 0),
         new NaturalPoint(0, -1, 0),
         new NaturalPoint(1, 0, 0)
     };
 }
コード例 #6
0
        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);
        }
コード例 #7
0
        /// <summary>
        /// Generates random points in the tetrahedron.
        /// </summary>
        /// <returns></returns>
        private static NaturalPoint[] GenerateRandomPointsInTetrahedron()
        {
            var rand         = new Random();
            var randomPoints = new NaturalPoint[numRandomPoints];

            for (int i = 0; i < numRandomPoints; i++)
            {
                double xi   = rand.NextDouble();
                double eta  = rand.NextDouble() * xi;
                double zeta = rand.NextDouble() * eta;
                randomPoints[i] = new NaturalPoint(xi, eta, zeta);
            }

            return(randomPoints);
        }
コード例 #8
0
        /// <summary>
        /// Generates random points inside a pyramid <see cref="https://people.sc.fsu.edu/~jburkardt/m_src/pyramid_grid/pyramid_grid.html"/>
        /// </summary>
        /// <returns></returns>
        private static NaturalPoint[] GenerateRandomPointsInPyramid()
        {
            var rand         = new Random();
            var randomPoints = new NaturalPoint[numRandomPoints];

            for (int i = 0; i < numRandomPoints; i++)
            {
                double zeta = rand.NextDouble();
                double xi   = (-1 + rand.NextDouble() * 2.0) * (1 - zeta);
                double eta  = (-1 + rand.NextDouble() * 2.0) * xi;
                randomPoints[i] = new NaturalPoint(xi, eta, zeta);
            }

            return(randomPoints);
        }
コード例 #9
0
        /// <summary>
        /// Generates random points in a wedge
        /// </summary>
        /// <returns></returns>
        private static NaturalPoint[] GenerarandomPointsInWedge()
        {
            var rand         = new Random();
            var randomPoints = new NaturalPoint[numRandomPoints];

            for (int i = 0; i < numRandomPoints; i++)
            {
                double xi   = -1 + rand.NextDouble() * 2.0;
                double eta  = rand.NextDouble();
                double zeta = rand.NextDouble() * eta;
                randomPoints[i] = new NaturalPoint(xi, eta, zeta);
            }

            return(randomPoints);
        }
コード例 #10
0
        private InterpolationQuad8() : base(CellType.Quad8, 8)
        {
            NodalNaturalCoordinates = new NaturalPoint[]
            {
                new NaturalPoint(-1.0, -1.0),
                new NaturalPoint(+1.0, -1.0),
                new NaturalPoint(+1.0, +1.0),
                new NaturalPoint(-1.0, +1.0),

                new NaturalPoint(+0.0, -1.0),
                new NaturalPoint(+1.0, +0.0),
                new NaturalPoint(+0.0, +1.0),
                new NaturalPoint(-1.0, +0.0),
            };
        }
コード例 #11
0
 private InterpolationShell8Cohesive() : base(CellType.Quad8, 8)
 {
     cachedN3AtGPs           = new Dictionary <IQuadrature2D, IReadOnlyList <Matrix> >();
     NodalNaturalCoordinates = new NaturalPoint[]
     {
         //TODO: validate this
         new NaturalPoint(1, 1),
         new NaturalPoint(-1, 1),
         new NaturalPoint(-1, -1),
         new NaturalPoint(1, -1),
         new NaturalPoint(0, 1),
         new NaturalPoint(-1, 0),
         new NaturalPoint(0, -1),
         new NaturalPoint(1, 0)
     };
 }
コード例 #12
0
        /// <summary>
        /// Calculates a tensor quantity at a given point by extrapolating (or interpolating) its known values at
        /// the integration points.
        /// </summary>
        /// <param name="tensorsAtGaussPoints">Their order must be the same as the order of integration points defined by
        ///     <see cref="Quadrature"/>.</param>
        /// <param name="naturalPoint">The point where the tensor will be computed. Its coordinates are expressed in the natural
        ///     (element local) system, instead of the coordinate system defined by the integration points.</param>
        /// <returns></returns>
        public double[] ExtrapolateTensorFromGaussPoints(IReadOnlyList <double[]> tensorsAtGaussPoints,
                                                         NaturalPoint naturalPoint)
        {
            double[] extrapolationFunctions = EvaluateExtrapolationFunctionsAt(naturalPoint);
            var      tensor = new double[6];

            for (int gp = 0; gp < Quadrature.IntegrationPoints.Count; gp++)
            {
                tensor[0] += extrapolationFunctions[gp] * tensorsAtGaussPoints[gp][0];
                tensor[1] += extrapolationFunctions[gp] * tensorsAtGaussPoints[gp][1];
                tensor[2] += extrapolationFunctions[gp] * tensorsAtGaussPoints[gp][2];
                tensor[3] += extrapolationFunctions[gp] * tensorsAtGaussPoints[gp][3];
                tensor[4] += extrapolationFunctions[gp] * tensorsAtGaussPoints[gp][4];
                tensor[5] += extrapolationFunctions[gp] * tensorsAtGaussPoints[gp][5];
            }

            return(tensor);
        }
コード例 #13
0
        protected override double[] EvaluateExtrapolationFunctionsAt(NaturalPoint point)
        {
            // Coordinates of the point in the auxiliary coordinate system of an imaginary "Gauss element" that has the Gauss
            // points as its nodes.
            double r = 2.0 * point.Xi - oneOverThree;
            double s = 2.0 * point.Eta - oneOverThree;

            // Shape functions of the imaginary "Gauss element".
            // Each shape function corresponds to an integration point of GaussQuadratureForTrianglesSymmetric.Order2Points3.
            // Therefore their order must be the same: point on Xi, point on Eta, point at right angle. This might differ from
            // the node order in InterpolationTri3.
            var shapeFunctions = new double[3];

            shapeFunctions[0] = r;
            shapeFunctions[1] = s;
            shapeFunctions[2] = 1 - r - s;
            return(shapeFunctions);
        }
コード例 #14
0
        private InterpolationTet10() : base(10)
        {
            NodalNaturalCoordinates = new NaturalPoint[]
            {
                new NaturalPoint(0, 0, 0),
                new NaturalPoint(1, 0, 0),
                new NaturalPoint(0, 1, 0),
                new NaturalPoint(0, 0, 1),

                new NaturalPoint(0.5, 0, 0),
                new NaturalPoint(0.5, 0.5, 0),
                new NaturalPoint(0, 0.5, 0),

                new NaturalPoint(0, 0, 0.5),
                new NaturalPoint(0, 0.5, 0.5),
                new NaturalPoint(0.5, 0, 0.5),
            };
        }
コード例 #15
0
        protected override double[] EvaluateExtrapolationFunctionsAt(NaturalPoint point)
        {
            // Coordinates of the point in the auxiliary coordinate system of an imaginary "Gauss element" that has the Gauss
            // points as its nodes.
            double r = sqrt3 * point.Xi;
            double s = sqrt3 * point.Eta;

            // Shape functions of the imaginary "Gauss element".
            // Each shape function corresponds to an integration point of Gauss-Legendre 2x2. Therefore their order is the same
            // as the one defined by GaussLegendre2D.Order2x2, namely Xi minor/Eta major, instead of the usual Quad4 order.
            var shapeFunctions = new double[4];                         // The usual Quad4 shape function would be:

            shapeFunctions[0] = 0.25 * (1 - r) * (1 - s);               // N0
            shapeFunctions[1] = 0.25 * (1 + r) * (1 - s);               // N1

            shapeFunctions[2] = 0.25 * (1 - r) * (1 + s);               // N3
            shapeFunctions[3] = 0.25 * (1 + r) * (1 + s);               // N2
            return(shapeFunctions);
        }
コード例 #16
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");
            }
        }
コード例 #17
0
        private static void TestInverseMapping()
        {
            var directMapping   = InterpolationQuad4.UniqueInstance;
            int numRandomPoints = 10;

            NaturalPoint[]       naturalPoints = GenerateRandomPointsInSquare(numRandomPoints);
            IReadOnlyList <Node> elementNodes  = nodeSet;

            for (int i = 0; i < 4; ++i)
            {
                IInverseInterpolation2D inverseMapping = directMapping.CreateInverseMappingFor(elementNodes);
                foreach (NaturalPoint originalPoint in naturalPoints)
                {
                    CartesianPoint cartesianPoint = directMapping.TransformNaturalToCartesian(elementNodes, originalPoint);
                    NaturalPoint   remappedPoint  = inverseMapping.TransformPointCartesianToNatural(cartesianPoint);
                    Assert.True(Coincide(originalPoint, remappedPoint));
                }

                elementNodes = CycleNodes(elementNodes);                 // The next iteration will use a different node order
            }
        }
コード例 #18
0
        private InterpolationPyra13() : base(13)
        {
            NodalNaturalCoordinates = new NaturalPoint[]
            {
                new NaturalPoint(1, 0, 0),
                new NaturalPoint(0, 1, 0),
                new NaturalPoint(-1, 0, 0),
                new NaturalPoint(0, -1, 0),
                new NaturalPoint(0, 0, 1),

                new NaturalPoint(0.5, 0.5, 0),
                new NaturalPoint(0.5, -0.5, 0),
                new NaturalPoint(0.5, 0, 0.5),
                new NaturalPoint(-0.5, 0.5, 0),
                new NaturalPoint(0, 0.5, 0.5),

                new NaturalPoint(-0.5, -0.5, 0),
                new NaturalPoint(-0.5, 0, 0.5),
                new NaturalPoint(0, -0.5, 0.5),
            };
        }
コード例 #19
0
        private Matrix CalculateNURBS2D(int degreeKsi, int degreeHeta, IVector knotValueVectorKsi,
                                        IVector knotValueVectorHeta, NaturalPoint naturalPoint, List <IWeightedPoint> patchControlPoints)
        {
            var numberOfCPKsi  = knotValueVectorKsi.Length - degreeKsi - 1;
            var numberOfCPHeta = knotValueVectorHeta.Length - degreeHeta - 1;

            BSPLines1D bsplinesKsi  = new BSPLines1D(degreeKsi, knotValueVectorKsi, Vector.CreateFromArray(new double[] { naturalPoint.Xi }));
            BSPLines1D bsplinesHeta = new BSPLines1D(degreeHeta, knotValueVectorHeta, Vector.CreateFromArray(new double[] { naturalPoint.Eta }));

            bsplinesKsi.calculateBSPLines();
            bsplinesHeta.calculateBSPLines();

            int numberOfElementControlPoints = patchControlPoints.Count;

            var nurbsValues = Matrix.CreateZero(numberOfElementControlPoints, 1);

            double sumKsiHeta = 0;

            for (int k = 0; k < numberOfElementControlPoints; k++)
            {
                int indexKsi  = patchControlPoints[k].ID / numberOfCPHeta;
                int indexHeta = patchControlPoints[k].ID % numberOfCPHeta;
                sumKsiHeta += bsplinesKsi.BSPLineValues[indexKsi, 0] *
                              bsplinesHeta.BSPLineValues[indexHeta, 0] *
                              patchControlPoints[k].WeightFactor;
            }

            for (int k = 0; k < numberOfElementControlPoints; k++)
            {
                int indexKsi  = patchControlPoints[k].ID / numberOfCPHeta;
                int indexHeta = patchControlPoints[k].ID % numberOfCPHeta;

                nurbsValues[k, 0] =
                    bsplinesKsi.BSPLineValues[indexKsi, 0] *
                    bsplinesHeta.BSPLineValues[indexHeta, 0] *
                    patchControlPoints[k].WeightFactor / sumKsiHeta;
            }

            return(nurbsValues);
        }
コード例 #20
0
        private InterpolationHexa27() : base(27)
        {
            NodalNaturalCoordinates = new NaturalPoint[]
            {
                new NaturalPoint(-1, -1, -1),
                new NaturalPoint(1, -1, -1),
                new NaturalPoint(1, 1, -1),
                new NaturalPoint(-1, 1, -1),

                new NaturalPoint(-1, -1, 1),
                new NaturalPoint(1, -1, 1),
                new NaturalPoint(1, 1, 1),
                new NaturalPoint(-1, 1, 1),

                new NaturalPoint(0, -1, -1),
                new NaturalPoint(-1, 0, -1),
                new NaturalPoint(-1, -1, 0),
                new NaturalPoint(1, 0, -1),

                new NaturalPoint(1, -1, 0),
                new NaturalPoint(0, 1, -1),
                new NaturalPoint(1, 1, 0),
                new NaturalPoint(-1, 1, 0),

                new NaturalPoint(0, -1, 1),
                new NaturalPoint(-1, 0, 1),
                new NaturalPoint(1, 0, 1),
                new NaturalPoint(0, 1, 1),

                new NaturalPoint(0, 0, -1),
                new NaturalPoint(0, -1, 0),
                new NaturalPoint(-1, 0, 0),
                new NaturalPoint(1, 0, 0),

                new NaturalPoint(0, 1, 0),
                new NaturalPoint(0, 0, 1),
                new NaturalPoint(0, 0, 0),
            };
        }
コード例 #21
0
        private InterpolationWedge15() : base(15)
        {
            NodalNaturalCoordinates = new NaturalPoint[]
            {
                new NaturalPoint(-1, 1, 0),
                new NaturalPoint(-1, 0, 1),
                new NaturalPoint(-1, 0, 0),
                new NaturalPoint(1, 1, 0),
                new NaturalPoint(1, 0, 1),
                new NaturalPoint(1, 0, 0),

                new NaturalPoint(-1, 0.5, 0.5),
                new NaturalPoint(-1, 0.5, 0),
                new NaturalPoint(0, 1, 0),
                new NaturalPoint(-1, 0, 0.5),

                new NaturalPoint(0, 0, 1),
                new NaturalPoint(0, 0, 0),
                new NaturalPoint(1, 0.5, 0.5),
                new NaturalPoint(1, 0.5, 0),
                new NaturalPoint(1, 0, 0.5)
            };
        }
コード例 #22
0
        protected override double[] EvaluateExtrapolationFunctionsAt(NaturalPoint naturalPoint)
        {
            // Coordinates of the point in the auxiliary coordinate system of an imaginary "Gauss element" that has the Gauss
            // points as its nodes.
            double ksi  = sqrt3 * naturalPoint.Xi;
            double heta = sqrt3 * naturalPoint.Eta;
            double zeta = sqrt3 * naturalPoint.Zeta;

            // Shape functions of the imaginary "Gauss element".
            // Each shape function corresponds to an integration point of Gauss-Legendre 2x2x2. Therefore their order is the same
            // as the one defined by GaussLegendre2D.Order2x2, namely Xi major/Eta minor, instead of the usual Quad4 order.
            var values = new double[8];                                         // The usual Hexa8 shape function would be:

            values[0] = 0.125 * (1 - ksi) * (1 - heta) * (1 - zeta);            // N0
            values[1] = 0.125 * (1 + ksi) * (1 - heta) * (1 - zeta);            // N1
            values[2] = 0.125 * (1 - ksi) * (1 + heta) * (1 - zeta);            // N3
            values[3] = 0.125 * (1 + ksi) * (1 + heta) * (1 - zeta);            // N2

            values[4] = 0.125 * (1 - ksi) * (1 - heta) * (1 + zeta);            // N4
            values[5] = 0.125 * (1 + ksi) * (1 - heta) * (1 + zeta);            // N5
            values[6] = 0.125 * (1 - ksi) * (1 + heta) * (1 + zeta);            // N7
            values[7] = 0.125 * (1 + ksi) * (1 + heta) * (1 + zeta);            // N6
            return(values);
        }
コード例 #23
0
 public double SignedDistanceOf(NaturalPoint point, XContinuumElement2D element,
                                EvalInterpolation2D interpolation)
 {
     return(SignedDistanceOfPoint(interpolation.TransformPointNaturalToGlobalCartesian()));
 }
コード例 #24
0
 /// <summary>
 /// See <see cref="IIsoparametricInterpolation2D.EvaluateFunctionsAt(NaturalPoint)"/>.
 /// </summary>
 public double[] EvaluateFunctionsAt(NaturalPoint naturalPoint)
 => EvaluateAt(naturalPoint.Xi, naturalPoint.Eta);
コード例 #25
0
        /// <summary>
        /// See <see cref="IIsoparametricInterpolation2D.TransformNaturalToCartesian(IReadOnlyList{Node}, NaturalPoint)"/>.
        /// </summary>
        public CartesianPoint TransformNaturalToCartesian(IReadOnlyList <Node> nodes, NaturalPoint naturalPoint)
        {
            double[] shapeFunctionValues = EvaluateAt(naturalPoint.Xi, naturalPoint.Eta);
            double   x = 0, y = 0;

            for (int i = 0; i < nodes.Count; ++i)
            {
                x += shapeFunctionValues[i] * nodes[i].X;
                y += shapeFunctionValues[i] * nodes[i].Y;
            }
            return(new CartesianPoint(x, y));
        }
コード例 #26
0
 /// <summary>
 /// See <see cref="IIsoparametricInterpolation2D.EvaluateNaturalGradientsAt(NaturalPoint)".
 /// </summary>
 public Matrix EvaluateNaturalGradientsAt(NaturalPoint naturalPoint)
 => EvaluateGradientsAt(naturalPoint.Xi, naturalPoint.Eta);
コード例 #27
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);
            }
        }
コード例 #28
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));
        }
コード例 #29
0
 /// <summary>
 /// Calculates the functions used for extrapolating quantities from the integration points to a given point, at the
 /// given point.
 /// </summary>
 /// <param name="naturalPoint">The coordinates of the point where the extrapolation functions will be calculated, in the
 ///     natural (element local) system.</param>
 /// <returns></returns>
 protected abstract double[] EvaluateExtrapolationFunctionsAt(NaturalPoint naturalPoint);
コード例 #30
0
 public double GetThicknessAt(NaturalPoint point, EvalInterpolation2D interpolation)
 => IsMaterial1(point, interpolation) ? Thickness1 : Thickness2;