protected void DrawPhi() { if (this.phi == null) { return; } var norm = FluidHelper.Infnorm(this.phi); var old = Gizmos.color; this.phi?.ForEachData((ref float value, int[] list) => { var dataOrg = this.phi.DataOrigin; var c = Color.white; if (value < 0) { c = Color.black; } c *= Mathf.Abs(value); c.a = 0.5f; Gizmos.color = c; Gizmos.DrawCube(new Vector3(list[0], list[1], 0) + new Vector3(dataOrg.x, dataOrg.y, 0), new Vector3(cellSpace, cellSpace, 0.1f) * 0.9f); }); Gizmos.color = old; }
protected void DrawVelocity() { if (this.velocity == null) { return; } var norm = FluidHelper.Infnorm(this.velocity); var scale = Vector2.one / norm * 0.4f * new Vector2(cellSpace, cellSpace); var old = Gizmos.color; this.velocity?.ForEachuData((ref float value, int i, int j) => { var dataOrg = this.velocity.uDataOrigin; var from = new Vector3(i, j, 0) + new Vector3(dataOrg.x, dataOrg.y, 0); var to = from + new Vector3(value, 0, 0) * scale.x; Gizmos.DrawLine(from, to); }); this.velocity?.ForEachvData((ref float value, int i, int j) => { var dataOrg = this.velocity.vDataOrigin; var from = new Vector3(i, j, 0) + new Vector3(dataOrg.x, dataOrg.y, 0); var to = from + new Vector3(0, value, 0) * scale.y; Gizmos.DrawLine(from, to); }); Gizmos.color = old; }
protected override int AbsoluteDataIndex(params int[] list) { Assert.IsTrue(list.Length == 2); Assert.IsTrue(0 <= list[0] && list[0] < this.DataSize.x); Assert.IsTrue(0 <= list[1] && list[1] < this.DataSize.y); Vector2Int index = FluidHelper.ClampIndex(new Vector2Int(list[0], list[1]), Vector2Int.zero, this.DataSize); return(index.x + (this.DataSize.x * index.y)); }
public override float BiLerp(int i, int j, float fx, float fy) { var f00 = this[i, j]; var f10 = this[i + 1, j]; var f01 = this[i, j + 1]; var f11 = this[i + 1, j + 1]; return(FluidHelper.BiLerp(f00, f10, f01, f11, fx, fy)); }
protected float GetCFL() { var h = cellSpace; var norm = FluidHelper.Infnorm(this.velocity); float maxv2 = Mathf.Max(h * Gravaty, sqr(norm.x) + sqr(norm.y)); if (maxv2 < 1e-16) { maxv2 = 1e-16f; } return(h / Mathf.Sqrt(maxv2)); }
public void AccumulatePoint(Vector2 pos, Vector2 value) { Vector2Int[] index; Vector2[] weights; var cellSpace = this.CellSize; var org = this.uDataOrigin; //and first - Vector2Int.one is for data index [0, size-1] var indexSize = this.uDataSize - Vector2Int.one; //note index max should be size-1, clamp did this check FluidHelper.GetIndexAndWeight(pos, org, cellSpace, Vector2Int.zero, indexSize, out index, out weights); for (var i = 0; i < index.Length; ++i) { var type = DataType.U; var id = this.AbsoluteIndex(type, index[i]); var weight = weights[i].x * weights[i].y; this.data[type][id] += value.x * weight; this.uWeightSum[index[i].x, index[i].y] += weight; } org = this.vDataOrigin; //and first - Vector2Int.one is for data index [0, size-1] indexSize = this.vDataSize - Vector2Int.one; //note index max should be size-1, clamp did this check FluidHelper.GetIndexAndWeight(pos, org, cellSpace, Vector2Int.zero, indexSize, out index, out weights); for (var i = 0; i < index.Length; ++i) { var type = DataType.V; var id = this.AbsoluteIndex(type, index[i]); var weight = weights[i].x * weights[i].y; this.data[type][id] += value.y * weight; this.vWeightSum[index[i].x, index[i].y] += weight; } }
public override Vector2 GetDataFromIndex(params int[] list) { Assert.IsTrue(list.Length == 4); var ret = new Vector2(); Assert.IsTrue(0 <= list[0] && list[0] < this.uDataSize.x); Assert.IsTrue(0 <= list[1] && list[1] < this.uDataSize.y); Vector2Int index = FluidHelper.ClampIndex(new Vector2Int(list[0], list[1]), Vector2Int.zero, this.uDataSize); ret.x = this.data[DataType.U][this.AbsoluteIndex(DataType.U, index)]; Assert.IsTrue(0 <= list[2] && list[2] < this.vDataSize.x); Assert.IsTrue(0 <= list[3] && list[3] < this.vDataSize.y); index = FluidHelper.ClampIndex(new Vector2Int(list[2], list[3]), Vector2Int.zero, this.vDataSize); ret.y = this.data[DataType.V][this.AbsoluteIndex(DataType.V, index)]; return(ret); }
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)); }
protected void ParticleToGrid() { this.velocity.ResetValueAndWeight(); this.marker.Reset(AIR); foreach (var p in this.CPUData) { if (p.active == false) { continue; } var pos = p.position; var vel = p.velocity; this.velocity.AccumulatePoint(pos, vel); Vector2Int posIndex; Vector2 posFrac; FluidHelper.GetIndexAndFraction(pos, this.marker.Origin, this.marker.CellSize, Vector2Int.zero, this.marker.DataSize, out posIndex, out posFrac); this.marker[posIndex.x, posIndex.y] = FLUID; } this.velocity.NormalizeWeight(); }