Example #1
0
        /// <summary>
        /// Sets the boundary cells at the outer edges of the cube so they perfectly counteract their neighbor
        /// </summary>
        /// <remarks>
        /// This is a way to keep fluid from leaking out of the box.  (not having walls really screws up the simulation code).
        /// Walls are added by treating the outer layer of cells as the wall.  Basically, every velocity in the layer next to this
        /// outer layer is mirrored.  So when you have some velocity towards the wall in the next-to-outer layer, the wall
        /// gets a velocity that perfectly counters it.
        /// 
        /// 
        /// Say we're at the left edge of the cube. The left cell is the boundary cell that needs to counteract its neighbor, the
        /// right cell. The right cell has a velocity that's up and to the left.
        /// 
        /// The boundary cell's x velocity needs to be opposite its neighbor, but its y velocity needs to be equal to its neighbor.
        /// This will produce a result that counteracts the motion of the fluid which would take it through the wall, and preserves
        /// the rest of the motion.
        /// 
        /// So what action is taken depends on which array is passed in; if we're dealing with x velocities, then we have to set
        /// the boundary cell's value to the opposite of its neighbor, but for everything else we set it to be the same.
        ///
        /// 
        /// This function also sets corners. This is done very simply, by setting each corner cell equal to the average of its three
        /// neighbors.
        /// </remarks>
        private static void SetBoundry_ORIG(SetBoundsType whichSide, double[] array, int size, BoundrySettings boundrySettings)
        {
            const double ONETHIRD = 1d / 3d;

            // Reflect the walls
            //NOTE: These arrays go from 1 to length-1.  The corners are handled later

            // X wall
            for (int z = 1; z < size - 1; z++)
            {
                for (int y = 1; y < size - 1; y++)
                {
                    array[IX(0, y, z, size)] = whichSide == SetBoundsType.VelocityX ? -array[IX(1, y, z, size)] : array[IX(1, y, z, size)];
                    array[IX(size - 1, y, z, size)] = whichSide == SetBoundsType.VelocityX ? -array[IX(size - 2, y, z, size)] : array[IX(size - 2, y, z, size)];
                }
            }

            // Y wall
            for (int z = 1; z < size - 1; z++)
            {
                for (int x = 1; x < size - 1; x++)
                {
                    array[IX(x, 0, z, size)] = whichSide == SetBoundsType.VelocityY ? -array[IX(x, 1, z, size)] : array[IX(x, 1, z, size)];
                    array[IX(x, size - 1, z, size)] = whichSide == SetBoundsType.VelocityY ? -array[IX(x, size - 2, z, size)] : array[IX(x, size - 2, z, size)];
                }
            }

            // Z wall
            for (int y = 1; y < size - 1; y++)
            {
                for (int x = 1; x < size - 1; x++)
                {
                    array[IX(x, y, 0, size)] = whichSide == SetBoundsType.VelocityZ ? -array[IX(x, y, 1, size)] : array[IX(x, y, 1, size)];
                    array[IX(x, y, size - 1, size)] = whichSide == SetBoundsType.VelocityZ ? -array[IX(x, y, size - 2, size)] : array[IX(x, y, size - 2, size)];
                }
            }


            // Corners take average of neighbors
            array[IX(0, 0, 0, size)] = ONETHIRD *
                                            (array[IX(1, 0, 0, size)]
                                          + array[IX(0, 1, 0, size)]
                                          + array[IX(0, 0, 1, size)]);

            array[IX(0, size - 1, 0, size)] = ONETHIRD *
                                            (array[IX(1, size - 1, 0, size)]
                                          + array[IX(0, size - 2, 0, size)]
                                          + array[IX(0, size - 1, 1, size)]);

            array[IX(0, 0, size - 1, size)] = ONETHIRD *
                                            (array[IX(1, 0, size - 1, size)]
                                          + array[IX(0, 1, size - 1, size)]
                                          + array[IX(0, 0, size - 2, size)]);

            array[IX(0, size - 1, size - 1, size)] = ONETHIRD *
                                            (array[IX(1, size - 1, size - 1, size)]
                                          + array[IX(0, size - 2, size - 1, size)]
                                          + array[IX(0, size - 1, size - 2, size)]);

            array[IX(size - 1, 0, 0, size)] = ONETHIRD *
                                            (array[IX(size - 2, 0, 0, size)]
                                          + array[IX(size - 1, 1, 0, size)]
                                          + array[IX(size - 1, 0, 1, size)]);

            array[IX(size - 1, size - 1, 0, size)] = ONETHIRD *
                                            (array[IX(size - 2, size - 1, 0, size)]
                                          + array[IX(size - 1, size - 2, 0, size)]
                                          + array[IX(size - 1, size - 1, 1, size)]);

            array[IX(size - 1, 0, size - 1, size)] = ONETHIRD *
                                            (array[IX(size - 2, 0, size - 1, size)]
                                          + array[IX(size - 1, 1, size - 1, size)]
                                          + array[IX(size - 1, 0, size - 2, size)]);

            array[IX(size - 1, size - 1, size - 1, size)] = ONETHIRD *
                                            (array[IX(size - 2, size - 1, size - 1, size)]
                                          + array[IX(size - 1, size - 2, size - 1, size)]
                                          + array[IX(size - 1, size - 1, size - 2, size)]);
        }
Example #2
0
        /// <remarks>
        /// Every cell has a set of velocities, and these velocities make things move. This is called advection.  As with diffusion, advection
        /// applies both to the dye and to the velocities themselves.
        /// 
        /// This function is responsible for actually moving things around.  To that end, it looks at each cell in turn.  In that cell, it grabs the
        /// velocity, follows that velocity back in time, and sees where it lands.  It then takes a weighted average of the cells around the spot
        /// where it lands, then applies that value to the current cell.
        /// </remarks>
        private static void Advect(SetBoundsType whichSide, double[] dest, double[] source, double[] velocX, double[] velocY, double[] velocZ, bool[] blocked, double timestep, int size, BoundrySettings boundrySettings)
        {
            for (int z = 1; z < size - 1; z++)
            {
                for (int y = 1; y < size - 1; y++)
                {
                    for (int x = 1; x < size - 1; x++)
                    {
                        int index1D = IX(x, y, z, size);

                        if (blocked[index1D])
                        {
                            continue;
                        }

                        // Reverse velocity, since we are interpolating backwards 
                        // xSrc and ySrc is the position of the source density.
                        double xSrc = x - (timestep * velocX[index1D]);
                        double ySrc = y - (timestep * velocY[index1D]);
                        double zSrc = z - (timestep * velocZ[index1D]);

                        if (xSrc < 0.5d) xSrc = 0.5d;
                        if (xSrc > size - 1.5d) xSrc = size - 1.5d;
                        int x0 = (int)xSrc;     // casting to int is also the equivalent of Math.Floor
                        int x1 = x0 + 1;

                        if (ySrc < 0.5d) ySrc = 0.5d;
                        if (ySrc > size - 1.5d) ySrc = size - 1.5d;
                        int y0 = (int)ySrc;
                        int y1 = y0 + 1;

                        if (zSrc < 0.5d) zSrc = 0.5d;
                        if (zSrc > size - 1.5d) zSrc = size - 1.5d;
                        int z0 = (int)zSrc;
                        int z1 = z0 + 1;

                        //Linear interpolation factors. Ex: 0.6 and 0.4
                        double xProp1 = xSrc - x0;
                        double xProp0 = 1d - xProp1;
                        double yProp1 = ySrc - y0;
                        double yProp0 = 1d - yProp1;
                        double zProp1 = zSrc - z0;
                        double zProp0 = 1d - zProp1;

                        // ugly no matter how you nest it
                        dest[index1D] =
                            xProp0 *
                                (yProp0 *
                                    (zProp0 * source[IX(x0, y0, z0, size)] +
                                    zProp1 * source[IX(x0, y0, z1, size)]) +
                                (yProp1 *
                                    (zProp0 * source[IX(x0, y1, z0, size)] +
                                    zProp1 * source[IX(x0, y1, z1, size)]))) +
                            xProp1 *
                                (yProp0 *
                                    (zProp0 * source[IX(x1, y0, z0, size)] +
                                    zProp1 * source[IX(x1, y0, z1, size)]) +
                                (yProp1 *
                                    (zProp0 * source[IX(x1, y1, z0, size)] +
                                    zProp1 * source[IX(x1, y1, z1, size)])));
                    }
                }
            }

            SetBoundry(whichSide, dest, blocked, size, boundrySettings);
        }
