Esempio n. 1
0
        void FormPreconditioner()
        {
            const float mic_parameter = 0.99f;
            float       d;

            preconditioner.Reset(0);

            var preconditionernx = this.preconditioner.DataSize.x;
            var preconditionerny = this.preconditioner.DataSize.y;

            for (int j = 1; j < preconditionerny - 1; ++j)
            {
                for (int i = 1; i < preconditionernx - 1; ++i)
                {
                    if (marker[i, j] == FLUID)
                    {
                        d = poisson[i, j].x - sqr(poisson[i - 1, j].y * preconditioner[i - 1, j])
                            - sqr(poisson[i, j - 1].z * preconditioner[i, j - 1])
                            - mic_parameter * (poisson[i - 1, j].y * poisson[i - 1, j].z * sqr(preconditioner[i - 1, j])
                                               + poisson[i, j - 1].z * poisson[i, j - 1].y * sqr(preconditioner[i, j - 1]));
                        preconditioner[i, j] = 1 / Mathf.Sqrt(d + 1e-6f);
                    }
                }
            }
        }
Esempio n. 2
0
        void FindDivergence()
        {
            r.Reset(0);
            this.r.ForEachData((ref float value, int[] list) =>
            {
                var i = list[0];
                var j = list[1];
                if (this.marker[i, j] == FLUID)
                {
                    this.r[i, j] = (this.velocity[MACGrid2DData.DataType.U, i + 1, j] - this.velocity[MACGrid2DData.DataType.U, i, j])
                                   + (this.velocity[MACGrid2DData.DataType.V, i, j + 1] - this.velocity[MACGrid2DData.DataType.V, i, j]);

                    //this.r[i, j] = 0.5f * (this.velocity[MACGrid2DData.DataType.U, i + 1, j] - this.velocity[MACGrid2DData.DataType.U, i-1, j])
                    //             + 0.5f * (this.velocity[MACGrid2DData.DataType.V, i, j + 1] - this.velocity[MACGrid2DData.DataType.V, i, j-1]);

                    //this.r[i, j] = this.velocity.GetDivergenceFromIndex(i, j);
                }
            });
        }
Esempio n. 3
0
        void ApplyPoisson(CellCenteredScalarGrid2D x, CellCenteredScalarGrid2D y)
        {
            y.Reset(0);
            var poissonnx = this.poisson.DataSize.x;
            var poissonny = this.poisson.DataSize.y;

            for (int j = 1; j < poissonny - 1; ++j)
            {
                for (int i = 1; i < poissonnx - 1; ++i)
                {
                    if (this.marker.GetDataFromIndex(i, j) == FLUID)
                    {
                        var value = poisson.GetDataFromIndex(i, j).x *x.GetDataFromIndex(i, j)
                                    + poisson.GetDataFromIndex(i - 1, j).y *x.GetDataFromIndex(i - 1, j)
                                    + poisson.GetDataFromIndex(i, j).y *x.GetDataFromIndex(i + 1, j)
                                    + poisson.GetDataFromIndex(i, j - 1).z *x.GetDataFromIndex(i, j - 1)
                                    + poisson.GetDataFromIndex(i, j).z *x.GetDataFromIndex(i, j + 1);
                        y.SetDataToIndex(value, i, j);
                    }
                }
            }
        }
Esempio n. 4
0
        void SolvePressure(int maxits, float tolerance)
        {
            int   its;
            float rNorm = FluidHelper.Infnorm(this.r);
            float tol   = tolerance * rNorm;

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

            if (rho == 0)
            {
                return;
            }
            for (its = 0; its < maxits; ++its)
            {
                ApplyPoisson(s, z);
                float alpha = rho / FluidHelper.Dot(s, z);
                FluidHelper.Increment(pressure, s, alpha);
                FluidHelper.Increment(r, z, -alpha);
                if (FluidHelper.Infnorm(this.r) <= tol)
                {
                    Debug.LogFormat("pressure converged to {0} in {1} iterations\n", FluidHelper.Infnorm(this.r), its);
                    return;
                }
                ApplyPreconditioner(r, z, mField);
                float rhonew = FluidHelper.Dot(z, r);
                float beta   = rhonew / rho;
                FluidHelper.ScaleAndIncrement(s, z, beta);
                rho = rhonew;
            }
            Debug.LogFormat("Didn't converge in pressure solve (its={0}, tol={1}, |r|={2})\n", its, tol, FluidHelper.Infnorm(this.r));
        }
Esempio n. 5
0
        void ApplyPreconditioner(CellCenteredScalarGrid2D x, CellCenteredScalarGrid2D y, CellCenteredScalarGrid2D m)
        {
            //Maybe Incomplete Cholesky??
            int   i, j;
            float d;
            var   xnx = x.DataSize.x;
            var   xny = x.DataSize.y;

            m.Reset();
            // solve L*m=x
            for (j = 1; j < xny - 1; ++j)
            {
                for (i = 1; i < xnx - 1; ++i)
                {
                    if (marker[i, j] == FLUID)
                    {
                        d = x[i, j] - poisson[i - 1, j].y * preconditioner[i - 1, j] * m[i - 1, j]
                            - poisson[i, j - 1].z * preconditioner[i, j - 1] * m[i, j - 1];
                        m[i, j] = preconditioner[i, j] * d;
                    }
                }
            }
            // solve L'*y=m
            y.Reset();
            for (j = xny - 2; j > 0; --j)
            {
                for (i = xnx - 2; i > 0; --i)
                {
                    if (marker[i, j] == FLUID)
                    {
                        d = m[i, j] - poisson[i, j].y * preconditioner[i, j] * y[i + 1, j]
                            - poisson[i, j].z * preconditioner[i, j] * y[i, j + 1];
                        y[i, j] = preconditioner[i, j] * d;
                    }
                }
            }
        }