/// <summary> /// Initialize the simulator object. /// </summary> public FluidSimulator getSimulator(int ord) { DateTime now = DateTime.UtcNow; FluidSimulator s = new FluidSimulator(progress, new RandomJames(now.Ticks * (ord + 1))); return(s); }
public WorkerThreadInit(FluidSimulator s, int n, double pptake, double deltat, double variancet) { sim = s; nPart = n; ppt = pptake; dt = deltat; vart = variancet; }
/// <summary> /// Simple world containing two segments. /// </summary> public static void Roof(FluidSimulator sim) { sim.SetBounds(0.0, 3.0, 0.0, 1.0); sim.RemoveAllWalls(); sim.AddWall(-0.01, 0.0, 3.0, 0.0); sim.AddWall(-0.01, 1.0, 3.0, 1.0); sim.AddWall(0.0, 0.0, 0.0, 1.0); sim.AddWall(0.5, 0.5, 0.9, 0.15); sim.AddWall(0.5, 0.5, 0.9, 0.85); }
/// <summary> /// Simple world containing one rectangle. /// </summary> public static void Rectangle(FluidSimulator sim) { sim.SetBounds(0.0, 3.0, 0.0, 1.0); sim.RemoveAllWalls(); sim.AddWall(-0.01, 0.0, 3.0, 0.0); sim.AddWall(-0.01, 1.0, 3.0, 1.0); sim.AddWall(0.0, 0.0, 0.0, 1.0); sim.AddWall(0.5, 0.2, 0.5, 0.8); sim.AddWall(0.5, 0.2, 1.1, 0.2); sim.AddWall(0.5, 0.8, 1.1, 0.8); sim.AddWall(1.1, 0.2, 1.1, 0.8); }
/// <summary> /// Simple world with a maze. /// </summary> public static void Maze(FluidSimulator sim) { sim.SetBounds(0.0, 3.0, 0.0, 1.0); sim.RemoveAllWalls(); sim.AddWall(-0.01, 0.0, 3.0, 0.0); sim.AddWall(-0.01, 1.0, 3.0, 1.0); sim.AddWall(0.0, 0.0, 0.0, 1.0); sim.AddWall(0.4, 0.0, 0.4, 0.8); sim.AddWall(0.6, 0.2, 0.6, 1.0); sim.AddWall(0.8, 0.0, 0.8, 0.8); sim.AddWall(1.0, 0.2, 1.0, 1.0); sim.AddWall(1.2, 0.0, 1.2, 0.8); sim.AddWall(1.4, 0.2, 1.4, 1.0); }
/// <summary> /// Runs the simulation (in separate thread[s]). /// </summary> public void RunSimulation() { // allocate & init simulator array: int threads = Math.Max(1, Environment.ProcessorCount - 1); if (!UseMultithreading) { threads = 1; } sims = new List <FluidSimulator>(threads); int t; for (t = 0; t < threads; t++) { FluidSimulator fs = getSimulator(t); worldInitFunctions[SelectedWorld](fs); sims.Add(fs); } int origW = width; int origH = height; foreach (var sim in sims) { width = origW; height = origH; sim.SetPresentationSize(ref width, ref height); sim.InitBuffers(); } // output presentation image: if (form.outputImage != null) { form.outputImage.Dispose(); } form.outputImage = new Bitmap(width, height, PixelFormat.Format24bppRgb); SyncObject so = new SyncObject(); so.bmp = form.outputImage; if (dirty || oldWidth != width || oldHeight != height) { SimTime = 0.0; TotalSpawned = 0L; cell = new int[height, width]; vx = new double[height, width]; vy = new double[height, width]; power = new double[height, width]; dirty = false; } else { sims[0].SimTime = SimTime; sims[0].TotalSpawned = TotalSpawned; System.Array.Copy(cell, sims[0].cell, width * height); System.Array.Copy(vx, sims[0].vx, width * height); System.Array.Copy(vy, sims[0].vy, width * height); System.Array.Copy(power, sims[0].power, width * height); } // progress & timer: progress.SyncInterval = ((width * (long)height) > (2L << 20)) ? 30000L : 10000L; progress.Reset(); lock ( sw ) { sw.Reset(); sw.Start(); } // run the simulators: Thread[] pool = new Thread[threads]; for (t = 0; t < threads; t++) { pool[t] = new Thread(new ParameterizedThreadStart(this.SimulationWorker)); } for (t = threads; --t >= 0;) { pool[t].Start(new WorkerThreadInit(sims[t], 8000, 4500.0f, 0.004, 0.004)); } do { Thread.Sleep(2000); bool velocity = false; bool pressure = false; lock ( progress ) { if (!progress.Continue) { break; } if (!progress.NeedsSync()) { continue; } velocity = progress.velocity; pressure = progress.pressure; } // 1. collect data from all workers: int x, y; lock ( cell ) { lock (sims[0].cell) { TotalSpawned = sims[0].TotalSpawned; SimTime = sims[0].SimTime; System.Array.Copy(sims[0].cell, cell, width * height); System.Array.Copy(sims[0].vx, vx, width * height); System.Array.Copy(sims[0].vy, vy, width * height); System.Array.Copy(sims[0].power, power, width * height); } for (t = 1; t < threads; t++) { lock (sims[t].cell) { TotalSpawned += sims[t].TotalSpawned; SimTime += sims[t].SimTime; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { cell[y, x] += sims[t].cell[y, x]; vx[y, x] += sims[t].vx[y, x]; vy[y, x] += sims[t].vy[y, x]; power[y, x] += sims[t].power[y, x]; } } } } } so.simTime = SimTime; so.totalSpawned = TotalSpawned; // 2. visualizations - default (pressure/velocity) and/or custom if (progress.velocity || progress.pressure || progress.custom) { maxV2N = 0.001; double V2N; maxV = 0.0; int n; for (y = 2; y < height - 2; y++) // avoid borders.. { for (x = 2; x < width - 2; x++) { if ((n = cell[y, x]) > 0) { if ((V2N = n * power[y, x]) > maxV2N) { maxV2N = V2N; } double mvx = Math.Abs(vx[y, x] / n); double mvy = Math.Abs(vy[y, x] / n); if (mvx > maxV) { maxV = mvx; } if (mvy > maxV) { maxV = mvy; } } } } int origin = 0; if (progress.velocity) { origin += height; } if (progress.pressure) { origin += height; } if (progress.custom) { origin += height; } if (origin > 0 && origin != form.outputImage.Height) { if (form.outputImage != null) { form.outputImage.Dispose(); } so.bmp = form.outputImage = new Bitmap(width, origin, PixelFormat.Format24bppRgb); } origin = 0; // individual visualizations - velocity if (progress.velocity) { VisualizeVelocity(so, 0, origin); origin += height; } // individual visualizations - pressure if (progress.pressure) { VisualizePressure(so, 0, origin); origin += height; } // individual visualizations - custom routine if (progress.custom) { VisualizeCustom(so, 0, origin, progress.param); origin += height; } progress.Sync(so); } }while (true); // wait for the simulator threads: for (t = 0; t < threads; t++) { pool[t].Join(); pool[t] = null; } long elapsed; lock ( sw ) { sw.Stop(); elapsed = sw.ElapsedMilliseconds; } string msg = string.Format(CultureInfo.InvariantCulture, "{0:f1}s [ {1}x{2}, mt{3}, sim{4:f1}s, spawned{5} ]", 1.0e-3 * elapsed, width, height, threads, SimTime, Util.kmg(TotalSpawned)); form.SetText(msg); Console.WriteLine("Simulation finished: " + msg); form.SetImage((Bitmap)form.outputImage.Clone()); form.StopSimulation(); }