Example #3
0
        /// <summary>
        /// Not exactly sure how this method works, it's solving a linear differential equation of some sort
        /// </summary>
        /// <remarks>
        ///  This runs through the whole array and sets each cell to a combination of its neighbors.  It does this several times; the more
        ///  iterations it does, the more accurate the results, but the slower things run.  (4 iterations is a good number to use).
        ///  
        /// After each iteration, it resets the boundaries so the calculations don't explode.
        /// </remarks>
        private static void LinearSolve(SetBoundsType whichSide, double[] dest, double[] source, bool[] blocked, double a, double c, int iterations, int size, BoundrySettings boundrySettings)
        {
            double cRecip = 1d / c;

            int index;

            for (int cntr = 0; cntr < iterations; cntr++)
            {
                for (int z = 1; z < size - 1; z++)
                {
                    for (int y = 1; y < size - 1; y++)
                    {
                        for (int x = 1; x < size - 1; x++)
                        {
                            index = IX(x, y, z, size);

                            if (blocked[index])
                            {
                                continue;
                            }

                            dest[index] =
                                    (source[IX(x, y, z, size)]
                                        + a * (dest[IX(x + 1, y, z, size)]
                                                + dest[IX(x - 1, y, z, size)]
                                                + dest[IX(x, y + 1, z, size)]
                                                + dest[IX(x, y - 1, z, size)]
                                                + dest[IX(x, y, z + 1, size)]
                                                + dest[IX(x, y, z - 1, size)]
                                       )) * cRecip;
                        }
                    }
                }

                SetBoundry(whichSide, dest, blocked, size, boundrySettings);
            }
        }
Example #4
0
        /// <summary>
        /// Allows the fluid to spread out (blurs the fluid)
        /// </summary>
        /// <remarks>
        /// Put a drop of soy sauce in some water, and you'll notice that it doesn't stay still, but it spreads out.  This
        /// happens even if the water and sauce are both perfectly still.  This is called diffusion. We use diffusion both
        /// in the obvious case of making the dye spread out, and also in the less obvious case of making the velocities
        /// of the fluid spread out.
        /// 
        /// Diffuse is really simple; it just precalculates a value and passes everything off to lin_solve.  So that means,
        /// while I know what it does, I don't really know how, since all the work is in that mysterious function
        /// </remarks>
        private static void Diffuse(SetBoundsType whichSide, double[] destination, double[] source, bool[] blocked, double timestep, double diffusion, int iterations, int size, BoundrySettings boundrySettings)
        {
            double a = timestep * diffusion;

            //NOTE: The 2D uses 4.  If 4 is used here, the color just spreads out, so maybe it's 2xDimensions?
            LinearSolve(whichSide, destination, source, blocked, a, 1 + 6 * a, iterations, size, boundrySettings);
        }
Example #5
0
        /// <summary>
        /// Forces the velocity to be mass conserving
        /// </summary>
        /// <remarks>
        /// The fluid that this class models is incompressible  This means that the amount of fluid in each box has to stay constant.
        /// That means that the amount of fluid going in has to be exactly equal to the amount of fluid going out.  The other
        /// operations tend to screw things up so that you get some boxes with a net outflow, and some with a net inflow.  This
        /// operation runs through all the cells and fixes them up so everything is in equilibrium.
        /// 
        /// This function is also somewhat mysterious as to exactly how it works, but it does some more running through the data
        /// and setting values, with some calls to lin_solve thrown in for fun
        /// 
        /// --------------
        /// 
        /// Every velocity field is the sum of an incompressible field and a gradient field.  To obtain an incompressible field we
        /// simply subtract the gradient field from our current velocities.
        /// 
        /// The gradient field indicates the direction of steepest descent of some height function. Imagine a terrain with hills and
        /// valleys with an arrow at every point pointing in the direction of steepest descent
        /// </remarks>
        private static void Project(double[] velocX, double[] velocY, double[] velocZ, double[] p, double[] div, bool[] blocked, int iterations, int size, BoundrySettings boundrySettings)
        {
            int index;

            for (int z = 1; z < size - 1; z++)
            {
                for (int y = 1; y < size - 1; y++)
                {
                    for (int x = 1; x < size - 1; x++)
                    {
                        index = IX(x, y, z, size);

                        if (blocked[index])
                        {
                            continue;
                        }

                        //Negative divergence
                        div[index] = -0.5d * (
                                 velocX[IX(x + 1, y, z, size)]
                                - velocX[IX(x - 1, y, z, size)]
                                + velocY[IX(x, y + 1, z, size)]
                                - velocY[IX(x, y - 1, z, size)]
                                + velocZ[IX(x, y, z + 1, size)]
                                - velocZ[IX(x, y, z - 1, size)]
                            ) / size;

                        //Pressure field
                        p[index] = 0;
                    }
                }
            }
            SetBoundry(SetBoundsType.Other, div, blocked, size, boundrySettings);
            SetBoundry(SetBoundsType.Other, p, blocked, size, boundrySettings);
            LinearSolve(SetBoundsType.Other, p, div, blocked, 1, 6, iterations, size, boundrySettings);

            for (int z = 1; z < size - 1; z++)
            {
                for (int y = 1; y < size - 1; y++)
                {
                    for (int x = 1; x < size - 1; x++)
                    {
                        index = IX(x, y, z, size);

                        if (blocked[index])
                        {
                            continue;
                        }

                        velocX[index] -= 0.5d * (p[IX(x + 1, y, z, size)]
                                                        - p[IX(x - 1, y, z, size)]) * size;
                        velocY[index] -= 0.5d * (p[IX(x, y + 1, z, size)]
                                                        - p[IX(x, y - 1, z, size)]) * size;
                        velocZ[index] -= 0.5d * (p[IX(x, y, z + 1, size)]
                                                        - p[IX(x, y, z - 1, size)]) * size;
                    }
                }
            }
            SetBoundry(SetBoundsType.VelocityX, velocX, blocked, size, boundrySettings);
            SetBoundry(SetBoundsType.VelocityY, velocY, blocked, size, boundrySettings);
            SetBoundry(SetBoundsType.VelocityZ, velocZ, blocked, size, boundrySettings);
        }
