示例#1
0
        /// <summary>
        /// Creates an n by n + 1 (where n is the length of the provided array
        /// of source panels) matrix representing the linear equations to be
        /// solved for the strengths of the source panels.
        /// </summary>
        /// <param name="sourcePanels">
        /// The array of source panels.
        /// </param>
        /// <param name="vPanels">
        /// A vector representing the velocity vector of the panels (the
        /// negative far-field flow velocity).
        /// </param>
        /// <returns>The equation matrix.</returns>
        public static double[,] CreateEquationMatrix(
            UnitStrengthRectangularSourcePanel[] sourcePanels, Vector3 vPanels)
        {
            int rows    = sourcePanels.Length;
            int columns = rows + 1;

            double[,] equationMatrix = new double[rows, columns];

            for (int i = 0; i < rows; i++)
            {
                Vector3 surfaceNormal =
                    Vector3.Cross(sourcePanels[i].U, sourcePanels[i].V);

                for (int j = 0; j < columns - 1; j++)
                {
                    Vector3 unscaledVelocity = Velocity.ComputeSteadyState(
                        sourcePanels[i].Position, sourcePanels[j]);

                    equationMatrix[i, j] =
                        Vector3.Dot(unscaledVelocity, surfaceNormal);
                }
                equationMatrix[i, columns - 1] =
                    Vector3.Dot(vPanels, surfaceNormal);
            }

            return(equationMatrix);
        }
示例#2
0
        public void ComputeSteadyState_WithDrInTheUVPlane_ReturnsTheCorrectValue()
        {
            // Arrange
            float   aOver2 = 1;
            float   bOver2 = 2;
            Vector3 dr     = new(3, 4, 0);
            Vector3 u      = Vector3.UnitX;
            Vector3 v      = Vector3.UnitY;

            float d11 = (dr - aOver2 * u - bOver2 * v).Length();
            float d12 = (dr - aOver2 * u + bOver2 * v).Length();
            float d21 = (dr + aOver2 * u - bOver2 * v).Length();
            float d22 = (dr + aOver2 * u + bOver2 * v).Length();

            float uDotDr = Vector3.Dot(u, dr);
            float vDotDr = Vector3.Dot(v, dr);

            float ln1 = MathF.Log(MathF.Abs(
                                      (-bOver2 - vDotDr + d11) * (bOver2 - vDotDr + d22) /
                                      ((-bOver2 - vDotDr + d21) * (bOver2 - vDotDr + d12))));
            float ln2 = MathF.Log(MathF.Abs(
                                      (-aOver2 - uDotDr + d11) * (aOver2 - uDotDr + d22) /
                                      ((aOver2 - uDotDr + d21) * (-aOver2 - uDotDr + d12))));

            Vector3 correctResult = 1 / (4 * MathF.PI) * (ln1 * u + ln2 * v);

            // Act
            Vector3 result = Velocity.ComputeSteadyState(aOver2, bOver2, dr, u, v);

            // Assert
            Assert.AreEqual(correctResult, result);
        }
示例#3
0
        public void SolveForSourcePanelStrengths_WithUnitCubeInput_SatisfiesTheTangentialFlowConstraint()
        {
            // Arrange
            UnitStrengthRectangularSourcePanel[] sourcePanels = new UnitStrengthRectangularSourcePanel[6]
            {
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(0.5F, 0, 0), U = Vector3.UnitY, V = Vector3.UnitZ
                },
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(-0.5F, 0, 0), U = Vector3.UnitY, V = Vector3.UnitZ
                },
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(0, 0.5F, 0), U = Vector3.UnitZ, V = Vector3.UnitX
                },
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(0, -0.5F, 0), U = Vector3.UnitZ, V = Vector3.UnitX
                },
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(0, 0, 0.5F), U = Vector3.UnitX, V = Vector3.UnitY
                },
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(0, 0, -0.5F), U = Vector3.UnitX, V = Vector3.UnitY
                }
            };
            Vector3 vPanels = new Vector3(10, 0, 0);

            // Act
            double[] strengths = Solver.SolveForSourcePanelStrengths(sourcePanels, vPanels);

            bool flowIsTangentialAtEachControlPoint = true;

            for (int i = 0; i < sourcePanels.Length; i++)
            {
                Vector3 surfaceNormal = Vector3.Cross(sourcePanels[i].U, sourcePanels[i].V);

                Vector3 velocity = vPanels;
                for (int j = 0; j < sourcePanels.Length; j++)
                {
                    velocity += (float)strengths[j] * Velocity.ComputeSteadyState(sourcePanels[i].Position, sourcePanels[j]);
                }

                if (Vector3.Dot(velocity, surfaceNormal) != 0)
                {
                    flowIsTangentialAtEachControlPoint = false;
                }
            }

            // Assert
            Assert.IsTrue(flowIsTangentialAtEachControlPoint);
        }
