public Matrix BuildLumpedMassMatrix()
        {
            int numDofs    = 2 * Nodes.Count;
            var lumpedMass = Matrix.CreateZero(numDofs, numDofs);
            IReadOnlyList <Matrix> shapeGradientsNatural =
                Interpolation.EvaluateNaturalGradientsAtGaussPoints(QuadratureForConsistentMass);

            // Contribution of each Gauss point to the element's area
            //TODO: Perhaps I could calculate the volume of the element without going through each Gauss point. Probably the
            //      nodes are needed instead of the GPs. For linear elements I can find the area geometrically (as polygons).
            //TODO: this should have been cached when integrating other quantities (e.g. stiffness)
            double area = 0;

            for (int gp = 0; gp < QuadratureForConsistentMass.IntegrationPoints.Count; ++gp)
            {
                var jacobian = new IsoparametricJacobian2D(Nodes, shapeGradientsNatural[gp]);
                area += jacobian.DirectDeterminant * QuadratureForConsistentMass.IntegrationPoints[gp].Weight;
            }

            // Divide the total mass uniformly for each node
            double nodalMass = Thickness * area * dynamicProperties.Density / Nodes.Count;

            for (int i = 0; i < numDofs; ++i)
            {
                lumpedMass[i, i] = nodalMass;
            }

            return(lumpedMass);
        }
Esempio n. 2
0
        public Matrix BuildDiffusionConductivityMatrix()
        {
            int numDofs      = Nodes.Count;
            var conductivity = Matrix.CreateZero(numDofs, numDofs);
            IReadOnlyList <Matrix> shapeGradientsNatural =
                Interpolation.EvaluateNaturalGradientsAtGaussPoints(QuadratureForStiffness);

            for (int gp = 0; gp < QuadratureForStiffness.IntegrationPoints.Count; ++gp)
            {
                // Calculate the necessary quantities for the integration
                //Matrix constitutive = (Matrix)(materialsAtGaussPoints[gp].ConstitutiveMatrix); // ugly cast will be removed along with the legacy Matrix classes
                var    jacobian = new IsoparametricJacobian2D(Nodes, shapeGradientsNatural[gp]);
                Matrix shapeGradientsCartesian =
                    jacobian.TransformNaturalDerivativesToCartesian(shapeGradientsNatural[gp]);
                Matrix deformation = BuildDeformationMatrix(shapeGradientsCartesian);

                // Contribution of this gauss point to the element stiffness matrix
                Matrix partialK = deformation.Transpose() * deformation;
                //Matrix partialΚ = deformation.Transpose() * (constitutive * deformation);
                //partialK.Scale(materialsAtGaussPoints[gaussPoint].ThermalConductivity);

                double dA = jacobian.DirectDeterminant * QuadratureForStiffness.IntegrationPoints[gp].Weight; //TODO: this is used by all methods that integrate. I should cache it.
                conductivity.AxpyIntoThis(partialK, dA * material.ThermalConductivity);
            }

            conductivity.ScaleIntoThis(Thickness);
            return(conductivity);
        }
