using System; using System.Collections.Generic; using System.Linq; using System.Text; using Annulus; using Azimuth; using Azimuth.DenseLinearAlgebra; using Slipstream.IdealFluid; namespace Slipstream.UnitTests { public class PanelGroupTests : UnitTestSharp.TestFixture { public static SimplePolygon equiTris = new SimplePolygon(new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(0.5, Math.Sqrt(3)/2), }); public static SimplePolygon unitBox = new SimplePolygon(new Vector[] { new Vector(-1, -1), new Vector(-1, 1), new Vector(1, 1), new Vector(1, -1), }); public static SimplePolygon unitCircleBox = new SimplePolygon(new Vector[] { new Vector(-Math.Sqrt(2)/2, -Math.Sqrt(2)/2), new Vector(-Math.Sqrt(2)/2, Math.Sqrt(2)/2), new Vector(Math.Sqrt(2)/2, Math.Sqrt(2)/2), new Vector(Math.Sqrt(2)/2, -Math.Sqrt(2)/2), }); public class ConstructorTests : UnitTestSharp.TestFixture { public void Tris() { var group = new PanelGroup(equiTris, 3); CheckEqual(new Scalar[] { 1, 1, 1, }, group.PanelLengths); CheckEqual(new Scalar[] { 0, 0, 0, }, group.SourceStrengths); var expectedControlPoints = new Vector[] { new Vector(0.5, 0), new Vector(0.75, Math.Sqrt(3) / 4), new Vector(0.25, Math.Sqrt(3) / 4), }; CheckEqual(expectedControlPoints, group.ControlPoints); var direction = new Vector[] { equiTris[1] - equiTris[0], equiTris[2] - equiTris[1], equiTris[0] - equiTris[2], }; AffineMatrix[] expectedTransforms = new AffineMatrix[] { new AffineMatrix(0, expectedControlPoints[0], -1), new AffineMatrix(Math.Atan2(direction[1].Y, direction[1].X), expectedControlPoints[1], -1), new AffineMatrix(Math.Atan2(direction[2].Y, direction[2].X), expectedControlPoints[2], -1), }; CheckEqual(expectedTransforms, group.PanelTransforms); CheckEqual(new Vector(0.5, Math.Sqrt(3) / 4), group.BoundingCircleCenter); CheckEqual(Math.Sqrt(7) / 4, group.BoundingCircleRadius); } } public class EnforceBoundaryConditionsTests : UnitTestSharp.TestFixture { public void Tris_NoVelocity() { var group = new PanelGroup(equiTris, 3); group.EnforceBoundaryConditions(x => Vector.Zero); foreach(var transform in group.PanelTransforms) { var velocity = group.VelocityAtPoint(transform.Translation); var normal = transform.TransformDirection(Vector.UnitY); CheckEqual(0, velocity.DotProduct(normal)); } } public void Tris_UniformVelocity() { var group = new PanelGroup(equiTris, 3); var uniformFluidVelocity = new Vector(100, 0); group.EnforceBoundaryConditions(x => uniformFluidVelocity); foreach (var transform in group.PanelTransforms) { var velocity = group.VelocityAtPoint(transform.Translation) - uniformFluidVelocity; var normal = transform.TransformDirection(Vector.UnitY); CheckEqual(0, velocity.DotProduct(normal)); } } public void PotentialCircle() { const int subdivs = 64; //var group = new PanelGroup(equiTris, 3); var group = new PanelGroup(unitCircleBox, 32); group.EnforceBoundaryConditions(pos => new Vector(100, 0)); var mat = PanelGroup.SourceToTargetCircle(1, subdivs); var transform = new AffineMatrix(0, group.BoundingCircleCenter, 1.0 / group.BoundingCircleRadius); AffineMatrix inverseTransform; transform.Inverse(out inverseTransform); DenseVector potentials; { PanelGroup.SolveForEquivelantSource(subdivs, mat, out potentials, posWS => { var posMS = transform.TransformPoint(posWS); var potential = group.PotentialAtPoint(posMS); return potential; }); } Vector position = new Vector(10, 3); var innerRadius = (Math.Sqrt(2) + 0.1) / Math.Sqrt(2); { var velocity = Vector.Zero; Scalar potential = 0; for (int i = 0; i < subdivs; ++i) { var sourceAngle = 2 * Math.PI * ((Scalar)i) / subdivs; var source = innerRadius * Vector.BuildFromAngleMagnitude(sourceAngle, 1); var sourceWS = inverseTransform.TransformPoint(source); var delta = position - sourceWS; var inverse = delta / delta.LengthSquared(); velocity += inverse * potentials[i]; potential += 0.5 * Math.Log(delta.LengthSquared()) * potentials[i]; } var groupPotential = group.PotentialAtPoint(position); var groupVelocity = group.VelocityAtPoint(position); Check(Vector.Distance(groupVelocity, velocity) < 1e-5); CheckEqual(groupPotential, potential); } } } } }