예제 #1
0
        private static void CalculateNeumannLoad2D(Element element, NeumannBoundaryCondition neumann, Dictionary <int, double> neumannLoad,
                                                   Nurbs2D nurbs, int j, double jacdet, IList <GaussLegendrePoint3D> gaussPoints, double xGaussPoint, double yGaussPoint, double zGaussPoint,
                                                   Vector surfaceBasisVector3)
        {
            var elementControlPoints = element.ControlPoints.ToArray();

            for (int k = 0; k < elementControlPoints.Length; k++)
            {
                int dofIDX =
                    element.Model.GlobalDofOrdering.GlobalFreeDofs[elementControlPoints[k], StructuralDof.TranslationX];
                int dofIDY =
                    element.Model.GlobalDofOrdering.GlobalFreeDofs[elementControlPoints[k], StructuralDof.TranslationY];
                int dofIDZ =
                    element.Model.GlobalDofOrdering.GlobalFreeDofs[elementControlPoints[k], StructuralDof.TranslationZ];

                if (neumannLoad.ContainsKey(dofIDX))
                {
                    neumannLoad[dofIDX] += nurbs.NurbsValues[k, j] * jacdet * gaussPoints[j].WeightFactor *
                                           neumann.Value(xGaussPoint, yGaussPoint, zGaussPoint)[0] *
                                           surfaceBasisVector3[0];
                }
                else
                {
                    neumannLoad.Add(
                        dofIDX,
                        nurbs.NurbsValues[k, j] * jacdet * gaussPoints[j].WeightFactor *
                        neumann.Value(xGaussPoint, yGaussPoint, zGaussPoint)[0] * surfaceBasisVector3[0]);
                }

                if (neumannLoad.ContainsKey(dofIDY))
                {
                    neumannLoad[dofIDY] += nurbs.NurbsValues[k, j] * jacdet * gaussPoints[j].WeightFactor *
                                           neumann.Value(xGaussPoint, yGaussPoint, zGaussPoint)[1] *
                                           surfaceBasisVector3[1];
                }
                else
                {
                    neumannLoad.Add(
                        dofIDY,
                        nurbs.NurbsValues[k, j] * jacdet * gaussPoints[j].WeightFactor * neumann.Value(xGaussPoint, yGaussPoint, zGaussPoint)[1] * surfaceBasisVector3[1]);
                }

                if (neumannLoad.ContainsKey(dofIDZ))
                {
                    neumannLoad[dofIDZ] += nurbs.NurbsValues[k, j] * jacdet * gaussPoints[j].WeightFactor * neumann.Value(xGaussPoint, yGaussPoint, zGaussPoint)[2] * surfaceBasisVector3[2];
                }
                else
                {
                    neumannLoad.Add(dofIDZ,
                                    nurbs.NurbsValues[k, j] * jacdet * gaussPoints[j].WeightFactor * neumann.Value(xGaussPoint, yGaussPoint, zGaussPoint)[2] * surfaceBasisVector3[2]);
                }
            }
        }
예제 #2
0
파일: Edge.cs 프로젝트: dimtsap/MSolve.IGA
 private void CalculateNeumann(LoadProvider provider, NeumannBoundaryCondition condition, Dictionary <int, double> load)
 {
     foreach (var element in ElementsDictionary.Values)
     {
         var loadNeumann = provider.LoadNeumann(element, this, condition);
         foreach (int dof in loadNeumann.Keys)
         {
             if (load.ContainsKey(dof))
             {
                 load[dof] += loadNeumann[dof];
             }
             else
             {
                 load.Add(dof, loadNeumann[dof]);
             }
         }
     }
 }