Esempio n. 3
0
        public Matrix BuildStabilizingConductivityMatrix()
        {
            int numDofs    = Nodes.Count;
            var convection = Matrix.CreateZero(numDofs, numDofs);
            IReadOnlyList <double[]> shapeFunctions =
                Interpolation.EvaluateFunctionsAtGaussPoints(QuadratureForConsistentMass);
            IReadOnlyList <Matrix> shapeGradientsNatural =
                Interpolation.EvaluateNaturalGradientsAtGaussPoints(QuadratureForConsistentMass);

            for (int gp = 0; gp < QuadratureForConsistentMass.IntegrationPoints.Count; ++gp)
            {
                Vector shapeFunctionMatrix     = BuildShapeFunctionMatrix(shapeFunctions[gp]);
                var    jacobian                = new IsoparametricJacobian2D(Nodes, shapeGradientsNatural[gp]);
                Matrix shapeGradientsCartesian =
                    jacobian.TransformNaturalDerivativesToCartesian(shapeGradientsNatural[gp]);
                Matrix deformation  = BuildDeformationMatrix(shapeGradientsCartesian);
                Vector deformationX = deformation.GetRow(0);
                Vector deformationY = deformation.GetRow(1);
                //Matrix partial = shapeFunctionMatrix.TensorProduct(shapeFunctionMatrix);
                Matrix partial = deformationX.TensorProduct(deformationY);
                double dA      = jacobian.DirectDeterminant * QuadratureForConsistentMass.IntegrationPoints[gp].Weight;
                convection.AxpyIntoThis(partial, dA);
            }

            //WARNING: the following needs to change for non uniform density. Perhaps the integration order too.
            convection.ScaleIntoThis(-Math.Pow(material.ThermalConvection, 2));
            return(convection);
        }
        public double CalculateArea()
        {
            //TODO: Linear elements can use the more efficient rules for volume of polygons. Therefore this method should be
            //      delegated to the interpolation.
            //TODO: A different integration rule should be used for integrating constant functions. For linear elements there
            //      is only 1 Gauss point (most probably), therefore the computational cost could be the same as using the
            //      polygonal formulas.
            double area = 0.0;
            IReadOnlyList <Matrix> shapeGradientsNatural =
                Interpolation.EvaluateNaturalGradientsAtGaussPoints(QuadratureForStiffness);

            for (int gp = 0; gp < QuadratureForStiffness.IntegrationPoints.Count; ++gp)
            {
                var jacobian = new IsoparametricJacobian2D(Nodes, shapeGradientsNatural[gp]);
                area += jacobian.DirectDeterminant * QuadratureForStiffness.IntegrationPoints[gp].Weight;                 //TODO: this is used by all methods that integrate. I should cache it.
            }
            return(area);
        }
Esempio n. 5
0
        public EvalInterpolation2D(IReadOnlyList <Node> elementNodes, double[] shapeFunctions, Matrix shapeGradientsNatural,
                                   IsoparametricJacobian2D jacobian)
        {
            int numNodes = elementNodes.Count;

#if DEBUG
            if ((shapeFunctions.Length != numNodes) || (shapeGradientsNatural.NumRows != numNodes))
            {
                throw new ArgumentException($"There are {numNodes} nodes, but {ShapeFunctions.Length} shape functions"
                                            + $" and {shapeGradientsNatural.NumRows} natural shape derivatives.");
            }
#endif
            this.elementNodes          = elementNodes;
            this.ShapeFunctions        = shapeFunctions;
            this.ShapeGradientsNatural = shapeGradientsNatural;
            this.Jacobian = jacobian;
            this.ShapeGradientsCartesian = jacobian.TransformNaturalDerivativesToCartesian(shapeGradientsNatural);
        }