Example #6
0
        private static void SetBoundry_ReachAround(SetBoundsType whichSide, double[] cells, int size, BoundrySettings boundrySettings)
        {
            double average, sum, count;

            bool wrapX = whichSide == SetBoundsType.VelocityX || whichSide == SetBoundsType.Ink;
            bool wrapY = whichSide == SetBoundsType.VelocityY || whichSide == SetBoundsType.Ink;
            bool wrapZ = whichSide == SetBoundsType.VelocityZ || whichSide == SetBoundsType.Ink;

            #region X wall

            if (wrapX)
            {
                // Copy of other side
                for (int z = 1; z < size - 1; z++)
                {
                    for (int y = 1; y < size - 1; y++)
                    {
                        cells[IX(0, y, z, size)] = cells[IX(size - 2, y, z, size)];
                        cells[IX(size - 1, y, z, size)] = cells[IX(1, y, z, size)];
                    }
                }
            }
            else
            {
                // Average
                for (int z = 1; z < size - 1; z++)
                {
                    for (int y = 1; y < size - 1; y++)
                    {
                        average = .5d * (cells[IX(1, y, z, size)] + cells[IX(size - 2, y, z, size)]);

                        cells[IX(0, y, z, size)] = average;
                        cells[IX(size - 1, y, z, size)] = average;
                    }
                }
            }

            #endregion
            #region Y wall

            if (wrapY)
            {
                // Copy of other side
                for (int z = 1; z < size - 1; z++)
                {
                    for (int x = 1; x < size - 1; x++)
                    {
                        cells[IX(x, 0, z, size)] = cells[IX(x, size - 2, z, size)];
                        cells[IX(x, size - 1, z, size)] = cells[IX(x, 1, z, size)];
                    }
                }
            }
            else
            {
                // Average
                for (int z = 1; z < size - 1; z++)
                {
                    for (int x = 1; x < size - 1; x++)
                    {
                        average = .5d * (cells[IX(x, 1, z, size)] + cells[IX(x, size - 2, z, size)]);

                        cells[IX(x, 0, z, size)] = average;
                        cells[IX(x, size - 1, z, size)] = average;
                    }
                }
            }

            #endregion
            #region Z wall

            if (wrapZ)
            {
                // Copy of other side
                for (int y = 1; y < size - 1; y++)
                {
                    for (int x = 1; x < size - 1; x++)
                    {
                        cells[IX(x, y, 0, size)] = cells[IX(x, y, size - 2, size)];
                        cells[IX(x, y, size - 1, size)] = cells[IX(x, y, 1, size)];
                    }
                }
            }
            else
            {
                // Average
                for (int y = 1; y < size - 1; y++)
                {
                    for (int x = 1; x < size - 1; x++)
                    {
                        average = .5d * (cells[IX(x, y, 1, size)] + cells[IX(x, y, size - 2, size)]);

                        cells[IX(x, y, 0, size)] = average;
                        cells[IX(x, y, size - 1, size)] = average;
                    }
                }
            }

            #endregion

            #region X edges

            for (int x = 1; x < size - 1; x++)
            {
                // 1
                sum = 0; count = 0;

                sum += cells[IX(x, size - 2, 0, size)]; count++;
                if (!wrapY)
                {
                    sum += cells[IX(x, 1, 0, size)]; count++;
                }

                sum += cells[IX(x, 0, size - 2, size)]; count++;
                if (!wrapZ)
                {
                    sum += cells[IX(x, 0, 1, size)]; count++;
                }

                cells[IX(x, 0, 0, size)] = sum / count;

                // 2
                sum = 0; count = 0;

                sum += cells[IX(x, 1, 0, size)]; count++;
                if (!wrapY)
                {
                    sum += cells[IX(x, size - 2, 0, size)]; count++;
                }

                sum += cells[IX(x, size - 1, size - 2, size)]; count++;
                if (!wrapZ)
                {
                    sum += cells[IX(x, size - 1, 1, size)]; count++;
                }

                cells[IX(x, size - 1, 0, size)] = sum / count;

                // 3
                sum = 0; count = 0;

                sum += cells[IX(x, size - 2, size - 1, size)]; count++;
                if (!wrapY)
                {
                    sum += cells[IX(x, 1, size - 1, size)]; count++;
                }

                sum += cells[IX(x, 0, 1, size)]; count++;
                if (!wrapZ)
                {
                    sum += cells[IX(x, 0, size - 2, size)]; count++;
                }

                cells[IX(x, 0, size - 1, size)] = sum / count;

                // 4
                sum = 0; count = 0;

                sum += cells[IX(x, 1, size - 1, size)]; count++;
                if (!wrapY)
                {
                    sum += cells[IX(x, size - 2, size - 1, size)]; count++;
                }

                sum += cells[IX(x, size - 1, 1, size)]; count++;
                if (!wrapZ)
                {
                    sum += cells[IX(x, size - 1, size - 2, size)]; count++;
                }

                cells[IX(x, size - 1, size - 1, size)] = sum / count;
            }

            #endregion
            #region Y edges

            for (int y = 1; y < size - 1; y++)
            {
                // 1
                sum = 0; count = 0;

                sum += cells[IX(size - 2, y, 0, size)]; count++;
                if (!wrapX)
                {
                    sum += cells[IX(1, y, 0, size)]; count++;
                }

                sum += cells[IX(0, y, size - 2, size)]; count++;
                if (!wrapZ)
                {
                    sum += cells[IX(0, y, 1, size)]; count++;
                }

                cells[IX(0, y, 0, size)] = sum / count;

                // 2
                sum = 0; count = 0;

                sum += cells[IX(1, y, 0, size)]; count++;
                if (!wrapX)
                {
                    sum += cells[IX(size - 2, y, 0, size)]; count++;
                }

                sum += cells[IX(size - 1, y, size - 2, size)]; count++;
                if (!wrapZ)
                {
                    sum += cells[IX(size - 1, y, 1, size)]; count++;
                }

                cells[IX(size - 1, y, 0, size)] = sum / count;

                // 3
                sum = 0; count = 0;

                sum += cells[IX(size - 2, y, size - 1, size)]; count++;
                if (!wrapX)
                {
                    sum += cells[IX(1, y, size - 1, size)]; count++;
                }

                sum += cells[IX(0, y, 1, size)]; count++;
                if (!wrapZ)
                {
                    sum += cells[IX(0, y, size - 2, size)]; count++;
                }

                cells[IX(0, y, size - 1, size)] = sum / count;

                // 4
                sum = 0; count = 0;

                sum += cells[IX(1, y, size - 1, size)]; count++;
                if (!wrapX)
                {
                    sum += cells[IX(size - 2, y, size - 1, size)]; count++;
                }

                sum += cells[IX(size - 1, y, 1, size)]; count++;
                if (!wrapZ)
                {
                    sum += cells[IX(size - 1, y, size - 2, size)]; count++;
                }

                cells[IX(size - 1, y, size - 1, size)] = sum / count;
            }

            #endregion
            #region Z edges

            for (int z = 0; z < size - 1; z++)
            {
                // 1
                sum = 0; count = 0;

                sum += cells[IX(size - 2, 0, z, size)]; count++;
                if (!wrapX)
                {
                    sum += cells[IX(1, 0, z, size)]; count++;
                }

                sum += cells[IX(0, size - 2, z, size)]; count++;
                if (!wrapY)
                {
                    sum += cells[IX(0, 1, z, size)]; count++;
                }

                cells[IX(0, 0, z, size)] = sum / count;

                // 2
                sum = 0; count = 0;

                sum += cells[IX(1, 0, z, size)]; count++;
                if (!wrapX)
                {
                    sum += cells[IX(size - 2, 0, z, size)]; count++;
                }

                sum += cells[IX(size - 1, size - 2, z, size)]; count++;
                if (!wrapY)
                {
                    sum += cells[IX(size - 1, 1, z, size)]; count++;
                }

                cells[IX(size - 1, 0, z, size)] = sum / count;

                // 3
                sum = 0; count = 0;

                sum += cells[IX(size - 2, size - 1, z, size)]; count++;
                if (!wrapX)
                {
                    sum += cells[IX(1, size - 1, z, size)]; count++;
                }

                sum += cells[IX(0, 1, z, size)]; count++;
                if (!wrapY)
                {
                    sum += cells[IX(0, size - 2, z, size)]; count++;
                }

                cells[IX(0, size - 1, z, size)] = sum / count;

                // 4
                sum = 0; count = 0;

                sum += cells[IX(1, size - 1, z, size)]; count++;
                if (!wrapX)
                {
                    sum += cells[IX(size - 2, size - 1, z, size)]; count++;
                }

                sum += cells[IX(size - 1, 1, z, size)]; count++;
                if (!wrapY)
                {
                    sum += cells[IX(size - 1, size - 2, z, size)]; count++;
                }

                cells[IX(size - 1, size - 1, z, size)] = sum / count;
            }

            #endregion

            #region Corners

            // 1
            sum = 0; count = 0;

            sum += cells[IX(size - 2, 0, 0, size)]; count++;
            if (!wrapX)
            {
                sum += cells[IX(1, 0, 0, size)]; count++;
            }

            sum += cells[IX(0, size - 2, 0, size)]; count++;
            if (!wrapY)
            {
                sum += cells[IX(0, 1, 0, size)]; count++;
            }

            sum += cells[IX(0, 0, size - 2, size)]; count++;
            if (!wrapZ)
            {
                sum += cells[IX(0, 0, 1, size)]; count++;
            }

            cells[IX(0, 0, 0, size)] = sum / count;

            // 2
            sum = 0; count = 0;

            sum += cells[IX(size - 2, size - 1, 0, size)]; count++;
            if (!wrapX)
            {
                sum += cells[IX(1, size - 1, 0, size)]; count++;
            }

            sum += cells[IX(0, 1, 0, size)]; count++;
            if (!wrapY)
            {
                sum += cells[IX(0, size - 2, 0, size)]; count++;
            }

            sum += cells[IX(0, size - 1, size - 2, size)]; count++;
            if (!wrapZ)
            {
                sum += cells[IX(0, size - 1, 1, size)]; count++;
            }

            cells[IX(0, size - 1, 0, size)] = sum / count;

            // 3
            sum = 0; count = 0;

            sum += cells[IX(size - 2, 0, size - 1, size)]; count++;
            if (!wrapX)
            {
                sum += cells[IX(1, 0, size - 1, size)]; count++;
            }

            sum += cells[IX(0, size - 2, size - 1, size)]; count++;
            if (!wrapY)
            {
                sum += cells[IX(0, 1, size - 1, size)]; count++;
            }

            sum += cells[IX(0, 0, 1, size)]; count++;
            if (!wrapZ)
            {
                sum += cells[IX(0, 0, size - 2, size)]; count++;
            }

            cells[IX(0, 0, size - 1, size)] = sum / count;

            // 4
            sum = 0; count = 0;

            sum += cells[IX(size - 2, size - 1, size - 1, size)]; count++;
            if (!wrapX)
            {
                sum += cells[IX(1, size - 1, size - 1, size)]; count++;
            }

            sum += cells[IX(0, 1, size - 1, size)]; count++;
            if (!wrapY)
            {
                sum += cells[IX(0, size - 2, size - 1, size)]; count++;
            }

            sum += cells[IX(0, size - 1, 1, size)]; count++;
            if (!wrapZ)
            {
                sum += cells[IX(0, size - 1, size - 2, size)]; count++;
            }

            cells[IX(0, size - 1, size - 1, size)] = sum / count;

            // 5
            sum = 0; count = 0;

            sum += cells[IX(1, 0, 0, size)]; count++;
            if (!wrapX)
            {
                sum += cells[IX(size - 2, 0, 0, size)]; count++;
            }

            sum += cells[IX(size - 1, size - 2, 0, size)]; count++;
            if (!wrapY)
            {
                sum += cells[IX(size - 1, 1, 0, size)]; count++;
            }

            sum += cells[IX(size - 1, 0, size - 2, size)]; count++;
            if (!wrapZ)
            {
                sum += cells[IX(size - 1, 0, 1, size)]; count++;
            }

            cells[IX(size - 1, 0, 0, size)] = sum / count;

            // 6
            sum = 0; count = 0;

            sum += cells[IX(1, size - 1, 0, size)]; count++;
            if (!wrapX)
            {
                sum += cells[IX(size - 2, size - 1, 0, size)]; count++;
            }

            sum += cells[IX(size - 1, 1, 0, size)]; count++;
            if (!wrapY)
            {
                sum += cells[IX(size - 1, size - 2, 0, size)]; count++;
            }

            sum += cells[IX(size - 1, size - 1, size - 2, size)]; count++;
            if (!wrapZ)
            {
                sum += cells[IX(size - 1, size - 1, 1, size)]; count++;
            }

            cells[IX(size - 1, size - 1, 0, size)] = sum / count;

            // 7
            sum = 0; count = 0;

            sum += cells[IX(1, 0, size - 1, size)]; count++;
            if (!wrapX)
            {
                sum += cells[IX(size - 2, 0, size - 1, size)]; count++;
            }

            sum += cells[IX(size - 1, size - 2, size - 1, size)]; count++;
            if (!wrapY)
            {
                sum += cells[IX(size - 1, 1, size - 1, size)]; count++;
            }

            sum += cells[IX(size - 1, 0, 1, size)]; count++;
            if (!wrapZ)
            {
                sum += cells[IX(size - 1, 0, size - 2, size)]; count++;
            }

            cells[IX(size - 1, 0, size - 1, size)] = sum / count;

            // 8
            sum = 0; count = 0;

            sum += cells[IX(1, size - 1, size - 1, size)]; count++;
            if (!wrapX)
            {
                sum += cells[IX(size - 2, size - 1, size - 1, size)]; count++;
            }

            sum += cells[IX(size - 1, 1, size - 1, size)]; count++;
            if (!wrapY)
            {
                sum += cells[IX(size - 1, size - 2, size - 1, size)]; count++;
            }

            sum += cells[IX(size - 1, size - 1, 1, size)]; count++;
            if (!wrapZ)
            {
                sum += cells[IX(size - 1, size - 1, size - 2, size)]; count++;
            }

            cells[IX(size - 1, size - 1, size - 1, size)] = sum / count;

            #endregion
        }
