private double ComputePBFDensity(FluidBody3d fluid, Vector3 pi, int i, int numNeighbors, int[,] neighbors)
        {
            //Density for Pi
            // Di = SUMj Mj * W(Pi - Pj, h)

            // Compute current density for particle i
            fluid.Densities[i] = fluid.ParticleMass * fluid.Kernel.W_zero;

            for (int j = 0; j < numNeighbors; j++)
            {
                int neighborIndex = neighbors[i, j];
                if (neighborIndex < fluid.NumParticles) // Test if fluid particle
                {
                    Vector3 pn = fluid.Predicted[neighborIndex];
                    fluid.Densities[i] += fluid.ParticleMass * fluid.Kernel.W(pi.x - pn.x, pi.y - pn.y, pi.z - pn.z);
                }
                else
                {
                    int k = neighborIndex - fluid.NumParticles;

                    Vector3 pn = Boundary.Positions[k];
                    fluid.Densities[i] += Boundary.Psi[k] * fluid.Kernel.W(pi.x - pn.x, pi.y - pn.y, pi.z - pn.z);
                }
            }

            double maxDensity = fluid.Densities[i];

            if (fluid.Density > maxDensity)
            {
                maxDensity = fluid.Density;
            }

            return(maxDensity - fluid.Density);
        }
        public void CreateFluid(double radius, double density)
        {
            //To make less particles decrease the size of the bounds or increase the radius.
            //Make sure fluid bounds fits inside the boundrys bounds.

            FluidBounds = new Box3d(-8, -4, 0, 8, -2, 2);
            ParticlesFromBounds source = new ParticlesFromBounds(radius, FluidBounds);

            System.Random rnd = new System.Random(0);

            Body          = new FluidBody3d(source, radius, density, Matrix4x4d.Identity);
            Body.Dampning = 0.0;
            Body.AddBoundry(Boundary);
            Body.RandomizePositions(rnd, radius * 0.01);
            Body.RandomizePositionOrder(rnd);

            FluidSpheres = new GameObject[Body.NumParticles];

            float diam = (float)Body.ParticleDiameter;

            for (int i = 0; i < FluidSpheres.Length; i++)
            {
                Vector3d pos = Body.Positions[i];

                GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                sphere.transform.parent     = transform;
                sphere.transform.position   = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
                sphere.transform.localScale = new Vector3(diam, diam, diam);
                sphere.GetComponent <Collider>().enabled = false;

                sphere.GetComponent <MeshRenderer>().material = sphereMaterial;

                FluidSpheres[i] = sphere;
            }
        }
