public FluidSimulationFrame(IntSize3 leveSetSizeStokesSize, int numParticles, IntSize3 navierStokesSize, float navierStokesCellSize) { LeveSetSizeStokesSize = leveSetSizeStokesSize; Particles = new Vector3[numParticles]; Phi = new double[leveSetSizeStokesSize.Volume()]; ParticleMask = new bool[leveSetSizeStokesSize.Volume()]; NavierStokesGrid = new NavierStokesGrid(navierStokesSize, navierStokesCellSize); }
public LevelSet(IntSize3 size, float cellSize, INavierStokesGrid grid) { Size = size; CellSize = cellSize; phi = new double[size.Volume()]; backPhi = new double[size.Volume()]; mass = new float[size.Volume()]; backMass = new float[size.Volume()]; states = new NavierStokesCellState[size.Volume()]; particleMass = new float[size.Volume()]; particleMask = new bool[size.Volume()]; for (int j = 0; j < Size.Height - 1; j++) { for (int i = 0; i < Size.Width - 1; i++) { var point = new Vector3(i, j, 0) * CellSize; State(i, j) = grid.StateAtPoint(point); } } }
public void TransferPhi(float deltaT, INavierStokesGrid grid) { /* * Parallel.For(0, Size.Volume(), index => * { * var j = index / Size.Width; * var i = index - j * Size.Width; * * if (i < 1 || i >= Size.Width - 1 || j < 1 || j >= Size.Height - 1) * return; * * var dpdx = (Phi(i + 1, j) - Phi(i - 1, j)) / (2 * CellSize); * var dpdy = (Phi(i, j + 1) - Phi(i, j - 1)) / (2 * CellSize); * var point = CellSize * (new Vector3(i, j, 0) + new Vector3(0.5f, 0.5f, 0.5f)); * var u = grid.GetVelocityAt(point) * deltaT; * var deltaPhi = -u.X * dpdx - u.Y * dpdy; * BackPhi(i, j) = Phi(i, j) + deltaPhi; * });*/ /* * for (int j = 1; j < Size.Height - 1; j++) * for (int i = 1; i < Size.Width - 1; i++) * { * var dpdx = (Phi(i + 1, j) - Phi(i - 1, j)) / (2 * CellSize); * var dpdy = (Phi(i, j + 1) - Phi(i, j - 1)) / (2 * CellSize); * var point = CellSize * (new Vector3(i, j, 0) + new Vector3(0.5f, 0.5f, 0.5f)); * var u = grid.GetVelocityAt(point) * deltaT; * var deltaPhi = -u.X * dpdx - u.Y * dpdy; * BackPhi(i, j) = Phi(i, j) + deltaPhi; * }*/ Array.Clear(backPhi, 0, backPhi.Length); var halfVector = new Vector3(0.5f, 0.5f, 0.5f); var cornerOffset = CellSize * halfVector; Parallel.For(0, Size.Volume(), index => { var j = index / Size.Width; var i = index - j * Size.Width; if (i < 1 || i >= Size.Width - 1 || j < 1 || j >= Size.Height - 1) { return; } var remainingDeltaT = deltaT; var point = CellSize * (new Vector3(i, j, 0) + halfVector); while (remainingDeltaT > 0) { var v = grid.GetVelocityAt(point); var vlen = v.Length(); var localDeltaT = vlen * remainingDeltaT > CellSize ? CellSize / vlen : remainingDeltaT; var potentialPoint = point + v * localDeltaT; var potentialCorner = potentialPoint - cornerOffset; var normPotentialCorner = potentialCorner / CellSize; var npci = (int)normPotentialCorner.X; var npcj = (int)normPotentialCorner.Y; if (State(npci, npcj) == NavierStokesCellState.Object) { break; } point = potentialPoint; remainingDeltaT -= localDeltaT; } var corner = point - cornerOffset; //var centerPoint = new Vector3(Size.Width, Size.Height, 0) * CellSize / 2; //while (grid.StateAtPoint(corner) == NavierStokesCellState.Object) //{ // corner = Vector3.Lerp(corner, centerPoint, 0.05f); //} var ti = (int)(corner.X / CellSize); var tj = (int)(corner.Y / CellSize); var intCorner = new Vector3(ti, tj, 0) * CellSize; var rightVolume = (corner.X - intCorner.X) / CellSize; var upVolume = (corner.Y - intCorner.Y) / CellSize; var leftVolume = 1 - rightVolume; var downVolume = 1 - upVolume; var originalMass = Phi(i, j); var a00 = originalMass * leftVolume * downVolume; var a01 = originalMass * leftVolume * upVolume; var a10 = originalMass * rightVolume * downVolume; var a11 = originalMass * rightVolume * upVolume; lock (backWriteLock) { BackPhi(ti, tj) += a00; BackPhi(ti + 1, tj) += a10; BackPhi(ti, tj + 1) += a01; BackPhi(ti + 1, tj + 1) += a11; } }); CodingHelper.Swap(ref phi, ref backPhi); }