示例#4
0
        public void ComputeSteadyState_WithDrEqualToTheZeroVector_ReturnsTheZeroVector()
        {
            // Arrange
            float   aOver2 = 1;
            float   bOver2 = 2;
            Vector3 dr     = Vector3.Zero;
            Vector3 u      = Vector3.UnitX;
            Vector3 v      = Vector3.UnitY;

            // Act
            Vector3 result = Velocity.ComputeSteadyState(aOver2, bOver2, dr, u, v);

            // Assert
            Assert.AreEqual(Vector3.Zero, result);
        }
示例#5
0
        public void ComputeSteadyState_WithDrOutsideTheUVPlane_ReturnsTheCorrectValue()
        {
            // Arrange
            float   aOver2 = 1;
            float   bOver2 = 2;
            Vector3 dr     = new(3, 4, 5);
            Vector3 u      = Vector3.UnitX;
            Vector3 v      = Vector3.UnitY;

            float d11 = (dr - aOver2 * u - bOver2 * v).Length();
            float d12 = (dr - aOver2 * u + bOver2 * v).Length();
            float d21 = (dr + aOver2 * u - bOver2 * v).Length();
            float d22 = (dr + aOver2 * u + bOver2 * v).Length();

            float uDotDr = Vector3.Dot(u, dr);
            float vDotDr = Vector3.Dot(v, dr);

            float ln1 = MathF.Log(MathF.Abs(
                                      (-bOver2 - vDotDr + d11) * (bOver2 - vDotDr + d22) /
                                      ((-bOver2 - vDotDr + d21) * (bOver2 - vDotDr + d12))));
            float ln2 = MathF.Log(MathF.Abs(
                                      (-aOver2 - uDotDr + d11) * (aOver2 - uDotDr + d22) /
                                      ((aOver2 - uDotDr + d21) * (-aOver2 - uDotDr + d12))));

            Vector3 c     = dr - uDotDr * u - vDotDr * v;
            float   sqrtK = c.Length();

            float atan11 = MathF.Atan2(
                (-aOver2 - uDotDr) * (-bOver2 - vDotDr), sqrtK * d11);
            float atan12 = MathF.Atan2(
                (-aOver2 - uDotDr) * (bOver2 - vDotDr), sqrtK * d12);
            float atan21 = MathF.Atan2(
                (aOver2 - uDotDr) * (-bOver2 - vDotDr), sqrtK * d21);
            float atan22 = MathF.Atan2(
                (aOver2 - uDotDr) * (bOver2 - vDotDr), sqrtK * d22);

            float atanSum = atan22 - atan21 - atan12 + atan11;

            Vector3 correctResult = 1 / (4 * MathF.PI) * (ln1 * u + ln2 * v +
                                                          (atanSum / sqrtK) * c);

            // Act
            Vector3 result = Velocity.ComputeSteadyState(aOver2, bOver2, dr, u, v);

            // Assert
            Assert.AreEqual(correctResult, result);
        }
