private static IReadOnlyList <NaturalPoint> FindNaturalPointsForTriangulation(XContinuumElement2D element,
                                                                                      IEnumerable <CartesianPoint> cartesianDelaunyPoints)
        {
            IInverseInterpolation2D inverseMapping = element.Interpolation.CreateInverseMappingFor(element.Nodes);
            var naturalDelaunyPoints = new List <NaturalPoint>();

            foreach (var cartesianPoint in cartesianDelaunyPoints)
            {
                naturalDelaunyPoints.Add(inverseMapping.TransformPointCartesianToNatural(cartesianPoint));
            }
            return(naturalDelaunyPoints);
        }
Esempio n. 2
0
        public EmbeddedNode BuildHostElementEmbeddedNode(Element element, Node node, IEmbeddedDOFInHostTransformationVector transformationVector)
        {
            IInverseInterpolation2D inverseInterpolation = Interpolation.CreateInverseMappingFor(Nodes);

            double[] naturalCoordinates = inverseInterpolation.TransformPointCartesianToNatural(new CartesianPoint(node.X, node.Y)).Coordinates;

            if (naturalCoordinates.Length == 0)
            {
                return(null);
            }

            element.EmbeddedNodes.Add(node);
            var embeddedNode = new EmbeddedNode(node, element, transformationVector.GetDependentDOFTypes);

            for (int i = 0; i < naturalCoordinates.Length; i++)
            {
                embeddedNode.Coordinates.Add(naturalCoordinates[i]);
            }
            return(embeddedNode);
        }
        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
            }
        }
Esempio n. 4
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);
            }
        }