Example #7
0
        private static void SetBoundry_BlockedCells(SetBoundsType whichSide, double[] cells, BoundrySettings boundrySettings)
        {
            //NOTE: It is safe to ignore blocked cells that are interior (surrounded by other blocked cells)

            IndexLERP[] blocked = null;

            switch (whichSide)
            {
                case SetBoundsType.VelocityX:
                    blocked = boundrySettings.Blocked_VelocityX;
                    break;

                case SetBoundsType.VelocityY:
                    blocked = boundrySettings.Blocked_VelocityY;
                    break;

                case SetBoundsType.VelocityZ:
                    blocked = boundrySettings.Blocked_VelocityZ;
                    break;

                case SetBoundsType.Ink:
                case SetBoundsType.Other:
                    blocked = boundrySettings.Blocked_Other;
                    break;

                default:
                    throw new ApplicationException("Unknown SetBoundsType: " + whichSide.ToString());
            }

            foreach (IndexLERP index in blocked)
            {
                // Add up the neighbors
                double newValue = 0d;

                if (index.Neighbors != null)
                {
                    foreach (var neighbor in index.Neighbors)
                    {
                        newValue += cells[neighbor.Item1] * neighbor.Item2;
                    }
                }

                // Store the average
                cells[index.Index1D] = newValue;
            }
        }
Example #8
0
        private static void SetBoundry_OpenSlaved(SetBoundsType whichSide, double[] cells, int size, BoundrySettings boundrySettings)
        {
            double[] source;

            switch (whichSide)
            {
                case SetBoundsType.VelocityX:
                    source = boundrySettings.OpenBorderVelocityX;
                    break;

                case SetBoundsType.VelocityY:
                    source = boundrySettings.OpenBorderVelocityY;
                    break;

                case SetBoundsType.VelocityZ:
                    source = boundrySettings.OpenBorderVelocityZ;
                    break;

                default:
                    // Non velocity can use the standard open method
                    SetBoundry_Open(whichSide, cells, size, boundrySettings);
                    return;
            }

            // When slaved, this field's velocity is just a copy of the source's velocity
            foreach (var index in boundrySettings.OpenBorderCells)
            {
                cells[index.Offset1D] = source[index.Offset1D];
            }
        }
