291 InitWindow(WIN_W, WIN_H,
"2D Ising -- Classic & Nucleation [TAB to switch]");
296 det.
id.assign(NN, -2);
300 std::vector<unsigned char> pixels(NN * 4, 255);
301 Image img = {pixels.data(), N, N, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8};
302 Texture2D tex = LoadTextureFromImage(img);
308 int sweeps_per_frame = 5;
312 enum class Mode { Classic, Nucleation } mode = Mode::Classic;
325 while (!WindowShouldClose()) {
326 if (IsKeyPressed(KEY_SPACE)) paused = !paused;
328 if (IsKeyPressed(KEY_H)) lat.
all_up();
330 if (IsKeyPressed(KEY_UP) && sweeps_per_frame < 20) sweeps_per_frame++;
331 if (IsKeyPressed(KEY_DOWN) && sweeps_per_frame > 1) sweeps_per_frame--;
332 if (IsKeyPressed(KEY_TAB)) {
333 if (mode == Mode::Classic) {
334 mode = Mode::Nucleation;
335 nuc_target = 15; nuc_half = 15;
342 mode = Mode::Classic;
351 if (mode == Mode::Classic) {
352 for (
int s = 0; s < sweeps_per_frame; ++s) lat.
sweep();
354 if (frame % 3 == 0) {
359 int lo = nuc_target - nuc_half;
360 int hi = nuc_target + nuc_half;
361 for (
int s = 0; s < sweeps_per_frame; ++s)
364 if (frame % 3 == 0) {
365 nuc_hist.
push(
static_cast<float>(nuc_size));
367 nuc_stats.
update(
static_cast<real>(nuc_size));
369 nuc_histo.
fill(
static_cast<real>(nuc_size));
374 if (mode == Mode::Classic) {
375 for (
int i = 0; i < NN; ++i) {
376 unsigned char c = (lat.
spins[i] > 0.0) ? 240 : 15;
377 pixels[4*i+0] = pixels[4*i+1] = pixels[4*i+2] = c;
382 for (
int i = 0; i < NN; ++i) {
383 if (lat.
spins[i] > 0.0) {
384 pixels[4*i+0] = 240; pixels[4*i+1] = 240; pixels[4*i+2] = 240;
386 pixels[4*i+0] = 220; pixels[4*i+1] = 50; pixels[4*i+2] = 50;
388 pixels[4*i+0] = 15; pixels[4*i+1] = 15; pixels[4*i+2] = 15;
393 UpdateTexture(tex, pixels.data());
396 ClearBackground({10, 10, 10, 255});
399 {0, 0, (float)N, (
float)N},
400 {0, 0, (float)SIM_SZ, (
float)SIM_SZ},
402 DrawRectangleLines(0, 0, SIM_SZ, SIM_SZ, DARKGRAY);
404 int px = PAN_X, cy = 10;
406 DrawText(
"2D Ising Model", px, cy, 17, WHITE); cy += 22;
409 bool is_nuc = (mode == Mode::Nucleation);
410 Color mode_col = is_nuc ? Color{220,110,50,255} : SKYBLUE;
411 DrawText(is_nuc ?
"NUCLEATION" :
"CLASSIC", px, cy, 13, mode_col);
412 DrawText(
"[TAB]", px + 90, cy, 10, DARKGRAY); cy += 18;
414 DrawText(TextFormat(
"N=%d spd=%d", N, sweeps_per_frame), px, cy, 11, GRAY);
419 float tc_frac =
static_cast<float>((TC - 0.05) / (5.0 - 0.05));
420 T = draw_slider(px, cy, PAN_W, T, 0.05, 5.0, tc_frac,
"T = %.3f", SKYBLUE);
422 DrawText(
"Tc", px +
static_cast<int>(tc_frac * PAN_W) - 5, cy+10, 9, YELLOW);
426 real Fnew = draw_slider(px, cy, PAN_W, lat.
F, 0.0, 0.2, -1.f,
434 DrawText(TextFormat(
"|m| = %.4f", cur_m), px, cy, 13, WHITE);
435 DrawText(TextFormat(
"MF = %.4f", mf_m), px, cy + 16, 13, YELLOW);
436 DrawText(TextFormat(
"E/N = %.4f", eng_hist.
back()), px, cy + 32, 13, LIGHTGRAY);
437 DrawText(TextFormat(
"beta = %.3f", (
float)lat.
beta), px, cy + 48, 13, GRAY);
440 Color pc = (T < TC) ? Color{80,200,80,255} : Color{200,80,80,255};
441 DrawText((T < TC) ?
"ORDERED" :
"DISORDERED", px, cy, 14, pc);
445 draw_graph(mag_hist, px, cy, PAN_W, gh, 0.f, 1.f, GREEN,
"|m|", mf_m);
447 draw_graph(eng_hist, px, cy, PAN_W, gh, -2.2f, 0.f, ORANGE,
"E/spin");
453 float tc_frac =
static_cast<float>((TC - 0.05) / (5.0 - 0.05));
454 T = draw_slider(px, cy, PAN_W, T, 0.05, 5.0, tc_frac,
"T = %.3f", SKYBLUE);
460 real Fnew = draw_slider(px, cy, PAN_W, lat.
F, 0.0, 0.3, -1.f,
461 "F = %.4f (nucleation field)", PINK);
468 int old_tgt = nuc_target;
469 real tgt = draw_slider(px, cy, PAN_W,
static_cast<real>(nuc_target),
470 10, 2000, -1.f,
"Nuc target = %.0f", {220,110,50,255});
471 nuc_target =
static_cast<int>(tgt);
472 if (nuc_target != old_tgt) { nuc_stats.
reset(); mag_stats.
reset(); nuc_histo.
reset(); }
478 int old_hw = nuc_half;
479 real hw = draw_slider(px, cy, PAN_W,
static_cast<real>(nuc_half),
480 5, 200, -1.f,
"Window +/- = %.0f", PURPLE);
481 nuc_half =
static_cast<int>(hw);
482 if (nuc_half != old_hw) { nuc_stats.
reset(); mag_stats.
reset(); nuc_histo.
reset(); }
487 int lo = nuc_target - nuc_half;
488 int hi = nuc_target + nuc_half;
490 DrawText(TextFormat(
"N_nuc = %d", nuc_size), px, cy, 14, {220,80,80,255});
491 DrawText(TextFormat(
"Window [%d, %d]", lo, hi), px, cy + 14, 10, GRAY);
492 DrawText(TextFormat(
"<N> = %.1f sigma = %.1f",
493 (
float)nuc_stats.
mean,
494 (
float)nuc_stats.
std_dev()), px, cy + 26, 11, {220,150,80,255});
495 DrawText(TextFormat(
"<|m|> = %.4f sigma = %.4f",
496 (
float)mag_stats.
mean,
497 (
float)mag_stats.
std_dev()), px, cy + 38, 11, WHITE);
498 DrawText(TextFormat(
"n = %llu sweeps",
499 static_cast<unsigned long long>(nuc_stats.
count)),
500 px, cy + 50, 10, GRAY);
501 DrawText(TextFormat(
"beta = %.3f", (
float)lat.
beta), px, cy + 62, 10, GRAY);
506 float graph_hi =
static_cast<float>(nuc_target + nuc_half + 30);
507 draw_graph(nuc_hist, px, cy, PAN_W, gh, 0.f, graph_hi,
508 {220,80,80,255},
"Nucleus size (red cluster)",
509 static_cast<float>(nuc_target));
513 draw_graph(mag_hist, px, cy, PAN_W, gh, 0.f, 1.f, GREEN,
"|m|");
519 DrawText(
"SPACE pause R rand H up N nucleus", px, cy, 9, DARKGRAY);
520 DrawText(
"UP/DOWN speed TAB mode", px, cy + 12, 9, DARKGRAY);
523 DrawText(
"PAUSED", SIM_SZ/2 - 45, SIM_SZ/2 - 12, 26, {255,100,100,220});