示例#1
0
        void ApplyPreconditioner(Array2Df x, Array2Df y, Array2Df m)
        {
            //Maybe Incomplete Cholesky??
            int   i, j;
            float d;

            m.Reset();
            // solve L*m=x
            for (j = 1; j < x.ny - 1; ++j)
            {
                for (i = 1; i < x.nx - 1; ++i)
                {
                    if (marker[i, j] == FLUID)
                    {
                        d = x[i, j] - poisson[i - 1, j, 1] * preconditioner[i - 1, j] * m[i - 1, j]
                            - poisson[i, j - 1, 2] * preconditioner[i, j - 1] * m[i, j - 1];
                        m[i, j] = preconditioner[i, j] * d;
                    }
                }
            }
            // solve L'*y=m
            y.Reset();
            for (j = x.ny - 2; j > 0; --j)
            {
                for (i = x.nx - 2; i > 0; --i)
                {
                    if (marker[i, j] == FLUID)
                    {
                        d = m[i, j] - poisson[i, j, 1] * preconditioner[i, j] * y[i + 1, j]
                            - poisson[i, j, 2] * preconditioner[i, j] * y[i, j + 1];
                        y[i, j] = preconditioner[i, j] * d;
                    }
                }
            }
        }
示例#2
0
 public void FindDivergence()
 {
     r.Reset();
     for (int j = 0; j < r.ny; ++j)
     {
         for (int i = 0; i < r.nx; ++i)
         {
             if (marker[i, j] == FLUID)
             {
                 r[i, j] = u[i + 1, j] - u[i, j] + v[i, j + 1] - v[i, j];
             }
         }
     }
 }
示例#3
0
        protected void BuildB()
        {
            rhsB.Reset();

            var density   = 1;
            var cellSpace = 1;
            var dt        = 1 / 30f;
            var scale     = density * cellSpace / dt;


            for (int j = 0; j < rhsB.ny; ++j)
            {
                for (int i = 0; i < rhsB.nx; ++i)
                {
                    if (marker[i, j] == FLUID)
                    {
                        var im1 = Mathf.Max(0, i - 1);
                        var jm1 = Mathf.Max(0, j - 1);

                        var ip1 = Mathf.Min(rhsB.nx - 1, i + 1);
                        var jp1 = Mathf.Min(rhsB.ny - 1, j + 1);

                        var div     = u[ip1, j] - u[i, j] + v[i, jp1] - v[i, j];
                        var baseRhs = scale * -div;

                        //left
                        if (marker[im1, j] == SOLID)
                        {
                            baseRhs += -scale * (u[i, j] - u[im1, j]);
                        }
                        //right
                        if (marker[ip1, j] == SOLID)
                        {
                            baseRhs += scale * (u[i, j] - u[ip1, j]);
                        }
                        if (marker[i, jm1] == SOLID)
                        {
                            baseRhs += -scale * (v[i, j] - v[im1, j]);
                        }
                        if (marker[i, jp1] == SOLID)
                        {
                            baseRhs += scale * (v[i, j] - v[ip1, j]);
                        }

                        rhsB[i, j] = baseRhs;
                    }
                }
            }
        }
示例#4
0
 public void ApplyPoisson(Array2Df x, Array2Df y)
 {
     y.Reset();
     for (int j = 1; j < poisson.ny - 1; ++j)
     {
         for (int i = 1; i < poisson.nx - 1; ++i)
         {
             if (marker[i, j] == FLUID)
             {
                 y[i, j] = poisson[i, j, 0] * x[i, j]
                           + poisson[i - 1, j, 1] * x[i - 1, j]
                           + poisson[i, j, 1] * x[i + 1, j]
                           + poisson[i, j - 1, 2] * x[i, j - 1]
                           + poisson[i, j, 2] * x[i, j + 1];
             }
         }
     }
 }