Exemplo n.º 3
0
        public GPUFluidSolver3d(FluidBody3d body)
        {
            InitCurrentShader();

            Body   = body;
            Forces = new List <ExternalForce3d>();
        }
        private void InitConstShaderData()
        {
            FluidBody3d fluid = Body as FluidBody3d;

            CurrentShader.SetInt("Iterations", Iterations);

            CurrentShader.SetFloat("FluidParticleMass", fluid.ParticleMass);
            CurrentShader.SetFloat("FluidDensity", fluid.Density);
        }
        internal FluidConstraint3dGPU(FluidBody3d body, FluidBoundary3d boundary) : base(body)
        {
            Iterations = 5;
            Boundary   = boundary;

            InitCurrentShader();

            body.Kernel.InitCubicKernel3dGPU(CurrentShader);

            InitConstShaderData();
        }
        internal override void ConstrainPositions(double di)
        {
            FluidBody3d fluid = Body as FluidBody3d;

            fluid.NeighboursSearcher.NeighbourhoodSearch(fluid.GPUPredicted, Boundary.GPUPositions);

            CurrentShader.SetInt("FluidNumParticles", fluid.NumParticles);
            //pre step(Calcuclate Density, Calculate Lambda Coeffs)
            CurrentShader.SetBuffer(KERNEL_ID_PRESTEP, "NeighboursMap", fluid.NeighboursSearcher.NeighboursMap);
            CurrentShader.SetBuffer(KERNEL_ID_PRESTEP, "NumNeighbours", fluid.NeighboursSearcher.NumNeighbours);

            CurrentShader.SetBuffer(KERNEL_ID_PRESTEP, "FluidPositions", fluid.GPUPositions);
            CurrentShader.SetBuffer(KERNEL_ID_PRESTEP, "FluidPredicted", fluid.GPUPredicted);
            CurrentShader.SetBuffer(KERNEL_ID_PRESTEP, "FluidDensities", fluid.GPUDensities);
            CurrentShader.SetBuffer(KERNEL_ID_PRESTEP, "FluidLambda", fluid.GPULambda);

            CurrentShader.SetBuffer(KERNEL_ID_PRESTEP, "BoundaryPositions", Boundary.GPUPositions);
            CurrentShader.SetBuffer(KERNEL_ID_PRESTEP, "BoundaryPsi", Boundary.GPUPsi);

            //constraint
            CurrentShader.SetBuffer(KERNEL_DENSITYCONSTRAINT, "NeighboursMap", fluid.NeighboursSearcher.NeighboursMap);
            CurrentShader.SetBuffer(KERNEL_DENSITYCONSTRAINT, "NumNeighbours", fluid.NeighboursSearcher.NumNeighbours);

            CurrentShader.SetBuffer(KERNEL_DENSITYCONSTRAINT, "FluidPositions", fluid.GPUPositions);
            CurrentShader.SetBuffer(KERNEL_DENSITYCONSTRAINT, "FluidPredicted", fluid.GPUPredicted);
            CurrentShader.SetBuffer(KERNEL_DENSITYCONSTRAINT, "FluidDensities", fluid.GPUDensities);
            CurrentShader.SetBuffer(KERNEL_DENSITYCONSTRAINT, "FluidLambda", fluid.GPULambda);

            CurrentShader.SetBuffer(KERNEL_DENSITYCONSTRAINT, "BoundaryPositions", Boundary.GPUPositions);
            CurrentShader.SetBuffer(KERNEL_DENSITYCONSTRAINT, "BoundaryPsi", Boundary.GPUPsi);

            int iter = 0;

            while (iter < Iterations)
            {
                //pre step(Calcuclate Density, Calculate Lambda Coeffs)
                CurrentShader.Dispatch(KERNEL_ID_PRESTEP, ShaderHelper.GetNumberOfDispatchGroups(fluid.NumParticles, BLOCK_SIZE), 1, 1);

                //constraint
                CurrentShader.Dispatch(KERNEL_DENSITYCONSTRAINT, ShaderHelper.GetNumberOfDispatchGroups(fluid.NumParticles, BLOCK_SIZE), 1, 1);

                iter++;
            }
        }
        private Vector3 SolveDensityConstraint(FluidBody3d fluid, Vector3 pi, int i, int numNeighbors, int[,] neighbors)
        {
            //Total position update for Pi
            // dPi = 1 / D0 * SUMj (Li + Lj) * dW(Pi - Pj, h)

            Vector3 corr              = Vector3.zero;
            double  InvDensity        = 1.0 / fluid.Density;
            double  MassMulInvDensity = fluid.ParticleMass * InvDensity;

            for (int j = 0; j < numNeighbors; j++)
            {
                int neighborIndex = neighbors[i, j];
                if (neighborIndex < fluid.NumParticles) // Test if fluid particle
                {
                    Vector3 pn = fluid.Predicted[neighborIndex];

                    Vector3 gradW = fluid.Kernel.GradW(new Vector3(pi.x - pn.x, pi.y - pn.y, pi.z - pn.z));

                    double lambda = (fluid.Lambda[i] + fluid.Lambda[neighborIndex]) * -MassMulInvDensity;
                    corr.x -= (float)lambda * gradW.x;
                    corr.y -= (float)lambda * gradW.y;
                    corr.z -= (float)lambda * gradW.z;
                }
                else
                {
                    int k = neighborIndex - fluid.NumParticles;

                    Vector3 pn = Boundary.Positions[k];

                    Vector3 gradW = fluid.Kernel.GradW(new Vector3(pi.x - pn.x, pi.y - pn.y, pi.z - pn.z));

                    double lambda = fluid.Lambda[i] * -Boundary.Psi[k] * InvDensity;
                    corr.x -= (float)lambda * gradW.x;
                    corr.y -= (float)lambda * gradW.y;
                    corr.z -= (float)lambda * gradW.z;
                }
            }

            return(corr);
        }
        internal override void ConstrainPositions(double di)
        {
            FluidBody3d fluid = Body as FluidBody3d;

            if (fluid == null)
            {
                return;
            }

            fluid.Hash.NeighborhoodSearch(fluid.Predicted, Boundary.Positions);

            int[,] neighbors = fluid.Hash.Neighbors;
            int[] numNeighbors = fluid.Hash.NumNeighbors;

            int iter = 0;

            while (iter < Iterations)
            {
                //Calculate lambda.
                for (int i = 0; i < fluid.NumParticles; i++)
                {
                    Vector3 pi = fluid.Predicted[i];
                    //Calculate density constraint.
                    ComputePBFDensity(fluid, pi, i, numNeighbors[i], neighbors);
                    ComputePBFLagrangeMultiplier(fluid, pi, i, numNeighbors[i], neighbors);
                }

                //Update position.
                for (int i = 0; i < fluid.NumParticles; i++)
                {
                    Vector3 pi = fluid.Predicted[i];
                    fluid.Predicted[i] += SolveDensityConstraint(fluid, pi, i, numNeighbors[i], neighbors);
                }

                iter++;
            }

            fluid.Hash.IncrementTimeStamp(); //TODO - needs to move
        }