示例#6
0
        public void CreateEquationMatrix_WithUnitCubeInput_CreatesTheCorrectLHS()
        {
            // Arrange
            UnitStrengthRectangularSourcePanel[] sourcePanels = new UnitStrengthRectangularSourcePanel[6]
            {
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(0.5F, 0, 0), U = Vector3.UnitY, V = Vector3.UnitZ
                },
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(-0.5F, 0, 0), U = Vector3.UnitY, V = Vector3.UnitZ
                },
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(0, 0.5F, 0), U = Vector3.UnitZ, V = Vector3.UnitX
                },
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(0, -0.5F, 0), U = Vector3.UnitZ, V = Vector3.UnitX
                },
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(0, 0, 0.5F), U = Vector3.UnitX, V = Vector3.UnitY
                },
                new UnitStrengthRectangularSourcePanel
                {
                    AOver2 = 0.5F, BOver2 = 0.5F, Position = new Vector3(0, 0, -0.5F), U = Vector3.UnitX, V = Vector3.UnitY
                }
            };
            Vector3 vPanels = new Vector3(10, 0, 0);

            double[,] correctLHS = new double[6, 6]
            {
                {
                    Velocity.ComputeSteadyState(sourcePanels[0].Position, sourcePanels[0]).X,
                    Velocity.ComputeSteadyState(sourcePanels[0].Position, sourcePanels[1]).X,
                    Velocity.ComputeSteadyState(sourcePanels[0].Position, sourcePanels[2]).X,
                    Velocity.ComputeSteadyState(sourcePanels[0].Position, sourcePanels[3]).X,
                    Velocity.ComputeSteadyState(sourcePanels[0].Position, sourcePanels[4]).X,
                    Velocity.ComputeSteadyState(sourcePanels[0].Position, sourcePanels[5]).X
                },
                {
                    Velocity.ComputeSteadyState(sourcePanels[1].Position, sourcePanels[0]).X,
                    Velocity.ComputeSteadyState(sourcePanels[1].Position, sourcePanels[1]).X,
                    Velocity.ComputeSteadyState(sourcePanels[1].Position, sourcePanels[2]).X,
                    Velocity.ComputeSteadyState(sourcePanels[1].Position, sourcePanels[3]).X,
                    Velocity.ComputeSteadyState(sourcePanels[1].Position, sourcePanels[4]).X,
                    Velocity.ComputeSteadyState(sourcePanels[1].Position, sourcePanels[5]).X
                },
                {
                    Velocity.ComputeSteadyState(sourcePanels[2].Position, sourcePanels[0]).Y,
                    Velocity.ComputeSteadyState(sourcePanels[2].Position, sourcePanels[1]).Y,
                    Velocity.ComputeSteadyState(sourcePanels[2].Position, sourcePanels[2]).Y,
                    Velocity.ComputeSteadyState(sourcePanels[2].Position, sourcePanels[3]).Y,
                    Velocity.ComputeSteadyState(sourcePanels[2].Position, sourcePanels[4]).Y,
                    Velocity.ComputeSteadyState(sourcePanels[2].Position, sourcePanels[5]).Y
                },
                {
                    Velocity.ComputeSteadyState(sourcePanels[3].Position, sourcePanels[0]).Y,
                    Velocity.ComputeSteadyState(sourcePanels[3].Position, sourcePanels[1]).Y,
                    Velocity.ComputeSteadyState(sourcePanels[3].Position, sourcePanels[2]).Y,
                    Velocity.ComputeSteadyState(sourcePanels[3].Position, sourcePanels[3]).Y,
                    Velocity.ComputeSteadyState(sourcePanels[3].Position, sourcePanels[4]).Y,
                    Velocity.ComputeSteadyState(sourcePanels[3].Position, sourcePanels[5]).Y
                },
                {
                    Velocity.ComputeSteadyState(sourcePanels[4].Position, sourcePanels[0]).Z,
                    Velocity.ComputeSteadyState(sourcePanels[4].Position, sourcePanels[1]).Z,
                    Velocity.ComputeSteadyState(sourcePanels[4].Position, sourcePanels[2]).Z,
                    Velocity.ComputeSteadyState(sourcePanels[4].Position, sourcePanels[3]).Z,
                    Velocity.ComputeSteadyState(sourcePanels[4].Position, sourcePanels[4]).Z,
                    Velocity.ComputeSteadyState(sourcePanels[4].Position, sourcePanels[5]).Z
                },
                {
                    Velocity.ComputeSteadyState(sourcePanels[5].Position, sourcePanels[0]).Z,
                    Velocity.ComputeSteadyState(sourcePanels[5].Position, sourcePanels[1]).Z,
                    Velocity.ComputeSteadyState(sourcePanels[5].Position, sourcePanels[2]).Z,
                    Velocity.ComputeSteadyState(sourcePanels[5].Position, sourcePanels[3]).Z,
                    Velocity.ComputeSteadyState(sourcePanels[5].Position, sourcePanels[4]).Z,
                    Velocity.ComputeSteadyState(sourcePanels[5].Position, sourcePanels[5]).Z
                }
            };

            // Act
            double[,] result = Solver.CreateEquationMatrix(sourcePanels, vPanels);

            bool lhsIsCorrect = true;

            for (int i = 0; i < 6; i++)
            {
                for (int j = 0; j < 6; j++)
                {
                    if (result[i, j] != correctLHS[i, j])
                    {
                        lhsIsCorrect = false;
                    }
                }
            }

            // Assert
            Assert.IsTrue(lhsIsCorrect);
        }
示例#7
0
 public void ComputeSteadyState()
 {
     Vector3 _ = Velocity.ComputeSteadyState(_r, _sourcePanel);
 }