示例#5
0
        void FormPreconditioner()
        {
            const float mic_parameter = 0.99f;
            float       d;

            preconditioner.Reset();
            for (int j = 1; j < preconditioner.ny - 1; ++j)
            {
                for (int i = 1; i < preconditioner.nx - 1; ++i)
                {
                    if (marker[i, j] == FLUID)
                    {
                        d = poisson[i, j, 0] - sqr(poisson[i - 1, j, 1] * preconditioner[i - 1, j])
                            - sqr(poisson[i, j - 1, 2] * preconditioner[i, j - 1])
                            - mic_parameter * (poisson[i - 1, j, 1] * poisson[i - 1, j, 2] * sqr(preconditioner[i - 1, j])
                                               + poisson[i, j - 1, 2] * poisson[i, j - 1, 1] * sqr(preconditioner[i, j - 1]));
                        preconditioner[i, j] = 1 / Mathf.Sqrt(d + 1e-6f);
                    }
                }
            }
        }
示例#6
0
        public void SolvePressure(int maxits, double tolerance)
        {
            int    its;
            double tol = tolerance * r.InfNorm();

            pressure.Reset();
            if (r.InfNorm() == 0)
            {
                return;
            }
            ApplyPreconditioner(r, z, m);
            z.CopyTo(s);
            float rho = z.Dot(r);

            if (rho == 0)
            {
                return;
            }
            for (its = 0; its < maxits; ++its)
            {
                ApplyPoisson(s, z);
                float alpha = rho / s.Dot(z);
                pressure.Increment(alpha, s);
                r.Increment(-alpha, z);
                if (r.InfNorm() <= tol)
                {
                    Debug.LogFormat("pressure converged to {0} in {1} iterations\n", r.InfNorm(), its);
                    return;
                }
                ApplyPreconditioner(r, z, m);
                float rhonew = z.Dot(r);
                float beta   = rhonew / rho;
                s.ScaleAndIncrement(beta, z);
                rho = rhonew;
            }
            Debug.LogFormat("Didn't converge in pressure solve (its={0}, tol={1}, |r|={2})\n", its, tol, r.InfNorm());
        }
示例#7
0
        public void TransferToGrid()
        {
            int   p = 0, i = 0, ui = 0, j = 0, vj = 0;
            float fx = 0, ufx = 0, fy = 0, vfy = 0;

            grid.u.Reset();
            sum.Reset();
            for (p = 0; p < np; ++p)
            {
                grid.bary_x(x[p][0], ref ui, ref ufx);
                grid.bary_y_centre(x[p][1], ref j, ref fy);
                accumulate(grid.u, u[p][0], ui, j, ufx, fy);
                /* TODO: call affineFix to incorporate c_px^n into the grid.u update */
                if (type == PICMain.SimType.APIC)
                {
                    affineFix(grid.u, cx[p], ui, j, ufx, fy);
                }
            }
            for (j = 0; j < grid.u.ny; ++j)
            {
                for (i = 0; i < grid.u.nx; ++i)
                {
                    if (sum[i, j] != 0)
                    {
                        grid.u[i, j] /= sum[i, j];
                    }
                }
            }

            grid.v.Reset();
            sum.Reset();
            for (p = 0; p < np; ++p)
            {
                grid.bary_x_centre(x[p][0], ref i, ref fx);
                grid.bary_y(x[p][1], ref vj, ref vfy);
                accumulate(grid.v, u[p][1], i, vj, fx, vfy);
                /* TODO: call affineFix to incorporate c_py^n into the grid.v update */
                if (type == PICMain.SimType.APIC)
                {
                    affineFix(grid.v, cy[p], i, vj, fx, vfy);
                }
            }
            for (j = 0; j < grid.v.ny; ++j)
            {
                for (i = 0; i < grid.v.nx; ++i)
                {
                    if (sum[i, j] != 0)
                    {
                        grid.v[i, j] /= sum[i, j];
                    }
                }
            }

            // identify where particles are in grid
            grid.marker.Reset();
            for (p = 0; p < np; ++p)
            {
                grid.bary_x(x[p][0], ref i, ref fx);
                grid.bary_y(x[p][1], ref j, ref fy);
                grid.marker[i, j] = PICGrid.FLUID;
            }
        }