예제 #3
0
 /// <summary>
 /// This method cannot be used, combined with <see cref="NurbsElement3D"/> as it refers to two-dimensional loads.
 /// </summary>
 /// <param name="element">An <see cref="Element"/> of type <see cref="NurbsElement3D"/>.</param>
 /// <param name="face">The <see cref="Face"/> that the <see cref="NeumannBoundaryCondition"/> was applied to.</param>
 /// <param name="neumann">The <see cref="NeumannBoundaryCondition"/>.</param>
 /// <returns>A <see cref="Dictionary{TKey,TValue}"/> whose keys are the numbering of the degree of freedom and values are the magnitude of the load due to the <see cref="NeumannBoundaryCondition"/>.</returns>
 public Dictionary <int, double> CalculateLoadingCondition(Element element, Face face, NeumannBoundaryCondition neumann) => throw new NotSupportedException();
 /// <summary>
 /// This method cannot be used, combined with <see cref="TSplineKirchhoffLoveShellElementMaterial"/> as it refers to one-dimensional loads.
 /// </summary>
 /// <param name="element">An element of type <see cref="TSplineKirchhoffLoveShellElementMaterial"/>.</param>
 /// <param name="edge">An one dimensional boundary entity. For more info see <see cref="Edge"/>.</param>
 /// <param name="neumann"><inheritdoc cref="NeumannBoundaryCondition"/></param>
 /// <returns>A <see cref="Dictionary{TKey,TValue}"/> where integer values denote the degree of freedom that has a value double load value due to the enforcement of the <see cref="NeumannBoundaryCondition"/>.</returns>
 public Dictionary <int, double> CalculateLoadingCondition(Element element, Edge edge, NeumannBoundaryCondition neumann) => throw new NotImplementedException();
예제 #5
0
        /// <summary>
        /// This method calculates the Neumann boundary condition when applied to a two-dimensional NURBS element.
        /// </summary>
        /// <param name="element">An element of type <see cref="NurbsElement2D"/></param>
        /// <param name="face">An two dimensional boundary entity. For more info see <see cref="Face"/>.</param>
        /// <param name="neumann"><inheritdoc cref="NeumannBoundaryCondition"/>.</param>
        /// <returns>A <see cref="Dictionary{TKey,TValue}"/> where integer values denote the degree of freedom that has a value double load value due to the enforcement of the <see cref="NeumannBoundaryCondition"/>.</returns>
        public Dictionary <int, double> CalculateLoadingCondition(Element element, Face face, NeumannBoundaryCondition neumann)
        {
            Contract.Requires(element != null, "The element cannot be null");
            Contract.Requires(face != null, "The face cannot be null");
            Contract.Requires(neumann != null, "The Neumann Boundary condition cannot be null");

            IList <GaussLegendrePoint3D> gaussPoints =
                CreateElementGaussPoints(element, face.Degrees[0], face.Degrees[1]);
            Dictionary <int, double> neumannLoad = new Dictionary <int, double>();
            var     elementControlPoints         = element.ControlPoints.ToArray();
            Nurbs2D nurbs = new Nurbs2D(element, elementControlPoints, face);

            for (int j = 0; j < gaussPoints.Count; j++)
            {
                var jacobianMatrix = JacobianMatrixForLoadCalculation(element, nurbs, j, out var xGaussPoint, out var yGaussPoint, out var zGaussPoint);

                Vector surfaceBasisVector1 = Vector.CreateZero(3);
                surfaceBasisVector1[0] = jacobianMatrix[0, 0];
                surfaceBasisVector1[1] = jacobianMatrix[0, 1];
                surfaceBasisVector1[2] = jacobianMatrix[0, 2];

                Vector surfaceBasisVector2 = Vector.CreateZero(3);
                surfaceBasisVector2[0] = jacobianMatrix[1, 0];
                surfaceBasisVector2[1] = jacobianMatrix[1, 1];
                surfaceBasisVector2[2] = jacobianMatrix[1, 2];

                Vector surfaceBasisVector3 = surfaceBasisVector1.CrossProduct(surfaceBasisVector2);

                double jacdet = jacobianMatrix[0, 0] * jacobianMatrix[1, 1]
                                - jacobianMatrix[1, 0] * jacobianMatrix[0, 1];

                CalculateNeumannLoad2D(element, neumann, neumannLoad, nurbs, j, jacdet, gaussPoints, xGaussPoint, yGaussPoint, zGaussPoint, surfaceBasisVector3);
            }

            return(neumannLoad);
        }