Example #9
0
        private static void SetBoundry_OpenShared(SetBoundsType whichSide, double[] cells, int size, BoundrySettings boundrySettings)
        {
            // This method is sort of a combination of SetBoundry_Open and SetBoundry_OpenSlaved.  It stores the average of what
            // open would have stored with what slave would have stored: (open + slave) / 2

            double[] source;

            switch (whichSide)
            {
                case SetBoundsType.VelocityX:
                    source = boundrySettings.OpenBorderVelocityX;
                    break;

                case SetBoundsType.VelocityY:
                    source = boundrySettings.OpenBorderVelocityY;
                    break;

                case SetBoundsType.VelocityZ:
                    source = boundrySettings.OpenBorderVelocityZ;
                    break;

                default:
                    // Non velocity can use the standard open method
                    SetBoundry_Open(whichSide, cells, size, boundrySettings);
                    return;
            }

            #region X wall

            int index;

            for (int z = 1; z < size - 1; z++)
            {
                for (int y = 1; y < size - 1; y++)
                {
                    index = IX(0, y, z, size);
                    cells[index] = .5d * (source[index] + cells[IX(1, y, z, size)]);

                    index = IX(size - 1, y, z, size);
                    cells[index] = .5d * (source[index] + cells[IX(size - 2, y, z, size)]);
                }
            }

            #endregion
            #region Y wall

            for (int z = 1; z < size - 1; z++)
            {
                for (int x = 1; x < size - 1; x++)
                {
                    index = IX(x, 0, z, size);
                    cells[index] = .5d * (source[index] + cells[IX(x, 1, z, size)]);

                    index = IX(x, size - 1, z, size);
                    cells[index] = .5d * (source[index] + cells[IX(x, size - 2, z, size)]);
                }
            }

            #endregion
            #region Z wall

            for (int y = 1; y < size - 1; y++)
            {
                for (int x = 1; x < size - 1; x++)
                {
                    index = IX(x, y, 0, size);
                    cells[index] = .5d * (source[index] + cells[IX(x, y, 1, size)]);

                    index = IX(x, y, size - 1, size);
                    cells[index] = .5d * (source[index] + cells[IX(x, y, size - 2, size)]);
                }
            }

            #endregion

            #region Edges

            double thisValue;

            for (int x = 1; x < size - 1; x++)
            {
                index = IX(x, 0, 0, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(x, 1, 0, size)], false) : cells[IX(x, 1, 0, size)]) +      // restrict y travel when it's the y veloctiy array
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(x, 0, 1, size)], false) : cells[IX(x, 0, 1, size)])        // restrict z travel when it's the z velocity array
                    );
                cells[index] = .5d * (source[index] + thisValue);       // now take the average of this field's value with the source.  NOTE: Giving the two equal weight, that's why I don't just add the 3 and divide by 3.

                index = IX(x, size - 1, 0, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(x, size - 2, 0, size)], true) : cells[IX(x, size - 2, 0, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(x, size - 1, 1, size)], false) : cells[IX(x, size - 1, 1, size)])
                    );
                cells[index] = .5d * (source[index] + thisValue);

                index = IX(x, 0, size - 1, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(x, 1, size - 1, size)], false) : cells[IX(x, 1, size - 1, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(x, 0, size - 2, size)], true) : cells[IX(x, 0, size - 2, size)])
                    );
                cells[index] = .5d * (source[index] + thisValue);

                index = IX(x, size - 1, size - 1, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(x, size - 2, size - 1, size)], true) : cells[IX(x, size - 2, size - 1, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(x, size - 1, size - 2, size)], true) : cells[IX(x, size - 1, size - 2, size)])
                    );
                cells[index] = .5d * (source[index] + thisValue);
            }

            for (int y = 1; y < size - 1; y++)
            {
                index = IX(0, y, 0, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, y, 0, size)], false) : cells[IX(1, y, 0, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, y, 1, size)], false) : cells[IX(0, y, 1, size)])
                    );
                cells[index] = .5d * (source[index] + thisValue);

                index = IX(size - 1, y, 0, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, y, 0, size)], true) : cells[IX(size - 2, y, 0, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, y, 1, size)], false) : cells[IX(size - 1, y, 1, size)])
                    );
                cells[index] = .5d * (source[index] + thisValue);

                index = IX(0, y, size - 1, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, y, size - 1, size)], false) : cells[IX(1, y, size - 1, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, y, size - 2, size)], true) : cells[IX(0, y, size - 2, size)])
                    );
                cells[index] = .5d * (source[index] + thisValue);

                index = IX(size - 1, y, size - 1, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, y, size - 1, size)], true) : cells[IX(size - 2, y, size - 1, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, y, size - 2, size)], true) : cells[IX(size - 1, y, size - 2, size)])
                    );
                cells[index] = .5d * (source[index] + thisValue);
            }

            for (int z = 0; z < size - 1; z++)
            {
                index = IX(0, 0, z, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, 0, z, size)], false) : cells[IX(1, 0, z, size)]) +
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, 1, z, size)], false) : cells[IX(0, 1, z, size)])
                    );
                cells[index] = .5d * (source[index] + thisValue);

                index = IX(size - 1, 0, z, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, 0, z, size)], true) : cells[IX(size - 2, 0, z, size)]) +
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, 1, z, size)], false) : cells[IX(size - 1, 1, z, size)])
                    );
                cells[index] = .5d * (source[index] + thisValue);

                index = IX(0, size - 1, z, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, size - 1, z, size)], false) : cells[IX(1, size - 1, z, size)]) +
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, size - 2, z, size)], true) : cells[IX(0, size - 2, z, size)])
                    );
                cells[index] = .5d * (source[index] + thisValue);

                index = IX(size - 1, size - 1, z, size);
                thisValue = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, size - 1, z, size)], true) : cells[IX(size - 2, size - 1, z, size)]) +
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, size - 2, z, size)], true) : cells[IX(size - 1, size - 2, z, size)])
                    );
                cells[index] = .5d * (source[index] + thisValue);
            }

            #endregion

            #region Corners

            // Corners take average of neighbors

            index = IX(0, 0, 0, size);
            thisValue = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, 0, 0, size)], false) : cells[IX(1, 0, 0, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, 1, 0, size)], false) : cells[IX(0, 1, 0, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, 0, 1, size)], false) : cells[IX(0, 0, 1, size)])
                );
            cells[index] = .5d * (source[index] + thisValue);

            index = IX(0, size - 1, 0, size);
            thisValue = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, size - 1, 0, size)], false) : cells[IX(1, size - 1, 0, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, size - 2, 0, size)], true) : cells[IX(0, size - 2, 0, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, size - 1, 1, size)], false) : cells[IX(0, size - 1, 1, size)])
                );
            cells[index] = .5d * (source[index] + thisValue);

            index = IX(0, 0, size - 1, size);
            thisValue = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, 0, size - 1, size)], false) : cells[IX(1, 0, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, 1, size - 1, size)], false) : cells[IX(0, 1, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, 0, size - 2, size)], true) : cells[IX(0, 0, size - 2, size)])
                );
            cells[index] = .5d * (source[index] + thisValue);

            index = IX(0, size - 1, size - 1, size);
            thisValue = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, size - 1, size - 1, size)], false) : cells[IX(1, size - 1, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, size - 2, size - 1, size)], true) : cells[IX(0, size - 2, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, size - 1, size - 2, size)], true) : cells[IX(0, size - 1, size - 2, size)])
                );
            cells[index] = .5d * (source[index] + thisValue);

            index = IX(size - 1, 0, 0, size);
            thisValue = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, 0, 0, size)], true) : cells[IX(size - 2, 0, 0, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, 1, 0, size)], false) : cells[IX(size - 1, 1, 0, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, 0, 1, size)], false) : cells[IX(size - 1, 0, 1, size)])
                );
            cells[index] = .5d * (source[index] + thisValue);

            index = IX(size - 1, size - 1, 0, size);
            thisValue = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, size - 1, 0, size)], true) : cells[IX(size - 2, size - 1, 0, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, size - 2, 0, size)], true) : cells[IX(size - 1, size - 2, 0, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, size - 1, 1, size)], false) : cells[IX(size - 1, size - 1, 1, size)])
                );
            cells[index] = .5d * (source[index] + thisValue);

            index = IX(size - 1, 0, size - 1, size);
            thisValue = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, 0, size - 1, size)], true) : cells[IX(size - 2, 0, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, 1, size - 1, size)], false) : cells[IX(size - 1, 1, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, 0, size - 2, size)], true) : cells[IX(size - 1, 0, size - 2, size)])
                );
            cells[index] = .5d * (source[index] + thisValue);

            index = IX(size - 1, size - 1, size - 1, size);
            thisValue = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, size - 1, size - 1, size)], true) : cells[IX(size - 2, size - 1, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, size - 2, size - 1, size)], true) : cells[IX(size - 1, size - 2, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, size - 1, size - 2, size)], true) : cells[IX(size - 1, size - 1, size - 2, size)])
                );
            cells[index] = .5d * (source[index] + thisValue);

            #endregion
        }