Exemplo n.º 9
0
        public void CreateFluid(float radius, float density)
        {
            //To make less particles decrease the size of the bounds or increase the radius.
            //Make sure fluid bounds fits inside the boundrys bounds.
            FluidBounds = new Box3f(-8, 0, 0, 8, -2, 2);//new Box3f(-7, 6, 1, 7, -2, 4);


            FluidParticlesWithConstraint source = new FluidParticlesWithConstraint(radius, FluidBounds, Boundary.NumParticles);

            System.Random rnd = new System.Random(0);

            Body          = new FluidBody3d(source, radius, density, Matrix4x4f.Identity);
            Body.Dampning = 0.0f;
            Body.AddBoundry(Boundary);
            Body.RandomizePositions(rnd, radius * 0.01f);
            Body.RandomizePositionOrder(rnd);

            Debug.Log(Body.NumParticles);


            CreateFluidVisualize();
        }
 internal FluidConstraint3d(FluidBody3d body, FluidBoundary3d boundary) : base(body)
 {
     Iterations = 5;
     Boundary   = boundary;
 }
        private void ComputePBFLagrangeMultiplier(FluidBody3d fluid, Vector3 pi, int i, int numNeighbors, int[,] neighbors)
        {
            double eps               = 1.0e-6;
            double InvDensity        = 1.0 / fluid.Density;
            double MassMulInvDensity = fluid.ParticleMass * InvDensity;

            // Evaluate constraint function. Clamp to prevent particle clumping at surface.
            //Ci = Di / D0 - 1
            double C = fluid.Densities[i] * InvDensity - 1.0;

            if (C < 0.0)
            {
                C = 0.0;
            }

            if (C != 0.0)
            {
                //Compute gradients.

                //Constraint gradient for Pi
                //dPkCi = 1/D0 * SUMj dPk * W(Pi - Pj, h)

                double   sum_grad_C2 = 0.0;
                Vector3d gradC_i     = Vector3d.Zero;

                for (int j = 0; j < numNeighbors; j++)
                {
                    int neighborIndex = neighbors[i, j];
                    if (neighborIndex < fluid.NumParticles) // Test if fluid particle
                    {
                        Vector3  pn    = fluid.Predicted[neighborIndex];
                        Vector3d gradW = fluid.Kernel.GradW(pi.x - pn.x, pi.y - pn.y, pi.z - pn.z);

                        Vector3d gradC_j;
                        gradC_j.x = -MassMulInvDensity * gradW.x;
                        gradC_j.y = -MassMulInvDensity * gradW.y;
                        gradC_j.z = -MassMulInvDensity * gradW.z;

                        sum_grad_C2 += gradC_j.x * gradC_j.x + gradC_j.y * gradC_j.y + gradC_j.z * gradC_j.z;

                        gradC_i.x -= gradC_j.x;
                        gradC_i.y -= gradC_j.y;
                        gradC_i.z -= gradC_j.z;
                    }
                    else
                    {
                        int k = neighborIndex - fluid.NumParticles;

                        Vector3 pn    = Boundary.Positions[k];
                        Vector3 gradW = fluid.Kernel.GradW(new Vector3(pi.x - pn.x, pi.y - pn.y, pi.z - pn.z));

                        double psi = -Boundary.Psi[k] * InvDensity;

                        Vector3d gradC_j;
                        gradC_j.x = psi * gradW.x;
                        gradC_j.y = psi * gradW.y;
                        gradC_j.z = psi * gradW.z;

                        sum_grad_C2 += gradC_j.x * gradC_j.x + gradC_j.y * gradC_j.y + gradC_j.z * gradC_j.z;

                        gradC_i.x -= gradC_j.x;
                        gradC_i.y -= gradC_j.y;
                        gradC_i.z -= gradC_j.z;
                    }
                }

                sum_grad_C2 += gradC_i.SqrMagnitude;

                //Lambda for Pi
                //Li = -Ci / SUM | dPk Ci |^ 2 + e

                // Compute lambda
                fluid.Lambda[i] = -C / (sum_grad_C2 + eps);
            }
            else
            {
                fluid.Lambda[i] = 0.0;
            }
        }
Exemplo n.º 12
0
 public FluidSolver3d(FluidBody3d body)
 {
     Body   = body;
     Forces = new List <ExternalForce3d>();
 }