Esempio n. 6
0
        public Matrix BuildCapacityMatrix()
        {
            int numDofs  = Nodes.Count;
            var capacity = Matrix.CreateZero(numDofs, numDofs);
            IReadOnlyList <double[]> shapeFunctions =
                Interpolation.EvaluateFunctionsAtGaussPoints(QuadratureForConsistentMass);
            IReadOnlyList <Matrix> shapeGradientsNatural =
                Interpolation.EvaluateNaturalGradientsAtGaussPoints(QuadratureForConsistentMass);

            for (int gp = 0; gp < QuadratureForConsistentMass.IntegrationPoints.Count; ++gp)
            {
                Vector shapeFunctionMatrix = BuildShapeFunctionMatrix(shapeFunctions[gp]);
                Matrix partial             = shapeFunctionMatrix.TensorProduct(shapeFunctionMatrix);
                var    jacobian            = new IsoparametricJacobian2D(Nodes, shapeGradientsNatural[gp]);
                double dA = jacobian.DirectDeterminant * QuadratureForConsistentMass.IntegrationPoints[gp].Weight;
                capacity.AxpyIntoThis(partial, dA);
            }

            //WARNING: the following needs to change for non uniform density. Perhaps the integration order too.
            capacity.ScaleIntoThis(Thickness * material.Density * material.SpecialHeatCoeff);
            return(capacity);
        }
        /// <summary>
        /// Calculate strains (exx, eyy, 2exy) and stresses (sxx, syy, sxy) at integration points, store them in the materials
        /// and return them (e.g. for postprocessing). The order of the tensors is the same as the order of the integration
        /// points defined by <see cref="QuadratureForStiffness"/>.
        /// </summary>
        /// <param name="localDisplacements"></param>
        /// <returns></returns>
        public (IReadOnlyList <double[]> strains, IReadOnlyList <double[]> stresses) UpdateStrainsStressesAtGaussPoints(
            double[] localDisplacements)
        {
            int numGPs   = QuadratureForStiffness.IntegrationPoints.Count;
            var strains  = new double[numGPs][];
            var stresses = new double[numGPs][];
            IReadOnlyList <Matrix> shapeGradientsNatural =
                Interpolation.EvaluateNaturalGradientsAtGaussPoints(QuadratureForStiffness);

            for (int gp = 0; gp < numGPs; ++gp)
            {
                IMatrixView constitutive             = materialsAtGaussPoints[gp].ConstitutiveMatrix;
                var         jacobian                 = new IsoparametricJacobian2D(Nodes, shapeGradientsNatural[gp]);
                Matrix      shapeGrandientsCartesian =
                    jacobian.TransformNaturalDerivativesToCartesian(shapeGradientsNatural[gp]);
                Matrix deformation = BuildDeformationMatrix(shapeGrandientsCartesian);

                strains[gp]  = deformation.Multiply(localDisplacements);
                stresses[gp] = constitutive.Multiply(strains[gp]);
            }

            return(strains, stresses);
        }
        public Matrix BuildConsistentMassMatrix()
        {
            int numDofs = 2 * Nodes.Count;
            var mass    = Matrix.CreateZero(numDofs, numDofs);
            IReadOnlyList <double[]> shapeFunctions =
                Interpolation.EvaluateFunctionsAtGaussPoints(QuadratureForConsistentMass);
            IReadOnlyList <Matrix> shapeGradientsNatural =
                Interpolation.EvaluateNaturalGradientsAtGaussPoints(QuadratureForConsistentMass);

            for (int gp = 0; gp < QuadratureForConsistentMass.IntegrationPoints.Count; ++gp)
            {
                Matrix shapeFunctionMatrix = BuildShapeFunctionMatrix(shapeFunctions[gp]);
                //Matrix partial = shapeFunctionMatrix.Transpose() * shapeFunctionMatrix;
                Matrix partial  = shapeFunctionMatrix.MultiplyRight(shapeFunctionMatrix, true, false);
                var    jacobian = new IsoparametricJacobian2D(Nodes, shapeGradientsNatural[gp]);
                double dA       = jacobian.DirectDeterminant * QuadratureForConsistentMass.IntegrationPoints[gp].Weight;
                mass.AxpyIntoThis(partial, dA);
            }

            //WARNING: the following needs to change for non uniform density. Perhaps the integration order too.
            mass.ScaleIntoThis(Thickness * dynamicProperties.Density);
            return(mass);
        }
        public Matrix BuildStiffnessMatrix()
        {
            int numDofs   = 2 * Nodes.Count;
            var stiffness = Matrix.CreateZero(numDofs, numDofs);
            IReadOnlyList <Matrix> shapeGradientsNatural =
                Interpolation.EvaluateNaturalGradientsAtGaussPoints(QuadratureForStiffness);

            for (int gp = 0; gp < QuadratureForStiffness.IntegrationPoints.Count; ++gp)
            {
                // Calculate the necessary quantities for the integration
                IMatrixView constitutive            = materialsAtGaussPoints[gp].ConstitutiveMatrix;
                var         jacobian                = new IsoparametricJacobian2D(Nodes, shapeGradientsNatural[gp]);
                Matrix      shapeGradientsCartesian =
                    jacobian.TransformNaturalDerivativesToCartesian(shapeGradientsNatural[gp]);
                Matrix deformation = BuildDeformationMatrix(shapeGradientsCartesian);

                // Contribution of this gauss point to the element stiffness matrix
                Matrix partial = deformation.ThisTransposeTimesOtherTimesThis(constitutive);
                double dA      = jacobian.DirectDeterminant * QuadratureForStiffness.IntegrationPoints[gp].Weight;            //TODO: this is used by all methods that integrate. I should cache it.
                stiffness.AxpyIntoThis(partial, dA);
            }
            stiffness.ScaleIntoThis(Thickness);
            return(stiffness);
        }