Example #10
0
        private static void SetBoundry_Open(SetBoundsType whichSide, double[] cells, int size, BoundrySettings boundrySettings)
        {
            // OpenBox needs to allow open flow for the velocity, but just copy cells for everything else
            //NOTE: Allow outflow, but not full inflow (the inflow becomes self reinforcing, and the whole field becomes a wall of wind)
            //NOTE: Inflow is only an issue along the wall where the corresponding velocity array is parallel (so the velocityX array only needs to worry about the x wall.  The y and z walls are safe to copy values, because the flow is perpendicular to them)

            #region X wall

            if (whichSide == SetBoundsType.VelocityX)
            {
                for (int z = 1; z < size - 1; z++)
                {
                    for (int y = 1; y < size - 1; y++)
                    {
                        cells[IX(0, y, z, size)] = SetBoundry_OpenSprtCap(cells[IX(1, y, z, size)], false);
                        cells[IX(size - 1, y, z, size)] = SetBoundry_OpenSprtCap(cells[IX(size - 2, y, z, size)], true);
                    }
                }
            }
            else
            {
                for (int z = 1; z < size - 1; z++)
                {
                    for (int y = 1; y < size - 1; y++)
                    {
                        cells[IX(0, y, z, size)] = cells[IX(1, y, z, size)];
                        cells[IX(size - 1, y, z, size)] = cells[IX(size - 2, y, z, size)];
                    }
                }
            }

            #endregion
            #region Y wall

            if (whichSide == SetBoundsType.VelocityY)
            {
                for (int z = 1; z < size - 1; z++)
                {
                    for (int x = 1; x < size - 1; x++)
                    {
                        cells[IX(x, 0, z, size)] = SetBoundry_OpenSprtCap(cells[IX(x, 1, z, size)], false);
                        cells[IX(x, size - 1, z, size)] = SetBoundry_OpenSprtCap(cells[IX(x, size - 2, z, size)], true);
                    }
                }
            }
            else
            {
                for (int z = 1; z < size - 1; z++)
                {
                    for (int x = 1; x < size - 1; x++)
                    {
                        cells[IX(x, 0, z, size)] = cells[IX(x, 1, z, size)];
                        cells[IX(x, size - 1, z, size)] = cells[IX(x, size - 2, z, size)];
                    }
                }
            }

            #endregion
            #region Z wall

            if (whichSide == SetBoundsType.VelocityZ)
            {
                for (int y = 1; y < size - 1; y++)
                {
                    for (int x = 1; x < size - 1; x++)
                    {
                        cells[IX(x, y, 0, size)] = SetBoundry_OpenSprtCap(cells[IX(x, y, 1, size)], false);
                        cells[IX(x, y, size - 1, size)] = SetBoundry_OpenSprtCap(cells[IX(x, y, size - 2, size)], true);
                    }
                }
            }
            else
            {
                for (int y = 1; y < size - 1; y++)
                {
                    for (int x = 1; x < size - 1; x++)
                    {
                        cells[IX(x, y, 0, size)] = cells[IX(x, y, 1, size)];
                        cells[IX(x, y, size - 1, size)] = cells[IX(x, y, size - 2, size)];
                    }
                }
            }

            #endregion

            #region Edges

            for (int x = 1; x < size - 1; x++)
            {
                cells[IX(x, 0, 0, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(x, 1, 0, size)], false) : cells[IX(x, 1, 0, size)]) +      // restrict y travel when it's the y veloctiy array
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(x, 0, 1, size)], false) : cells[IX(x, 0, 1, size)])        // restrict z travel when it's the z velocity array
                    );

                cells[IX(x, size - 1, 0, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(x, size - 2, 0, size)], true) : cells[IX(x, size - 2, 0, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(x, size - 1, 1, size)], false) : cells[IX(x, size - 1, 1, size)])
                    );

                cells[IX(x, 0, size - 1, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(x, 1, size - 1, size)], false) : cells[IX(x, 1, size - 1, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(x, 0, size - 2, size)], true) : cells[IX(x, 0, size - 2, size)])
                    );

                cells[IX(x, size - 1, size - 1, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(x, size - 2, size - 1, size)], true) : cells[IX(x, size - 2, size - 1, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(x, size - 1, size - 2, size)], true) : cells[IX(x, size - 1, size - 2, size)])
                    );
            }

            for (int y = 1; y < size - 1; y++)
            {
                cells[IX(0, y, 0, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, y, 0, size)], false) : cells[IX(1, y, 0, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, y, 1, size)], false) : cells[IX(0, y, 1, size)])
                    );

                cells[IX(size - 1, y, 0, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, y, 0, size)], true) : cells[IX(size - 2, y, 0, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, y, 1, size)], false) : cells[IX(size - 1, y, 1, size)])
                    );

                cells[IX(0, y, size - 1, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, y, size - 1, size)], false) : cells[IX(1, y, size - 1, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, y, size - 2, size)], true) : cells[IX(0, y, size - 2, size)])
                    );

                cells[IX(size - 1, y, size - 1, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, y, size - 1, size)], true) : cells[IX(size - 2, y, size - 1, size)]) +
                    (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, y, size - 2, size)], true) : cells[IX(size - 1, y, size - 2, size)])
                    );
            }

            for (int z = 0; z < size - 1; z++)
            {
                cells[IX(0, 0, z, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, 0, z, size)], false) : cells[IX(1, 0, z, size)]) +
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, 1, z, size)], false) : cells[IX(0, 1, z, size)])
                    );

                cells[IX(size - 1, 0, z, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, 0, z, size)], true) : cells[IX(size - 2, 0, z, size)]) +
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, 1, z, size)], false) : cells[IX(size - 1, 1, z, size)])
                    );

                cells[IX(0, size - 1, z, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, size - 1, z, size)], false) : cells[IX(1, size - 1, z, size)]) +
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, size - 2, z, size)], true) : cells[IX(0, size - 2, z, size)])
                    );

                cells[IX(size - 1, size - 1, z, size)] = 0.5 * (
                    (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, size - 1, z, size)], true) : cells[IX(size - 2, size - 1, z, size)]) +
                    (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, size - 2, z, size)], true) : cells[IX(size - 1, size - 2, z, size)])
                    );
            }

            #region FLAWED

            //double average1, average2, average3, average4;

            //for (int x = 1; x < size - 1; x++)
            //{
            //    average1 = 0.5 * (cells[IX(x, 1, 0, size)] + cells[IX(x, 0, 1, size)]);
            //    average2 = 0.5 * (cells[IX(x, size - 2, size - 1, size)] + cells[IX(x, size - 1, size - 2, size)]);
            //    average3 = 0.5 * (cells[IX(x, size - 2, 0, size)] + cells[IX(x, size - 1, 1, size)]);
            //    average4 = 0.5 * (cells[IX(x, 1, size - 1, size)] + cells[IX(x, 0, size - 2, size)]);

            //    if (whichSide == SetBoundsType.VelocityY || whichSide == SetBoundsType.VelocityZ)
            //    {
            //        average1 = SetBoundry_OpenBoxSprtCap(average1, false);
            //        average2 = SetBoundry_OpenBoxSprtCap(average2, true);
            //        average3 *= OPENINFLOWMULT;
            //        average4 *= OPENINFLOWMULT;
            //    }

            //    cells[IX(x, 0, 0, size)] = average1;
            //    cells[IX(x, size - 1, size - 1, size)] = average2;

            //    cells[IX(x, size - 1, 0, size)] = average3;
            //    cells[IX(x, 0, size - 1, size)] = average4;
            //}

            //for (int y = 1; y < size - 1; y++)
            //{
            //    average1 = 0.5 * (cells[IX(1, y, 0, size)] + cells[IX(0, y, 1, size)]);
            //    average2 = 0.5 * (cells[IX(size - 2, y, size - 1, size)] + cells[IX(size - 1, y, size - 2, size)]);
            //    average3 = 0.5 * (cells[IX(size - 2, y, 0, size)] + cells[IX(size - 1, y, 1, size)]);
            //    average4 = 0.5 * (cells[IX(1, y, size - 1, size)] + cells[IX(0, y, size - 2, size)]);

            //    if (whichSide == SetBoundsType.VelocityX || whichSide == SetBoundsType.VelocityZ)
            //    {
            //        average1 = SetBoundry_OpenBoxSprtCap(average1, false);
            //        average2 = SetBoundry_OpenBoxSprtCap(average2, true);
            //        average3 *= OPENINFLOWMULT;
            //        average4 *= OPENINFLOWMULT;
            //    }

            //    cells[IX(0, y, 0, size)] = average1;
            //    cells[IX(size - 1, y, size - 1, size)] = average2;

            //    cells[IX(size - 1, y, 0, size)] = average3;
            //    cells[IX(0, y, size - 1, size)] = average4;
            //}

            //for (int z = 0; z < size - 1; z++)
            //{
            //    average1 = 0.5 * (cells[IX(1, 0, z, size)] + cells[IX(0, 1, z, size)]);
            //    average2 = 0.5 * (cells[IX(size - 2, size - 1, z, size)] + cells[IX(size - 1, size - 2, z, size)]);
            //    average3 = 0.5 * (cells[IX(size - 2, 0, z, size)] + cells[IX(size - 1, 1, z, size)]);
            //    average4 = 0.5 * (cells[IX(1, size - 1, z, size)] + cells[IX(0, size - 2, z, size)]);

            //    if (whichSide == SetBoundsType.VelocityX || whichSide == SetBoundsType.VelocityY)
            //    {
            //        average1 = SetBoundry_OpenBoxSprtCap(average1, false);
            //        average2 = SetBoundry_OpenBoxSprtCap(average2, true);
            //        average3 *= OPENINFLOWMULT;
            //        average4 *= OPENINFLOWMULT;
            //    }

            //    cells[IX(0, 0, z, size)] = average1;
            //    cells[IX(size - 1, size - 1, z, size)] = average2;

            //    cells[IX(size - 1, 0, z, size)] = average3;
            //    cells[IX(0, size - 1, z, size)] = average4;
            //}

            #endregion

            #endregion

            #region Corners

            // Corners take average of neighbors

            cells[IX(0, 0, 0, size)] = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, 0, 0, size)], false) : cells[IX(1, 0, 0, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, 1, 0, size)], false) : cells[IX(0, 1, 0, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, 0, 1, size)], false) : cells[IX(0, 0, 1, size)])
                );

            cells[IX(0, size - 1, 0, size)] = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, size - 1, 0, size)], false) : cells[IX(1, size - 1, 0, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, size - 2, 0, size)], true) : cells[IX(0, size - 2, 0, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, size - 1, 1, size)], false) : cells[IX(0, size - 1, 1, size)])
                );

            cells[IX(0, 0, size - 1, size)] = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, 0, size - 1, size)], false) : cells[IX(1, 0, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, 1, size - 1, size)], false) : cells[IX(0, 1, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, 0, size - 2, size)], true) : cells[IX(0, 0, size - 2, size)])
                );

            cells[IX(0, size - 1, size - 1, size)] = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(1, size - 1, size - 1, size)], false) : cells[IX(1, size - 1, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(0, size - 2, size - 1, size)], true) : cells[IX(0, size - 2, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(0, size - 1, size - 2, size)], true) : cells[IX(0, size - 1, size - 2, size)])
                );

            cells[IX(size - 1, 0, 0, size)] = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, 0, 0, size)], true) : cells[IX(size - 2, 0, 0, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, 1, 0, size)], false) : cells[IX(size - 1, 1, 0, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, 0, 1, size)], false) : cells[IX(size - 1, 0, 1, size)])
                );

            cells[IX(size - 1, size - 1, 0, size)] = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, size - 1, 0, size)], true) : cells[IX(size - 2, size - 1, 0, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, size - 2, 0, size)], true) : cells[IX(size - 1, size - 2, 0, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, size - 1, 1, size)], false) : cells[IX(size - 1, size - 1, 1, size)])
                );

            cells[IX(size - 1, 0, size - 1, size)] = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, 0, size - 1, size)], true) : cells[IX(size - 2, 0, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, 1, size - 1, size)], false) : cells[IX(size - 1, 1, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, 0, size - 2, size)], true) : cells[IX(size - 1, 0, size - 2, size)])
                );

            cells[IX(size - 1, size - 1, size - 1, size)] = ONETHIRD * (
                (whichSide == SetBoundsType.VelocityX ? SetBoundry_OpenSprtCap(cells[IX(size - 2, size - 1, size - 1, size)], true) : cells[IX(size - 2, size - 1, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityY ? SetBoundry_OpenSprtCap(cells[IX(size - 1, size - 2, size - 1, size)], true) : cells[IX(size - 1, size - 2, size - 1, size)]) +
                (whichSide == SetBoundsType.VelocityZ ? SetBoundry_OpenSprtCap(cells[IX(size - 1, size - 1, size - 2, size)], true) : cells[IX(size - 1, size - 1, size - 2, size)])
                );


            #region FLAWED

            //double average;
            //bool isVelocity = whichSide == SetBoundsType.VelocityX || whichSide == SetBoundsType.VelocityY || whichSide == SetBoundsType.VelocityZ;

            //// 1
            //average = ONETHIRD * (
            //    cells[IX(1, 0, 0, size)] +
            //    cells[IX(0, 1, 0, size)] +
            //    cells[IX(0, 0, 1, size)]);

            //if (isVelocity) average *= OPENINFLOWMULT;

            //cells[IX(0, 0, 0, size)] = average;

            //// 2
            //average = ONETHIRD * (
            //    cells[IX(1, size - 1, 0, size)] +
            //    cells[IX(0, size - 2, 0, size)] +
            //    cells[IX(0, size - 1, 1, size)]);

            //if (isVelocity) average *= OPENINFLOWMULT;

            //cells[IX(0, size - 1, 0, size)] = average;

            //// 3
            //average = ONETHIRD * (
            //    cells[IX(1, 0, size - 1, size)] +
            //    cells[IX(0, 1, size - 1, size)] +
            //    cells[IX(0, 0, size - 2, size)]);

            //if (isVelocity) average *= OPENINFLOWMULT;

            //cells[IX(0, 0, size - 1, size)] = average;

            //// 4
            //average = ONETHIRD * (
            //    cells[IX(1, size - 1, size - 1, size)] +
            //    cells[IX(0, size - 2, size - 1, size)] +
            //    cells[IX(0, size - 1, size - 2, size)]);

            //if (isVelocity) average *= OPENINFLOWMULT;

            //cells[IX(0, size - 1, size - 1, size)] = average;

            //// 5
            //average = ONETHIRD * (
            //    cells[IX(size - 2, 0, 0, size)] +
            //    cells[IX(size - 1, 1, 0, size)] +
            //    cells[IX(size - 1, 0, 1, size)]);

            //if (isVelocity) average *= OPENINFLOWMULT;

            //cells[IX(size - 1, 0, 0, size)] = average;

            //// 6
            //average = ONETHIRD * (
            //    cells[IX(size - 2, size - 1, 0, size)] +
            //    cells[IX(size - 1, size - 2, 0, size)] +
            //    cells[IX(size - 1, size - 1, 1, size)]);

            //if (isVelocity) average *= OPENINFLOWMULT;

            //cells[IX(size - 1, size - 1, 0, size)] = average;

            //// 7
            //average = ONETHIRD * (
            //    cells[IX(size - 2, 0, size - 1, size)] +
            //    cells[IX(size - 1, 1, size - 1, size)] +
            //    cells[IX(size - 1, 0, size - 2, size)]);

            //if (isVelocity) average *= OPENINFLOWMULT;

            //cells[IX(size - 1, 0, size - 1, size)] = average;

            //// 8
            //average = ONETHIRD * (
            //    cells[IX(size - 2, size - 1, size - 1, size)] +
            //    cells[IX(size - 1, size - 2, size - 1, size)] +
            //    cells[IX(size - 1, size - 1, size - 2, size)]);

            //if (isVelocity) average *= OPENINFLOWMULT;

            //cells[IX(size - 1, size - 1, size - 1, size)] = average;

            #endregion

            #endregion
        }
Example #11
0
        private static void SetBoundry_Closed(SetBoundsType whichSide, double[] cells, int size, BoundrySettings boundrySettings)
        {
            #region X wall

            // When it's the x velocity, it needs to reflect off of this wall.  All other cases slide along it (or in the case of non
            // velocities, just a copy)
            double reflectMult = whichSide == SetBoundsType.VelocityX ? -boundrySettings.WallReflectivity : 1d;

            for (int z = 1; z < size - 1; z++)
            {
                for (int y = 1; y < size - 1; y++)
                {
                    cells[IX(0, y, z, size)] = reflectMult * cells[IX(1, y, z, size)];
                    cells[IX(size - 1, y, z, size)] = reflectMult * cells[IX(size - 2, y, z, size)];
                }
            }

            #endregion
            #region Y wall

            reflectMult = whichSide == SetBoundsType.VelocityY ? -boundrySettings.WallReflectivity : 1d;

            for (int z = 1; z < size - 1; z++)
            {
                for (int x = 1; x < size - 1; x++)
                {
                    cells[IX(x, 0, z, size)] = reflectMult * cells[IX(x, 1, z, size)];
                    cells[IX(x, size - 1, z, size)] = reflectMult * cells[IX(x, size - 2, z, size)];
                }
            }

            #endregion
            #region Z wall

            reflectMult = whichSide == SetBoundsType.VelocityZ ? -boundrySettings.WallReflectivity : 1d;

            for (int y = 1; y < size - 1; y++)
            {
                for (int x = 1; x < size - 1; x++)
                {
                    cells[IX(x, y, 0, size)] = reflectMult * cells[IX(x, y, 1, size)];
                    cells[IX(x, y, size - 1, size)] = reflectMult * cells[IX(x, y, size - 2, size)];
                }
            }

            #endregion

            #region Edges

            for (int x = 1; x < size - 1; x++)
            {
                cells[IX(x, 0, 0, size)] = 0.5 * (cells[IX(x, 1, 0, size)] + cells[IX(x, 0, 1, size)]);
                cells[IX(x, size - 1, 0, size)] = 0.5 * (cells[IX(x, size - 2, 0, size)] + cells[IX(x, size - 1, 1, size)]);
                cells[IX(x, 0, size - 1, size)] = 0.5 * (cells[IX(x, 1, size - 1, size)] + cells[IX(x, 0, size - 2, size)]);
                cells[IX(x, size - 1, size - 1, size)] = 0.5 * (cells[IX(x, size - 2, size - 1, size)] + cells[IX(x, size - 1, size - 2, size)]);
            }

            for (int y = 1; y < size - 1; y++)
            {
                cells[IX(0, y, 0, size)] = 0.5 * (cells[IX(1, y, 0, size)] + cells[IX(0, y, 1, size)]);
                cells[IX(size - 1, y, 0, size)] = 0.5 * (cells[IX(size - 2, y, 0, size)] + cells[IX(size - 1, y, 1, size)]);
                cells[IX(0, y, size - 1, size)] = 0.5 * (cells[IX(1, y, size - 1, size)] + cells[IX(0, y, size - 2, size)]);
                cells[IX(size - 1, y, size - 1, size)] = 0.5 * (cells[IX(size - 2, y, size - 1, size)] + cells[IX(size - 1, y, size - 2, size)]);
            }

            for (int z = 0; z < size - 1; z++)
            {
                cells[IX(0, 0, z, size)] = 0.5 * (cells[IX(1, 0, z, size)] + cells[IX(0, 1, z, size)]);
                cells[IX(size - 1, 0, z, size)] = 0.5 * (cells[IX(size - 2, 0, z, size)] + cells[IX(size - 1, 1, z, size)]);
                cells[IX(0, size - 1, z, size)] = 0.5 * (cells[IX(1, size - 1, z, size)] + cells[IX(0, size - 2, z, size)]);
                cells[IX(size - 1, size - 1, z, size)] = 0.5 * (cells[IX(size - 2, size - 1, z, size)] + cells[IX(size - 1, size - 2, z, size)]);
            }

            #endregion

            #region Corners

            // Corners take average of neighbors
            cells[IX(0, 0, 0, size)] = ONETHIRD * (
                cells[IX(1, 0, 0, size)] +
                cells[IX(0, 1, 0, size)] +
                cells[IX(0, 0, 1, size)]);

            cells[IX(0, size - 1, 0, size)] = ONETHIRD * (
                cells[IX(1, size - 1, 0, size)] +
                cells[IX(0, size - 2, 0, size)] +
                cells[IX(0, size - 1, 1, size)]);

            cells[IX(0, 0, size - 1, size)] = ONETHIRD * (
                cells[IX(1, 0, size - 1, size)] +
                cells[IX(0, 1, size - 1, size)] +
                cells[IX(0, 0, size - 2, size)]);

            cells[IX(0, size - 1, size - 1, size)] = ONETHIRD * (
                cells[IX(1, size - 1, size - 1, size)] +
                cells[IX(0, size - 2, size - 1, size)] +
                cells[IX(0, size - 1, size - 2, size)]);

            cells[IX(size - 1, 0, 0, size)] = ONETHIRD * (
                cells[IX(size - 2, 0, 0, size)] +
                cells[IX(size - 1, 1, 0, size)] +
                cells[IX(size - 1, 0, 1, size)]);

            cells[IX(size - 1, size - 1, 0, size)] = ONETHIRD * (
                cells[IX(size - 2, size - 1, 0, size)] +
                cells[IX(size - 1, size - 2, 0, size)] +
                cells[IX(size - 1, size - 1, 1, size)]);

            cells[IX(size - 1, 0, size - 1, size)] = ONETHIRD * (
                cells[IX(size - 2, 0, size - 1, size)] +
                cells[IX(size - 1, 1, size - 1, size)] +
                cells[IX(size - 1, 0, size - 2, size)]);

            cells[IX(size - 1, size - 1, size - 1, size)] = ONETHIRD * (
                cells[IX(size - 2, size - 1, size - 1, size)] +
                cells[IX(size - 1, size - 2, size - 1, size)] +
                cells[IX(size - 1, size - 1, size - 2, size)]);

            #endregion
        }
Example #12
0
        private static void SetBoundry(SetBoundsType whichSide, double[] cells, bool[] blocked, int size, BoundrySettings boundrySettings)
        {
            // Outer Edges
            switch (boundrySettings.BoundryType)
            {
                case FluidFieldBoundryType3D.Closed:
                    SetBoundry_Closed(whichSide, cells, size, boundrySettings);
                    break;

                case FluidFieldBoundryType3D.Open:
                    SetBoundry_Open(whichSide, cells, size, boundrySettings);
                    break;

                case FluidFieldBoundryType3D.Open_Shared:
                    SetBoundry_OpenShared(whichSide, cells, size, boundrySettings);
                    break;

                case FluidFieldBoundryType3D.Open_Slaved:
                    SetBoundry_OpenSlaved(whichSide, cells, size, boundrySettings);
                    break;

                case FluidFieldBoundryType3D.WrapAround:
                    SetBoundry_ReachAround(whichSide, cells, size, boundrySettings);
                    break;

                default:
                    throw new ApplicationException("Unknown FluidFieldBoundryType3D: " + boundrySettings.BoundryType.ToString());
            }

            // Blocked Cells
            if (boundrySettings.HasBlockedCells)
            {
                // This has similar logic to closed box, but applied facing outward around the blocked cells
                SetBoundry_BlockedCells(whichSide, cells, boundrySettings);
            }
        }