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),
     };
 }
Example #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));
        }
        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);
        }
        /// <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);
        }
Example #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)
     };
 }
        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);
        }
        /// <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);
        }
        /// <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);
        }
        /// <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);
        }
        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),
            };
        }
 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)
     };
 }
        /// <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);
        }
Example #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);
        }
        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),
            };
        }
        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);
        }
        }                               // 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");
            }
        }
        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
            }
        }
Example #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),
            };
        }
Example #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);
        }
Example #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),
            };
        }
Example #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)
            };
        }
        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);
        }
Example #23
0
 public double SignedDistanceOf(NaturalPoint point, XContinuumElement2D element,
                                EvalInterpolation2D interpolation)
 {
     return(SignedDistanceOfPoint(interpolation.TransformPointNaturalToGlobalCartesian()));
 }
Example #24
0
 /// <summary>
 /// See <see cref="IIsoparametricInterpolation2D.EvaluateFunctionsAt(NaturalPoint)"/>.
 /// </summary>
 public double[] EvaluateFunctionsAt(NaturalPoint naturalPoint)
 => EvaluateAt(naturalPoint.Xi, naturalPoint.Eta);
Example #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));
        }
Example #26
0
 /// <summary>
 /// See <see cref="IIsoparametricInterpolation2D.EvaluateNaturalGradientsAt(NaturalPoint)".
 /// </summary>
 public Matrix EvaluateNaturalGradientsAt(NaturalPoint naturalPoint)
 => EvaluateGradientsAt(naturalPoint.Xi, naturalPoint.Eta);
Example #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);
            }
        }
Example #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));
        }
 /// <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);
 public double GetThicknessAt(NaturalPoint point, EvalInterpolation2D interpolation)
 => IsMaterial1(point, interpolation) ? Thickness1 : Thickness2;