예제 #6
0
        private static void CalculatePressure1D(
            Element element,
            Edge edge,
            NeumannBoundaryCondition neumann,
            IList <ControlPoint> controlPoints,
            IList <GaussLegendrePoint3D> gaussPoints,
            IDictionary <int, double> neumannLoad)
        {
            var nurbs = new Nurbs1D(element, controlPoints, edge);

            for (int j = 0; j < gaussPoints.Count; j++)
            {
                double xGaussPoint          = 0;
                double yGaussPoint          = 0;
                double zGaussPoint          = 0;
                double jacobian1            = 0.0;
                double jacobian2            = 0.0;
                var    elementControlPoints = element.ControlPointsDictionary.Values.ToArray();
                for (int k = 0; k < elementControlPoints.Length; k++)
                {
                    xGaussPoint += nurbs.NurbsValues[k, j] * elementControlPoints[k].X;
                    yGaussPoint += nurbs.NurbsValues[k, j] * elementControlPoints[k].Y;
                    zGaussPoint += nurbs.NurbsValues[k, j] * elementControlPoints[k].Z;
                    jacobian1   += nurbs.NurbsDerivativeValuesKsi[k, j] * elementControlPoints[k].X;
                    jacobian2   += nurbs.NurbsDerivativeValuesKsi[k, j] * elementControlPoints[k].Y;
                }

                double jacdet         = Math.Sqrt(Math.Pow(jacobian1, 2) + Math.Pow(jacobian2, 2));
                var    loadGaussPoint = neumann.Value(xGaussPoint, yGaussPoint, zGaussPoint);

                for (int k = 0; k < element.ControlPointsDictionary.Count; k++)
                {
                    if (element.Model.GlobalDofOrdering.GlobalFreeDofs.Contains(elementControlPoints[k],
                                                                                StructuralDof.TranslationX))
                    {
                        int dofIDX =
                            element.Model.GlobalDofOrdering.GlobalFreeDofs[elementControlPoints[k],
                                                                           StructuralDof.TranslationX];
                        if (neumannLoad.ContainsKey(dofIDX))
                        {
                            neumannLoad[dofIDX] += jacdet * gaussPoints[j].WeightFactor * nurbs.NurbsValues[k, j] *
                                                   loadGaussPoint[0];
                        }
                        else
                        {
                            neumannLoad.Add(
                                dofIDX,
                                jacdet * gaussPoints[j].WeightFactor * nurbs.NurbsValues[k, j] * loadGaussPoint[0]);
                        }
                    }

                    if (!element.Model.GlobalDofOrdering.GlobalFreeDofs.Contains(
                            elementControlPoints[k],
                            StructuralDof.TranslationY))
                    {
                        continue;
                    }

                    var dofIDY =
                        element.Model.GlobalDofOrdering.GlobalFreeDofs[
                            elementControlPoints[k],
                            StructuralDof.TranslationY];
                    if (neumannLoad.ContainsKey(dofIDY))
                    {
                        neumannLoad[dofIDY] += jacdet * gaussPoints[j].WeightFactor * nurbs.NurbsValues[k, j] *
                                               loadGaussPoint[1];
                    }
                    else
                    {
                        neumannLoad.Add(dofIDY,
                                        jacdet * gaussPoints[j].WeightFactor * nurbs.NurbsValues[k, j] * loadGaussPoint[1]);
                    }
                }
            }
        }
