public FastBitmapAccess(Bitmap b, Parameters p) { this.b = b; // Set up states su = new State(p); sv = new State(p); }
// Initialise the states with user-defined initial u0,v0 public void Initialise(State s, Parameters p, int a) { // a = 0 refers to species u // a = 1 refers to species v if (a == 0) for (int i = 0; i < p.N; i++) for (int j = 0; j < p.N; j++) s.U[i, j] = p.U0; else if (a == 1) for (int i = 0; i < p.N; i++) for (int j = 0; j < p.N; j++) s.U[i, j] = p.V0; }
public void ManipulateImage(State s, int scale) { int k,l,m; int shades = 3; // Number of colour shades desired //Lock Image BitmapData data = b.LockBits(new Rectangle(Point.Empty, b.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); byte* ptr = (byte*)(data.Scan0); //access the bits of the bitmap for (int i = 0; i < data.Height; i++) { for (int j = 0; j < data.Width; j++) { // The scale variable just designates how many pixels in a bitmap // correspond to one element in the state array k = (int)(double)(i / scale); l = (int)(double)(j / scale); // Code if different shades are desired for (m = 0; m < 11; m++) { if ((int)s.U[k, l] == m) { // Two different colouring schemes // This one in use, not commented, basically assigns // black to state = 0 and white to state = 10 // then scales using the number of shades desired by the "shades" variable // 255-255-255 = white // 0-0-0 = black ptr[0] = (byte)((m * 255) / shades); // Blue ptr[1] = (byte)((m * 255) / shades); // Green ptr[2] = (byte)((m * 255) / shades); // Red //ptr[0] = (byte)(255 - ((m * 255) / shades)); // Blue //ptr[1] = (byte)(255 - ((m * 255) / shades)); // Green //ptr[2] = (byte)(255 - ((m * 255) / shades)); // Red } } ptr += 3;//move pointer on 3 bytes as each pixel = 24 bits = 3 bytes } //after we go through a row move on the extra piece ptr += data.Stride - data.Width * 3; } b.UnlockBits(data); }
// Calculate average of states u and v public double[] Average(State su, State sv) { double[] avgs = new double[2]; double sumu = 0.0; double sumv = 0.0; for (int i = 0; i < p.N; i++) { for (int j = 0; j < p.N; j++) { sumu += su.U[i, j]; sumv += sv.U[i, j]; } } avgs[0] = sumu / (p.N * p.N); avgs[1] = sumv / (p.N * p.N); return avgs; }
public void InitialiseStates(State su, State sv) { this.su = su; this.sv = sv; }
// Truncate a passed in state (for initial random configurations) public void TruncateGeneral(State s) { float prob = 0; int trunc = 0; for (i = 0; i < p.N; i++) { for (j = 0; j < p.N; j++) { trunc = (int)(Math.Floor(s.U[i, j])); prob = (float)(s.U[i, j]) - trunc; if (rand.NextDouble() <= prob) s.U[i, j] = trunc + 1; else s.U[i, j] = trunc; } } }
// Perform one iteration public double[] Iterate(State su, State sv) { Diffusion(su, Ru); Diffusion(sv, Rv); Reaction(su, sv); Truncate(su); Truncate(sv); return Average(su, sv); }
// Reaction rule private void Reaction(State su, State sv) { f = new double[p.N, p.N]; g = new double[p.N, p.N]; // Calculate f[i,j], g[i,j] // and u,v before truncation for (i = 0; i < p.N; i++) { for (j = 0; j < p.N; j++) { f[i, j] = p.A - ((p.B + 1) * su.U[i, j]) + (su.U[i, j] * su.U[i, j] * sv.U[i, j]); g[i, j] = p.B * su.U[i, j] - (su.U[i, j] * su.U[i, j] * sv.U[i, j]); su.Utemp[i, j] = (float)(normu * su.Vsum[i, j] + p.Step * f[i, j]); sv.Utemp[i, j] = (float)(normv * sv.Vsum[i, j] + p.Step * g[i, j]); } } }
// Truncate the results using a probablistic rule private void Truncate(State s) { float prob = 0; // Probability int trunc = 0; // Truncated result for (i = 0; i < p.N; i++) { for (j = 0; j < p.N; j++) { trunc = (int)(Math.Floor(s.Utemp[i, j])); prob = (float)(s.Utemp[i, j]) - trunc; if (rand.NextDouble() <= prob) s.U[i, j] = trunc + 1; else s.U[i, j] = trunc; } } }
// Diffusion process private void Diffusion(State s, int R) { // Initialise to zero for (i = 0; i < p.N; i++) for (j = 0; j < p.N; j++) s.Hsum[i, j] = s.Vsum[i, j] = 0.0; // Diffusion along horizontal direction for (i = 0; i < p.N; i++) { // Needed to count the centre cell s.Hsum[i, R] = s.U[i, R]; // Horizontal local average of cells (R, R +/- j) for (j = 1; j <= R; j++) s.Hsum[i, R] += s.U[i, R + j] + s.U[i, R - j]; // Horizontal sum with periodic BCs applied by modulus operator for (k = R; k < p.N; k++) s.Hsum[i, (k + 1) % p.N] = s.Hsum[i, k] + s.U[i, (k + (R + 1)) % p.N] - s.U[i, (k - R) % p.N]; } // Needed because the above horizontal code sum doesn't "wrap around" for species v // This doesn't affect species u. It only corrects species v for Rv = 2. for (i = 0; i < p.N; i++) s.Hsum[i, 1] = s.Hsum[i, 0] + s.U[i, (p.N + (R + 1)) % p.N] - s.U[i, (p.N - R) % p.N]; // Diffusion along vertical direction for (i = 0; i < p.N; i++) { // Needed to count the centre cell s.Vsum[R, i] = s.Hsum[R, i]; // Vertical local average of cells (R, R +/- j) for (j = 1; j <= R; j++) s.Vsum[R, i] += s.Hsum[R + j, i] + s.Hsum[R - j, i]; // Vertical sum with periodic BCs applied by modulus operator for (k = R; k < p.N; k++) s.Vsum[(k + 1) % p.N, i] = s.Vsum[k, i] + s.Hsum[(k + (R + 1)) % p.N, i] - s.Hsum[(k - R) % p.N, i]; } // Needed because the above vertical code sum doesn't "wrap around" for species v // This doesn't affect species u. It only corrects species v for Rv = 2. for (i = 0; i < p.N; i++) s.Vsum[1, i] = s.Vsum[0, i] + s.Hsum[(p.N + (R + 1)) % p.N, i] - s.Hsum[(p.N - R) % p.N, i]; }
private void parametersToolStripMenuItem_Click(object sender, EventArgs e) { btStop_Click(sender, e); // Stop everything when user opens parameter window frmParameterBox frmp = new frmParameterBox(); // Save current parameter values frmp.Pdata.Psetname = p.Psetname; frmp.Pdata.Ru = p.Ru; frmp.Pdata.Rv = p.Rv; frmp.Pdata.A = p.A; frmp.Pdata.B = p.B; frmp.Pdata.U0 = p.U0; frmp.Pdata.V0 = p.V0; frmp.Pdata.Step = p.Step; frmp.Pdata.N = p.N; frmp.Pdata.Maxtime = p.Maxtime; // Save changed values // This updates quite a lot of things DialogResult d = frmp.ShowDialog(); if (d == DialogResult.OK) { // Assign user-defined parameters p.Psetname = frmp.Pdata.Psetname; p.Ru = frmp.Pdata.Ru; p.Rv = frmp.Pdata.Rv; p.U0 = frmp.Pdata.U0; p.V0 = frmp.Pdata.V0; p.A = frmp.Pdata.A; p.B = frmp.Pdata.B; p.Step = frmp.Pdata.Step; p.N = frmp.Pdata.N; p.Maxtime = frmp.Pdata.Maxtime; tbTime.Text = "0.00"; btJump.Enabled = true; // Create new state objects su = new State(p); sv = new State(p); // If user changes parameters, update the states & display su.Initialise(su, p, 0); sv.Initialise(sv, p, 1); // Truncatate states probabilistically if using random initial conditions rules.Initialise(p); rules.TruncateGeneral(su); rules.TruncateGeneral(sv); Display(su, sv); // Reinitialise imaging if parameters are changed bu = new Bitmap(bitmapsize, bitmapsize); bv = new Bitmap(bitmapsize, bitmapsize); pictBoxu.Image = bu; pictBoxv.Image = bv; fu = new FastBitmapAccess(bu, p); fv = new FastBitmapAccess(bv, p); DisplayFull(fu, su); DisplayFull(fv, sv); pictBoxu.Refresh(); pictBoxv.Refresh(); // Refresh picture box // Update and display diffusion coefficients diffu = p.Ru * (p.Ru + 1) * p.Step; diffu /= 6; diffv = p.Rv * (p.Rv + 1) * p.Step; diffv /= 6; tbDiffu.Text = Convert.ToString(diffu); tbDiffv.Text = Convert.ToString(diffv); twu.Close(); twv.Close(); // Create directories for averages pathpset[0] = pathpics + "\\" + p.Psetname; pathpset[1] = pathpics + "\\" + p.Psetname; Directory.CreateDirectory(pathpset[0]); Directory.CreateDirectory(pathpset[1]); twu = File.CreateText(string.Format("{0}\\Average_u.csv", pathpset[0])); twv = File.CreateText(string.Format("{0}\\Average_v.csv", pathpset[1])); // Create directories for images pathpset[0] += "\\species_u\\"; pathpset[1] += "\\species_v\\"; Directory.CreateDirectory(pathpset[0]); Directory.CreateDirectory(pathpset[1]); } else if (d == DialogResult.Cancel) { frmp.Close(); } }
private void MACA_Load(object sender, EventArgs e) { frmParameterBox frmp = new frmParameterBox(); DialogResult d = frmp.ShowDialog(); if (d == DialogResult.OK) { // Assign user-defined parameters p.Psetname = frmp.Pdata.Psetname; p.Ru = frmp.Pdata.Ru; p.Rv = frmp.Pdata.Rv; p.U0 = frmp.Pdata.U0; p.V0 = frmp.Pdata.V0; p.A = frmp.Pdata.A; p.B = frmp.Pdata.B; p.Step = frmp.Pdata.Step; p.N = frmp.Pdata.N; p.Maxtime = frmp.Pdata.Maxtime; } // Maximise the main window as default this.WindowState = FormWindowState.Maximized; // Initialise states u, v with parameters p and display them su = new State(p); sv = new State(p); su.Initialise(su, p, 0); sv.Initialise(sv, p, 1); // Truncatate states probabilistically if using random initial conditions rules.Initialise(p); rules.TruncateGeneral(su); rules.TruncateGeneral(sv); Display(su, sv); // Initial imaging bu = new Bitmap(bitmapsize, bitmapsize); // New image of desired size (user specified) bv = new Bitmap(bitmapsize, bitmapsize); // It's scaled acording to the size of p.N pictBoxu.Image = bu; // Assign image to picturebox pictBoxv.Image = bv; fu = new FastBitmapAccess(bu, p); fv = new FastBitmapAccess(bv, p); try { // Update display DisplayFull(fu, su); DisplayFull(fv, sv); pictBoxu.Refresh(); pictBoxv.Refresh(); } catch (Exception ex) { MessageBox.Show(ex.Message); this.Close(); } // Update and display diffusion coefficients diffu = p.Ru * (p.Ru + 1) * p.Step; diffu /= 6; diffv = p.Rv * (p.Rv + 1) * p.Step; diffv /= 6; tbDiffu.Text = Convert.ToString(diffu); tbDiffv.Text = Convert.ToString(diffv); // Create directories for images // if (p.Psetname == null) // p.Psetname = "Basic Configuration"; // if user hits "cancel" upon opening // Create the directory \p.Psetname\ & add the average_u,v.csv files to ti pathpset[0] = pathpics + "\\" + p.Psetname; pathpset[1] = pathpics + "\\" + p.Psetname; Directory.CreateDirectory(pathpset[0]); Directory.CreateDirectory(pathpset[1]); twu = File.CreateText(string.Format("{0}\\Average_u.csv", pathpset[0])); twv = File.CreateText(string.Format("{0}\\Average_v.csv", pathpset[1])); pathpset[0] += "\\species_u\\"; pathpset[1] += "\\species_v\\"; Directory.CreateDirectory(pathpset[0]); Directory.CreateDirectory(pathpset[1]); }
// Display a bitmap of given state s private void DisplayFull(FastBitmapAccess f, State s) { f.ManipulateImage(s, (int)(bitmapsize / p.N)); // Draw }
// Basic display private void Display(State su, State sv) { str = null; str2 = null; // Only display top left corner if (p.N < 6) { for (i = 0; i < p.N; i++) { for (j = 0; j < p.N; j++) { str += Convert.ToString(Math.Round(su.U[i, j], 2)) + " "; str2 += Convert.ToString(Math.Round(sv.U[i, j], 2)) + " "; } str += "\n"; str2 += "\n"; } } else { for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { str += Convert.ToString(Math.Round(su.U[i, j], 2)) + " "; str2 += Convert.ToString(Math.Round(sv.U[i, j], 2)) + " "; } str += "\n"; str2 += "\n"; } } lbtestu.Text = str; lbtestv.Text = str2; }