예제 #7
0
        /// <summary>
        /// This method calculates the Neumann boundary condition when applied to a one dimensional NURBS element.
        /// </summary>
        /// <param name="element">An element of type <see cref="NurbsElement1D"/>.</param>
        /// <param name="edge">An one dimensional boundary entity. For more info see <see cref="Edge"/>.</param>
        /// <param name="neumann"><inheritdoc cref="NeumannBoundaryCondition"/></param>
        /// <returns>A <see cref="Dictionary{TKey,TValue}"/> where integer values denote the degree of freedom that has a value double load value due to the enforcement of the <see cref="NeumannBoundaryCondition"/>.</returns>
        public Dictionary <int, double> CalculateLoadingCondition(Element element, Edge edge, NeumannBoundaryCondition neumann)
        {
            IList <GaussLegendrePoint3D> gaussPoints   = CreateElementGaussPoints(element);
            Dictionary <int, double>     neumannLoad   = new Dictionary <int, double>();
            IList <ControlPoint>         controlPoints = new List <ControlPoint>();

            CalculateEdgeControlPoints(element, edge, controlPoints);

            CalculatePressure1D(element, edge, neumann, controlPoints, gaussPoints, neumannLoad);
            return(neumannLoad);
        }
        /// <summary>
        /// Solve the PDE backwards from the end.
        /// Each step t, solve Ax=b, where A is constructed from pu, pm, and pd, and b is calculated from t+dt
        /// </summary>
        public double[][] Solve(double[] t, double[] xGrid, double[] x, Func <double, double> payOff)
        {
            var value = new double[t.Length][];

            for (var i = 0; i < t.Length; ++i)
            {
                value[i] = new double[x.Length];
            }

            for (var j = 0; j < x.Length; ++j)
            {
                value[t.Length - 1][j] = payOff(x[j]);
            }

            var boundaryConditions = new NeumannBoundaryCondition[2];

            boundaryConditions[0] = new NeumannBoundaryCondition(Boundary.Upper,
                                                                 payOff(x[x.Length - 1]) - payOff(x[x.Length - 2]));
            boundaryConditions[1] = new NeumannBoundaryCondition(Boundary.Lower,
                                                                 payOff(x[1]) - payOff(x[0]));

            var dt   = t[1] - t[0];
            var dx   = xGrid[1] - xGrid[0];
            var nu   = _alpha(0.0, 0.0, dt);
            var beta = _beta(0.0, 0.0);
            var rf   = _r(0.0);
            var pu   = -nu * dt / (4 * dx) - beta * dt / (2 * dx * dx);
            var pd   = nu * dt / (4 * dx) - beta * dt / (2 * dx * dx);
            var pm   = 1 + rf * dt / 2 + beta * dt / (dx * dx);

            var steps      = t.Length;
            var gridPoints = xGrid.Length;

            var diagonal      = new List <double>();
            var upperDiagonal = new List <double>();
            var lowerDiagonal = new List <double>();

            diagonal.Add(1);
            upperDiagonal.Add(-1);
            lowerDiagonal.Add(0);

            for (var i = 1; i < gridPoints - 1; ++i)
            {
                lowerDiagonal.Add(pd);
                diagonal.Add(pm);
                upperDiagonal.Add(pu);
            }

            diagonal.Add(-1);
            lowerDiagonal.Add(1);
            upperDiagonal.Add(0);

            var aTridiagonal = new TridiagonalMatrix(gridPoints, diagonal.ToArray(), upperDiagonal.ToArray(), lowerDiagonal.ToArray());
            var b            = new double[gridPoints];

            for (var i = steps - 2; i >= 0; --i)
            {
                for (var j = 1; j < gridPoints - 1; ++j)
                {
                    b[j] = -pu * value[i + 1][j + 1] - pd * value[i + 1][j - 1] - (pm - 2) * value[i + 1][j];
                }
                Array.ForEach(boundaryConditions, boundary =>
                {
                    b = boundary.Apply(b);
                });

                var solution = aTridiagonal.SolveFor(b);
                for (var k = 0; k < solution.Length; ++k)
                {
                    value[i][k] = Math.Max(solution[k], payOff(x[k]));
                }
            }

            return(value);
        }