lattice_gas/0000755000175000017500000000000011551377446012372 5ustar peterpeterlattice_gas/model.c0000644000175000017500000001606511546406264013641 0ustar peterpeter// Lattice gas. #include "model.h" int scattering = 0; #ifdef USE_OMP #warning Using OpenMP in compilation: Make sure you remembered to pass -fopenmp to gcc. #include #endif space_t allocate_space(int width, int height) { space_t result; height *= WORDLENGTH; result.width = width; result.height = height; result.state = 0; result.buffer0 = (cell_slice_t*) malloc( sizeof(cell_slice_t) * width * height ); result.buffer1 = (cell_slice_t*) malloc( sizeof(cell_slice_t) * width * height ); memset(result.buffer0, 0, sizeof(cell_slice_t) * width * height); memset(result.buffer1, 0, sizeof(cell_slice_t) * width * height); return result; } uint64_t lfsr; #define LFSR_STEP(x) (((x) >> 1) ^ (uint64_t)((0 - ((x) & (uint64_t)1)) & 0x800000000000000d)) #ifdef COUNT_RANDOM_BITS_FOR_FUN long random_bits_consumed = 0; #endif uint64_t update_random(void) { #ifdef COUNT_RANDOM_BITS_FOR_FUN random_bits_consumed++; #endif lfsr = LFSR_STEP(lfsr); return lfsr; } uint64_t full_random(void) { for (int ii=0; ii<64; ii++) update_random(); return lfsr; } void init_lfsr(void) { lfsr = time(NULL); for (int ii=0; ii<1000; ii++) { update_random(); } } void update(const space_t* restrict const s) { cell_slice_t* restrict const read = s->state ? s->buffer1 : s->buffer0; cell_slice_t* restrict const write = s->state ? s->buffer0 : s->buffer1; #ifdef USE_OMP uint64_t random_seed = full_random(); #pragma omp parallel { uint64_t temp_lfsr = random_seed ^ omp_get_thread_num(); #ifdef COUNT_RANDOM_BITS_FOR_FUN int bits_used_by_this_thread = 64; #endif for (int ii=0; ii<64; ii++) temp_lfsr = LFSR_STEP(temp_lfsr); #pragma omp for #endif for (int yy=1; yyheight-1; yy++) { for (int xx=1; xxwidth-1; xx++) { #ifndef NO_RANDOMNESS #ifndef USE_OMP bitslice random_bits = update_random(); #else bitslice random_bits = temp_lfsr; temp_lfsr = LFSR_STEP(temp_lfsr); #ifdef COUNT_RANDOM_BITS_FOR_FUN bits_used_by_this_thread++; #endif #endif #else bitslice random_bits = 0; #endif cell_slice_t inputs = read[xx + yy * s->width]; // By default, transport. cell_slice_t outputs = inputs; #ifndef HEAD_ON_PASSES_THROUGH // Model head on collisions. const bitslice collision0 = inputs.in[0] & ~inputs.in[1] & ~inputs.in[2] & inputs.in[3] & ~inputs.in[4] & ~inputs.in[5]; const bitslice collision1 = ~inputs.in[0] & inputs.in[1] & ~inputs.in[2] & ~inputs.in[3] & inputs.in[4] & ~inputs.in[5]; const bitslice collision2 = ~inputs.in[0] & ~inputs.in[1] & inputs.in[2] & ~inputs.in[3] & ~inputs.in[4] & inputs.in[5]; outputs.in[0] &= ~collision0; outputs.in[3] &= ~collision0; outputs.in[1] |= collision0 & random_bits; outputs.in[4] |= collision0 & random_bits; outputs.in[2] |= collision0 & ~random_bits; outputs.in[5] |= collision0 & ~random_bits; outputs.in[1] &= ~collision1; outputs.in[4] &= ~collision1; outputs.in[2] |= collision1 & random_bits; outputs.in[5] |= collision1 & random_bits; outputs.in[3] |= collision1 & ~random_bits; outputs.in[0] |= collision1 & ~random_bits; outputs.in[2] &= ~collision2; outputs.in[5] &= ~collision2; outputs.in[3] |= collision2 & random_bits; outputs.in[0] |= collision2 & random_bits; outputs.in[4] |= collision2 & ~random_bits; outputs.in[1] |= collision2 & ~random_bits; #endif // Model three way collisions. const bitslice collision3 = inputs.in[0] & ~inputs.in[1] & inputs.in[2] & ~inputs.in[3] & inputs.in[4] & ~inputs.in[5]; const bitslice collision4 = ~inputs.in[0] & inputs.in[1] & ~inputs.in[2] & inputs.in[3] & ~inputs.in[4] & inputs.in[5]; #ifndef THREE_WAY_RANDOMLY_SCATTERS outputs.in[0] &= ~collision3; outputs.in[2] &= ~collision3; outputs.in[4] &= ~collision3; outputs.in[1] |= collision3; outputs.in[3] |= collision3; outputs.in[5] |= collision3; outputs.in[1] &= ~collision4; outputs.in[3] &= ~collision4; outputs.in[5] &= ~collision4; outputs.in[0] |= collision4; outputs.in[2] |= collision4; outputs.in[4] |= collision4; #else outputs.in[0] &= ~collision3 | random_bits; outputs.in[2] &= ~collision3 | random_bits; outputs.in[4] &= ~collision3 | random_bits; outputs.in[1] |= collision3 & ~random_bits; outputs.in[3] |= collision3 & ~random_bits; outputs.in[5] |= collision3 & ~random_bits; outputs.in[1] &= ~collision4 | random_bits; outputs.in[3] &= ~collision4 | random_bits; outputs.in[5] &= ~collision4 | random_bits; outputs.in[0] |= collision4 & ~random_bits; outputs.in[2] |= collision4 & ~random_bits; outputs.in[4] |= collision4 & ~random_bits; #endif // Push outputs write[xx + (yy+1) * s->width].in[0] = outputs.in[0]; write[xx + (yy+1) * s->width].in[1] = outputs.in[1] << 1; write[xx-1 + (yy+1) * s->width].in[1] |= outputs.in[1] >> 63; write[xx + yy * s->width].in[2] |= outputs.in[2] << 1; write[xx-1 + yy * s->width].in[2] |= outputs.in[2] >> 63; write[xx + (yy-1) * s->width].in[3] = outputs.in[3]; write[xx + (yy-1) * s->width].in[4] |= outputs.in[4] >> 1; write[xx+1 + (yy-1) * s->width].in[4] |= outputs.in[4] << 63; write[xx + yy * s->width].in[5] |= outputs.in[5] >> 1; write[xx+1 + yy * s->width].in[5] = outputs.in[5] << 63; } } #ifdef USE_OMP } #endif #ifndef WIND_TUNNEL_BOUNDARY_CONDITIONS // Enforce periodic boundary conditions: // Top and bottom rows for (int xx=0; xxwidth; xx++) { for (int ii=0; ii<6; ii++) { write[xx + (s->height-2) * s->width].in[ii] ^= write[xx].in[ii]; } for (int ii=0; ii<6; ii++) { write[xx + s->width].in[ii] ^= write[xx + (s->height-1) * s->width].in[ii]; } } // Left and right sides. for (int yy=0; yyheight; yy++) { for (int ii=0; ii<6; ii++) { write[s->width-2 + yy * s->width].in[ii] ^= write[yy * s->width].in[ii]; } for (int ii=0; ii<6; ii++) { write[1 + yy * s->width].in[ii] ^= write[s->width-1 + yy * s->width].in[ii]; } } #else // Wind tunnel boundary conditions! // Right side, random particles. for (int yy=0; yyheight; yy++) { for (int ii=0; ii<6; ii++) { write[s->width-2 + yy * s->width].in[ii] ^= update_random() & update_random() & 1; if (ii == 2) write[s->width-2 + yy * s->width].in[ii] ^= update_random() & 1; } } // Top and bottom rows, source random particles for (int xx=0; xxwidth; xx++) { for (int ii=0; ii<6; ii++) { write[xx + (s->height-2) * s->width].in[ii] = update_random() & update_random(); } for (int ii=0; ii<6; ii++) { write[xx + s->width].in[ii] = update_random() & update_random(); } } #endif memset(read, 0, sizeof(*read) * s->width * s->height); } void time_reverse(const space_t* restrict s) { cell_slice_t* restrict const read = s->state ? s->buffer1 : s->buffer0; for (int yy=1; yyheight-1; yy++) { for (int xx=1; xxwidth-1; xx++) { cell_slice_t inputs = read[xx + yy * s->width]; read[xx + yy * s->width].in[0] = inputs.in[3]; read[xx + yy * s->width].in[1] = inputs.in[4]; read[xx + yy * s->width].in[2] = inputs.in[5]; read[xx + yy * s->width].in[3] = inputs.in[0]; read[xx + yy * s->width].in[4] = inputs.in[1]; read[xx + yy * s->width].in[5] = inputs.in[2]; } } } lattice_gas/example.c0000644000175000017500000006071211551377355014176 0ustar peterpeter#include #include #include #include #include #include #ifdef USE_OMP #warning Using OpenMP in compilation: Make sure you remembered to pass -fopenmp to gcc. #include #endif #include "model.h" int mouse_x = 0, mouse_y = 0, mouse_button_down = 0; int keys_held[64] = {0}; void remove_key( int keys_held[64], int v ) { int ii; for (ii=0; ii<64; ii++) { if (keys_held[ii] == v) keys_held[ii] = 0; } } void add_key( int keys_held[64], int v ) { int ii; remove_key( keys_held, v ); for (ii=0; ii<64; ii++) { if (keys_held[ii] == 0) { keys_held[ii] = v; return; } } } int test_key( int keys_held[64], int v ) { int ii; for (ii=0; ii<64; ii++) { if (keys_held[ii] == v) return 1; } return 0; } #ifdef INTERLACED_RENDER #ifndef INITIAL_INTERLACE_FACTOR int INTERLACED_RENDER_factor = 1; #else int INTERLACED_RENDER_factor = INITIAL_INTERLACE_FACTOR; #endif #endif #ifdef MOUSE_PERTURB #ifndef INITIAL_MOUSE_EFFECT_STRENGTH int mouse_effect_strength = 64; #else int mouse_effect_strength = INITIAL_MOUSE_EFFECT_STRENGTH; #endif #ifndef INITIAL_MOUSE_EFFECT_SIZE int mouse_effect_size = 64; #else int mouse_effect_size = INITIAL_MOUSE_EFFECT_SIZE; #endif int controls_locked = 0; int saved_mouse_x, saved_mouse_y, saved_mouse_button_down; int saved_keys_held[64] = {0}; #endif #ifdef OVERLAY_MOMENTUM #ifndef INITIAL_MOMENTUM_UNIT_SIZE int momentum_unit_size = 32; #else int momentum_unit_size = INITIAL_MOMENTUM_UNIT_SIZE; #endif #ifndef INITIAL_MOMENTUM_VISIBILITY int momentum_visibility = 0; #else int momentum_visibility = INITIAL_MOMENTUM_VISIBILITY; #endif #endif #ifdef PARTICLES_INVISIBLE #ifndef INITIAL_PARTICLE_VISIBILITY int particle_visibility = 1; #else int particle_visibility = INITIAL_PARTICLE_VISIBILITY; #endif #endif int WIDTH, HEIGHT; #define BPP 4 #define DEPTH 32 static void reset_layer(space_t* space, int layer); static inline void setpixel(SDL_Surface *screen, int x, int y, Uint32 colour) { Uint32 *pixmem32; // if (x >= WIDTH) { // printf("%i\n", x - WIDTH); // return; // } #ifdef LOW_PASS if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return; #endif y = y*screen->pitch/BPP; pixmem32 = (Uint32*) screen->pixels + y + x; #ifndef LOW_PASS *pixmem32 = colour; #else *pixmem32 += colour; #endif } static inline void setpixel_bounds_check(SDL_Surface *screen, int x, int y, Uint32 colour) { #ifndef LOW_PASS if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return; #endif setpixel(screen, x, y, colour); } void DrawScreen(SDL_Surface* screen, space_t* space) { if(SDL_MUSTLOCK(screen)) { if(SDL_LockSurface(screen) < 0) return; } #ifdef PARTICLES_INVISIBLE #ifndef LOW_PASS if (!particle_visibility) SDL_FillRect(screen, NULL, SDL_MapRGB( screen->format, 0, 0, 0 )); #endif #endif #ifdef LOW_PASS #ifndef PSYCHEDELIC SDL_FillRect(screen, NULL, SDL_MapRGB( screen->format, 0, 0, 0 )); #else // static int line_to_reset = 0; // line_to_reset += HEIGHT/7 + 1; // line_to_reset %= HEIGHT; // for (int ii=0; iipixels + BPP * WIDTH * line, 0, WIDTH*BPP); // } for (int ii=0; iipixels)[ii] -= 8; ((uint8_t*)screen->pixels)[ii+1] -= 3; ((uint8_t*)screen->pixels)[ii+2] -= 8; ((uint8_t*)screen->pixels)[ii+3] -= 7; // if (((uint8_t*)screen->pixels)[ii] < 50) // ((uint8_t*)screen->pixels)[ii] = 0; } if ( ((uint8_t*)screen->pixels)[0] == 0 ) { for (int ii=0; iipixels)[ii+2] = 0; } //SDL_FillRect(screen, NULL, SDL_MapRGB( screen->format, 0, 0, 0 )); } #endif #endif #ifdef RESET_LAYERS static int layer_reset_timer = 0; static int layer_to_reset = 0; if ( layer_reset_timer++ == RESET_LAYERS ) { reset_layer(space, layer_to_reset++); layer_to_reset %= 6; layer_reset_timer = 0; } #endif const cell_slice_t* restrict const read = space->state ? space->buffer1 : space->buffer0; #ifdef INTERLACED_RENDER static int phase = 0; phase++; phase %= INTERLACED_RENDER_factor; phase %= HEIGHT; #endif int true_yy_limit = space->height-1; if (true_yy_limit-1 > HEIGHT) true_yy_limit = HEIGHT+1; #ifdef PARTICLES_INVISIBLE if (particle_visibility) { #endif #ifdef USE_OMP #pragma omp parallel shared(screen, space, true_yy_limit) { #pragma omp for #endif #ifdef INTERLACED_RENDER for (int yy=1+phase; yywidth-1; xx++) { cell_slice_t values = read[xx + yy * space->width]; int loop_max = WORDLENGTH; if ((xx-1)*64 + WORDLENGTH > WIDTH) { loop_max = (WIDTH - (xx-1)*64); } for (int bit=0; bit>= 8; //sum += sum << 24; //sum += (sum << 16) + (sum << 8); //sum *= 0x010101010101; //sum >>= 56; /* int sum = \ ((uint64_t)(p_values[ 1]&0x80000000)) + \ ((uint64_t)(p_values[ 3]&0x80000000)) + \ ((uint64_t)(p_values[ 5]&0x80000000)) + \ ((uint64_t)(p_values[ 7]&0x80000000)) + \ ((uint64_t)(p_values[ 9]&0x80000000)) + \ ((uint64_t)(p_values[11]&0x80000000));*/ int sum = (values.in[0]>>63) + (values.in[1]>>63) + (values.in[2]>>63) + (values.in[3]>>63) + (values.in[4]>>63) + (values.in[5]>>63); //int sum = (values.in[0]) + (values.in[1]) + (values.in[2]) + (values.in[3]) + (values.in[4]) + (values.in[5]); //int sum = 0; //int sum = ((values.in[0])&1) + ((values.in[1])&1) + ((values.in[2])&1) + ((values.in[3])&1) + ((values.in[4])&1) + ((values.in[5])&1); int xv = xx*WORDLENGTH + bit - 64; #ifndef LOW_PASS uint32_t color = (sum*42); #else uint32_t color = (sum*8); #endif #ifndef COLOR_FUNCTION #define COLOR_FUNCTION color = color << 16 // By default, just red. #endif COLOR_FUNCTION; setpixel(screen, xv, yy - 1, color ); #ifdef LOW_PASS setpixel(screen, xv-1, yy - 1, color ); setpixel(screen, xv+1, yy - 1, color ); setpixel(screen, xv, yy - 2, color ); setpixel(screen, xv, yy, color ); #endif values.in[0] <<= 1; values.in[1] <<= 1; values.in[2] <<= 1; values.in[3] <<= 1; values.in[4] <<= 1; values.in[5] <<= 1; } } } #ifdef USE_OMP } #endif #ifdef PARTICLES_INVISIBLE } #endif #ifdef OVERLAY_MOMENTUM if (momentum_visibility) { double x_momenta[(space->height-2) / momentum_unit_size + 2][((space->width-2)*WORDLENGTH) / momentum_unit_size + 1]; double y_momenta[(space->height-2) / momentum_unit_size + 2][((space->width-2)*WORDLENGTH) / momentum_unit_size + 1]; memset(x_momenta, 0, sizeof(x_momenta)); memset(y_momenta, 0, sizeof(y_momenta)); #define SIN_PI_OVER_4 0.70710678118654746 for (int yy=1; yywidth-1; xx++) { cell_slice_t values = read[xx + yy * space->width]; int loop_max = WORDLENGTH; if ((xx-1)*64 + WORDLENGTH > WIDTH) { loop_max = (WIDTH - (xx-1)*64); } for (int bit=0; bit>= 1; values.in[1] >>= 1; values.in[2] >>= 1; values.in[3] >>= 1; values.in[4] >>= 1; values.in[5] >>= 1; } } } #ifdef DYNAMIC_ARROW_SIZING // Compute the laplacian, and use it to size the arrows. double laplacian[(space->height-2) / momentum_unit_size + 2][((space->width-2)*WORDLENGTH) / momentum_unit_size + 1]; memset(laplacian, 0, sizeof(laplacian)); // Compute the mean laplacian, and drive arrows larger than it bigger, and arrows smaller than it smaller. double mean_laplacian = 0.0; int count = 0; for (int yy=1; yy<(space->height-2) / momentum_unit_size-1; yy++) { for (int xx=1; xx<((space->width-2)*WORDLENGTH) / momentum_unit_size - 1; xx++) { double local_laplacian = fabs(x_momenta[yy][xx+1] - x_momenta[yy][xx]) + fabs(x_momenta[yy][xx-1] - x_momenta[yy][xx]) + fabs(y_momenta[yy+1][xx] - y_momenta[yy][xx]) + fabs(y_momenta[yy-1][xx] - y_momenta[yy][xx]); laplacian[yy][xx] = local_laplacian; mean_laplacian += local_laplacian; // Numerical stability problems for large grids? count++; } } mean_laplacian *= 10; mean_laplacian /= count; #endif for (int yy=0; yy<(space->height-2) / momentum_unit_size + 1; yy++) { for (int xx=0; xx<((space->width-2)*WORDLENGTH) / momentum_unit_size; xx++) { #ifdef DYNAMIC_ARROW_SIZING // Skip cells marked as done. if (laplacian[yy][xx] == -1) continue; #endif double x_momentum = x_momenta[yy][xx]; double y_momentum = y_momenta[yy][xx]; double x_offset = xx * momentum_unit_size + momentum_unit_size/2; double y_offset = yy * momentum_unit_size + momentum_unit_size/2; double norm, c; #ifndef DYNAMIC_ARROW_SIZING norm = sqrt(x_momentum*x_momentum + y_momentum*y_momentum); c = 0.75 / (norm * momentum_unit_size); #else // Note that we can only dynamically make arrows bigger, unless we do more computation to subdivide the momentum sums. if (laplacian[yy][xx] < mean_laplacian && ((xx&1)^1) && ((yy&1)^1) && (xx < ((space->width-2)*WORDLENGTH) / momentum_unit_size - 1) && ( yy < (space->height-2) / momentum_unit_size ) ) { if ((laplacian[yy][xx]+laplacian[yy][xx+1]+laplacian[yy+1][xx]+laplacian[yy+1][xx+1]) < mean_laplacian && ((xx&3) == 0) && ((yy&3) == 0) && (xx < ((space->width-2)*WORDLENGTH) / momentum_unit_size - 2) && ( yy < (space->height-2) / momentum_unit_size - 2 )) { x_momentum = 0; y_momentum = 0; for (int yyy=0; yyy<4; yyy++) { for (int xxx=0; xxx<4; xxx++) { laplacian[yy+yyy][xx+xxx] = -1; x_momentum += x_momenta[yy+yyy][xx+xxx]; y_momentum += y_momenta[yy+yyy][xx+xxx]; } } x_offset += momentum_unit_size/2 + momentum_unit_size; y_offset += momentum_unit_size/2 + momentum_unit_size; norm = sqrt(x_momentum*x_momentum + y_momentum*y_momentum); c = 0.75 / (norm * momentum_unit_size*4); } else { laplacian[yy][xx+1] = -1; laplacian[yy+1][xx] = -1; laplacian[yy+1][xx+1] = -1; x_momentum += x_momenta[yy][xx+1] + x_momenta[yy+1][xx] + x_momenta[yy+1][xx+1]; y_momentum += y_momenta[yy][xx+1] + y_momenta[yy+1][xx] + y_momenta[yy+1][xx+1]; x_offset += momentum_unit_size/2; y_offset += momentum_unit_size/2; norm = sqrt(x_momentum*x_momentum + y_momentum*y_momentum); c = 0.75 / (norm * momentum_unit_size*2); } } else { norm = sqrt(x_momentum*x_momentum + y_momentum*y_momentum); c = 0.75 / (norm * momentum_unit_size); } #endif int sx=0, sy=0; for (int ii=0; iipixels, BPP * WIDTH * HEIGHT); #endif if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); SDL_Flip(screen); } static void reset_layer(space_t* space, int layer) { cell_slice_t* restrict const write = space->state ? space->buffer1 : space->buffer0; for (int yy=1; yyheight-1; yy++) { for (int xx=1; xxwidth-1; xx++) { for (int ii=0; ii<6; ii++) { #ifndef WIND_TUNNEL_BOUNDARY_CONDITIONS #ifndef VACUUM if (layer == -1 || ii == layer) { // This anding and oring is the first few digits of the binary expansion of 1/6th, which is a density I decided on arbitrarily. write[xx + yy * space->width].in[ii] = (full_random() & full_random() & full_random()) | (full_random() & full_random() & full_random() & full_random() & full_random()) | (full_random() & full_random() & full_random() & full_random() & full_random() & full_random() & full_random()); } #endif #else write[xx + yy * space->width].in[ii] = 0; #endif /* if (layer == -1 || ii == layer) { write[xx + yy * space->width].in[ii] = (full_random() & full_random() & full_random()) | (full_random() & full_random() & full_random() & full_random() & full_random()) | (full_random() & full_random() & full_random() & full_random() & full_random() & full_random() & full_random()); } if (ii == 2) write[xx + yy * space->width].in[ii] = full_random() | full_random() | full_random(); */ } } } #ifdef BOX_IN_THE_MIDDLE for (int yy=space->height/3; yy<(2*space->height)/3; yy++) { for (int xx=space->width/3; xx<(2*space->width)/3; xx++) { for (int ii=0; ii<6; ii++) { if (layer == -1 || ii == layer) { write[xx + yy * space->width].in[ii] = -1; //full_random(); } } } } #endif } static void reinit(space_t* space) { space->state = 0; memset(space->buffer0, 0, sizeof(cell_slice_t) * space->width * space->height); memset(space->buffer1, 0, sizeof(cell_slice_t) * space->width * space->height); reset_layer(space, -1); } int main(int argc, char **argv) { SDL_Surface *screen; SDL_Event event; const SDL_VideoInfo *info; struct timeval start_time; struct timeval stop_time; if (SDL_Init(SDL_INIT_VIDEO) < 0 ) return 1; info = SDL_GetVideoInfo(); if (info == NULL) { fprintf(stderr, "Unable to get video info: %s\n", SDL_GetError()); return 1; } WIDTH = info->current_w; HEIGHT = info->current_h; #ifdef DROP_RESOLUTION WIDTH /= DROP_RESOLUTION; HEIGHT /= DROP_RESOLUTION; #endif fprintf(stderr, "Resolution: %ix%i\n", WIDTH, HEIGHT); int blocks_wide = (WIDTH+63)/64 + 2; int blocks_high = (HEIGHT+1)/64 + 1; fprintf(stderr, "Size: %ix%i blocks. (%ix%i active cells, %li in total.)\n", blocks_wide, blocks_high, blocks_wide*64-128, blocks_high*64-2, (long)(blocks_wide*64 - 128) * (long)(blocks_high*64 - 2)); space_t space = allocate_space(blocks_wide, blocks_high); init_lfsr(); reinit(&space); #ifdef BENCHMARK_ONLY fprintf(stderr, "=== Benchmark Only Mode ===\nRecompile without -DBENCHMARK_ONLY=%i to recompile.\n", BENCHMARK_ONLY); gettimeofday(&start_time, NULL); for (int ii=0; iicurrent_w, info->current_h, DEPTH, SDL_FULLSCREEN|SDL_HWSURFACE))) { SDL_Quit(); return 1; } #ifndef MOUSE_PERTURB SDL_ShowCursor(SDL_DISABLE); #endif int continue_running = 1; int total_update_count = 0; int total_frame_count = 0; int rate = 0; int paused = 1; #ifdef INITIAL_RATE rate = INITIAL_RATE; #endif #ifdef INITIAL_PAUSED paused = INITIAL_PAUSED; #endif gettimeofday(&start_time, NULL); while(continue_running) { #ifdef MOUSE_PERTURB if (!controls_locked) { saved_mouse_x = mouse_x; saved_mouse_y = mouse_y; saved_mouse_button_down = mouse_button_down; for (int ii=0; ii<64; ii++) { saved_keys_held[ii] = keys_held[ii]; } } #endif if (! paused) { #ifdef MOUSE_PERTURB int modulus = mouse_effect_strength; int filter_length = 0; while (modulus > 1<>= 1; } #endif for (int ii=0; ii < 1<= WIDTH || y < 0 || y >= HEIGHT) continue; for (int ii=0; ii<6; ii++) { bitslice rb = 1; int jj = filter_length; while (jj--) rb &= update_random(); // Determine the type of command being given. if (key_LEFT) { if (ii == 2) current[x/WORDLENGTH + y * space.width].in[ii] |= (bitslice)rb << (WORDLENGTH - 1 - x%WORDLENGTH); else current[x/WORDLENGTH + y * space.width].in[ii] &= ~ ( (bitslice)rb << (WORDLENGTH - 1 - x%WORDLENGTH) ); } else if (key_RIGHT) { if (ii == 5) current[x/WORDLENGTH + y * space.width].in[ii] |= (bitslice)rb << (WORDLENGTH - 1 - x%WORDLENGTH); else current[x/WORDLENGTH + y * space.width].in[ii] &= ~ ( (bitslice)rb << (WORDLENGTH - 1 - x%WORDLENGTH) ); } else if (key_UP) { if (ii == 3) current[x/WORDLENGTH + y * space.width].in[ii] |= (bitslice)rb << (WORDLENGTH - 1 - x%WORDLENGTH); else current[x/WORDLENGTH + y * space.width].in[ii] &= ~ ( (bitslice)rb << (WORDLENGTH - 1 - x%WORDLENGTH) ); } else if (key_DOWN) { if (ii == 0) current[x/WORDLENGTH + y * space.width].in[ii] |= (bitslice)rb << (WORDLENGTH - 1 - x%WORDLENGTH); else current[x/WORDLENGTH + y * space.width].in[ii] &= ~ ( (bitslice)rb << (WORDLENGTH - 1 - x%WORDLENGTH) ); } else if (key_LSHIFT || key_RSHIFT) { current[x/WORDLENGTH + y * space.width].in[ii] |= (bitslice)rb << (WORDLENGTH - 1 - x%WORDLENGTH); } } } } } #endif } } DrawScreen(screen, &space); total_frame_count++; while(SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: continue_running = 0; break; case SDL_MOUSEBUTTONDOWN: if( event.button.button == SDL_BUTTON_LEFT ) { mouse_button_down = 1; } break; case SDL_MOUSEBUTTONUP: if ( event.button.button == SDL_BUTTON_LEFT ) { mouse_button_down = 0; } break; case SDL_KEYUP: remove_key(keys_held, event.key.keysym.sym); break; case SDL_KEYDOWN: add_key(keys_held, event.key.keysym.sym); if (event.key.keysym.sym == '=') { rate++; } if (event.key.keysym.sym == '-') { rate--; } #ifdef INTERLACED_RENDER if (event.key.keysym.sym == '1') INTERLACED_RENDER_factor /= 2; if (event.key.keysym.sym == '2') INTERLACED_RENDER_factor *= 2; if (INTERLACED_RENDER_factor < 1) INTERLACED_RENDER_factor = 1; if ((test_key(keys_held, SDLK_LCTRL) || test_key(keys_held, SDLK_RCTRL)) && event.key.keysym.sym == '1') { rate = 0; INTERLACED_RENDER_factor = 1; } #endif #ifdef MOUSE_PERTURB if (event.key.keysym.sym == SDLK_DELETE) controls_locked ^= 1; if (event.key.keysym.sym == '6') { if (test_key(keys_held, SDLK_LCTRL) || test_key(keys_held, SDLK_RCTRL)) saved_mouse_button_down ^= 1; else mouse_effect_strength *= 2; } if (event.key.keysym.sym == '7') mouse_effect_strength /= 2; if (mouse_effect_strength < 4) mouse_effect_strength = 4; if (event.key.keysym.sym == '8') { if (test_key(keys_held, SDLK_LCTRL) || test_key(keys_held, SDLK_RCTRL)) mouse_effect_size = 1; else mouse_effect_size /= 2; } if (event.key.keysym.sym == '9') mouse_effect_size *= 2; if (mouse_effect_strength < 1) mouse_effect_strength = 1; #endif #ifdef OVERLAY_MOMENTUM if (event.key.keysym.sym == '3') momentum_unit_size /= 2; if (event.key.keysym.sym == '4') { if (test_key(keys_held, SDLK_LCTRL) || test_key(keys_held, SDLK_RCTRL)) momentum_visibility ^= 1; else momentum_unit_size *= 2; } if ((test_key(keys_held, SDLK_LCTRL) || test_key(keys_held, SDLK_RCTRL)) && event.key.keysym.sym == '3') momentum_unit_size = 0; if (momentum_unit_size < 4) momentum_unit_size = 4; #endif #ifdef PARTICLES_INVISIBLE if (event.key.keysym.sym == '5') particle_visibility ^= 1; #endif if (event.key.keysym.sym == SDLK_SPACE) { paused ^= 1; } if (event.key.keysym.sym == SDLK_RETURN) { time_reverse(&space); } if (event.key.keysym.sym == SDLK_BACKSPACE) { reinit(&space); #ifdef AUTO_EQUILIBRIATE for (int ii=0; ii> 1) << 16;" # Dimmer particles, to let momentum arrows stand out more clearly. #OPTIONS+= -DCOLOR_FUNCTION="color *= 0x010101;" # Maximum contrast mode. #OPTIONS+= -DCOLOR_FUNCTION="color <<= 8;" # Particles are green. #OPTIONS+= -DCOLOR_FUNCTION="color <<= 0;" # Particles are blue. #OPTIONS+= -DCOLOR_FUNCTION="color = (0xff - color) << 16;" # Inverse coloration: Particles are black on an otherwise red background. #OPTIONS+= -DCOLOR_FUNCTION="color = update_random() ^ update_random();" # Add random noise! # Initial settings: #OPTIONS+= -DINITIAL_PAUSED=1 # Default: 1 (paused) #OPTIONS+= -DINITIAL_RATE=0 # Default: 0 #OPTIONS+= -DINITIAL_INTERLACE_FACTOR=2 # Default: 1 #OPTIONS+= -DINITIAL_PARTICLE_VISIBILITY=1 # Default: 1 (visible) #OPTIONS+= -DINITIAL_MOMENTUM_UNIT_SIZE=64 # Default: 256 #OPTIONS+= -DINITIAL_MOMENTUM_VISIBILITY=1 # Default: 0 (visible) #OPTIONS+= -DINITIAL_MOUSE_EFFECT_STRENGTH=8 # Default: 64 (Lower is more powerful.) #OPTIONS+= -DINITIAL_MOUSE_EFFECT_SIZE=64 # Default: 64 # This next option streams video to stdout, suitable to be transcoded in real time. # Try with a command like: ./LatticeGas | ffmpeg -y -f rawvideo -pix_fmt bgra -s YOUR_RESOLUTION_HERE -i - -vcodec libx264 -vpre lossless_ultrafast lattice_gas_lossless.mkv # Be forewarned, the datarate from this option is absolutely obcene. A typically sized screen could easily be well over 200 MiB/s. #OPTIONS+= -DSTREAM_VIDEO_TO_STDOUT EXTRA_CFLAGS= -std=c99 -O3 -ffast-math -Wall all: LatticeGas LatticeGas: example.c model.c model.h Makefile gcc $(CFLAGS) $(EXTRA_CFLAGS) $(OPTIONS) `sdl-config --cflags --libs` example.c model.c -o LatticeGas clean: rm -f LatticeGas lattice_gas/LatticeGas0000755000175000017500000005647611551163361014347 0ustar peterpeterELF>0 @@C@8 @$!@@@@@88@8@@@t;t; >>`>`P 0>0>`0>`TT@T@DDPtd88@8@QtdRtd>>`>`/lib64/ld-linux-x86-64.so.2GNUGNU:Nu~Kc+:     @ |CEqX8 "h@[PzGPC`4@`;@`@`4 @:6@libSDL-1.2.so.0__gmon_start___Jv_RegisterClasses_init_finiSDL_LockSurfaceSDL_MapRGBSDL_FillRectSDL_UnlockSurfaceSDL_FlipSDL_InitSDL_GetVideoInfoSDL_SetVideoModeSDL_PollEventSDL_QuitSDL_GetErrorlibc.so.6time__stack_chk_failmemset__fprintf_chkmallocstderrgettimeofday__libc_start_main_edata__bss_start_endGLIBC_2.4GLIBC_2.3.4GLIBC_2.2.5ii Lti Vui b?`@`@`@`@`@` @`(@`0@` 8@` @@` H@` P@` X@``@`h@`p@`x@`@`@`Hs],H55 %5 @%5 h%5 h%5 h%5 h%5 h%5 h%5 h%5 hp%5 h`%5 h P%5 h @%5 h 0%5 h %5 h %5 h%z5 h%r5 h%j5 h1I^HHPTI5@H5@HP@HHy4 HtHÐUHSH=85 uK >`H25 H>`HHH9s$fDHH 5 >`H4 H9r4 H[fff.UH=/2 HtHt(>`Ð1@HH=t94uHH=uf1@HH=t;4uHH=uf1H@t u7Ð1@HH=t94uff1Dffffff.UHAWAVAUATSHHHudH%(HE1(u@tHX=3 u!H{111gH߉1;=]3 HUz LBLE5 +3 55 LEA@D@9DlDFDMlp5 DlADzE94HUAEGDEDC5 EAADHcHRHHUE9LJ(LB HzHrHJHA@CA@EMcDXAHHIE1HHC IIAI?I?HEIHI?HEIHI?EMMI?EMMI?GA*EADHE9|HUPAD9 1 AD9l=4 uo{(u@tH3HLEdL3%(He[A\A]A^A_AE)AEEsHEH@HELE $1 1H`AAPHHELcILeID$LHH)L|$H)Lt$IIL1LLlHE 0 3 %s(c(DžxHXẢtpDxtE@EAUD|xUHcHRHHULR(LJ LBHzHrHt9UNE@|Dm1 'AALcHEL]IHE@D)ʃAHHH*LIH*LIHH*HHL]YYNHE\H*LC,߃IL]Xf(YYXH*HXH9MAX XH*A f(\XA4pEE@Pm@;UxDlD9xJHXDHEpVHUfEWDf&1Dc&DIAPLc1LMHc*LȉEA<ƉfA(f(AYYXfA(ÍD*QY^1*1fA/f(f(E1f(AYfA(Yf.f(YYXAX,,xGxC;0 };;/ }3KDYAHLcHcLL[ A H- @AA*f/wAYD,ED*E1*@EE)EA*1f(YAYD*fD(AYDYf(\YX,хxUfA(XYX,Ʌx<;2/ }4; / },DkHcADiAHLk HcHADXYX,Ѕx\fA(\YX,ȅxC;. };; . }3DkHcADiAHLk HcHAD + D9AE9EAP9ArV9IH`fU҉U ~+ fff.AWAVAUATUSHhDoH|$PEHGHD$XHD$PpD$L@D$H{H$rHD$hI`HD$VHD$LHD$ BHD$(8HD$0.I&IIM!HM!HD$8I!HD$@\$LHL$H#L$H#L$ L#l$8\$HL#l$@H#L$(H#L$0HcI!HD$XH[H\$H#$HL!H L H HT$PD$LD$HHH@HHD$XHD$@sHD$8iHD$0_IWHD$(MHD$ CHD$9HD$/HD$%IIM!IM!HHI!H$I!HT$ H#T$(H#T$L#,$H#T$HL$0H#L$8H#T$I!HD$@L!H L HPHT$PD$LD$HHH@HHD$XHD$@HD$8yHD$0oIgHD$(]HD$ SHD$IHD$?HD$5I-IM!"IM!HHI!H$I!HT$ H#T$(H#T$L#,$H#T$HL$0H#L$8H#T$I!HD$@L!H L HPHT$PD$LD$HHH@HHD$XHD$@HD$8HD$0IwHD$(mHD$ cHD$YHD$OHD$EI=IM!2IM!'HHI!H$I!HT$ H#T$(H#T$L#,$H#T$HL$0H#L$8H#T$I!HD$@L!H L HPHT$PD$LD$HHH@HHD$XHD$@HD$8HD$0IHD$(}HD$ sHD$iHD$_HD$UIMIM!BIM!7H/HI!$H$I!HT$ H#T$(H#T$L#,$H#T$HL$0H#L$8H#T$I!HD$@L!H L HP HT$PD$LD$HHH@HHD$XHD$@HD$8HD$0IHD$(HD$ HD$yHD$oHD$eI]IM!RIM!GH?HI!4H$I!(HT$ H#T$(H#T$L#,$H#T$HL$0H#L$8H#T$D$HI!HD$@L!H L HP(HT$PC9D$HSrD$LF9D$L&VUUU))9HD$P0D6)DAHcD)L@IHH,@HHl$Xf9}FHHH@H@H@H@ H@(H09|ƃL9|Hh[]A\A]A^A_HT$PHRHT$X#f.AW AVAUATUSH]¸99HH HD@6@H="$ 1 & D~& a& @H=# ?W& ƉADfADhADHcЉ$1HT$xIcHT$xHT$xHT$6@H$DHHc$Hc$1H$DŽ$HHk0Hc$Hc$1H$HHk0gH$s{ HH$ H$1EDŽ$DŽ$DŽ$D$tDŽ$=# $fo" " f# fo" $ " f# fo" $ ~" f# fo" $ f# fo" f# fo" f# fo" f# fo" f# fo" f# fo" f# fo" f# fo" f# fo" f# fo" f# fo" f# fo" f# $ H! 1ۉ$$D$p$T$p9|$p$ID$lH$ $$H$1HH= B`uA1f.HH= B`uD$P1HH= B`uD$X1HH= B`uD$d1HH=r B`0uD$h1HH=t B`/uD$h=J"  " B" $ 9ʉL$LDd$`\$\Hl$8AAA9i@! D=! AD@>;! L$LF|9)E D;=! ¹?D|$HDt$TD|$\T$DDt$`A1Ѓ?))L$@@AHDfH!ŃuEHDtXAD$HL$@Hc$D$DHHHH@HHD$8H!A<Af.t$P\AuD|$HD$DD$L$@HT$8Dt$THDHH@HH \( fAA9D$L9T$Ly\$\D$lD$p9D$lD$tH$H$1$D$H$H$D$H$1H$H+$H$H+$H=G Hi@BHк7@H*D$8YsL$tH= @7@1W$H= h7@18HcL$tH= 7@HL$x1*L$tH= f(7@L$YT$ ^D$8*$T$ H=d 7@Y^D$8H*D$xL$H=2 8@Y^D$8lG1H[]A\A]A^A_L$XtxA8D$HL$@$HT$8D$DHHH@HH \BDD$HL$@$HT$8D$DHHH@HH \ T$dtVED$HL$@$HT$8D$DHHH@HH Dt$T AA9D$hD$HL$@Ic$D$DHHH@HHD$8H ^H$E1D$P-D$XOD$drD$h$< $88@$A`$=-1>2"   1HH=%A`2u16<7   89t3-41DHH=A`2u3t =b  V 5  uH$$umHc$Hc$1H$DŽ$HHk0PHc$Hc$1H$HHk0)H$T$0u5* ADDDŽ$$ $ $u $k $1;A`u ǀA`HH=ui    f1HH=A`1u  1 HH=tiA`2u5  A[ DA5H=a H6@16v'f1A`1tHH=u% .5G  " E1 f1HH=XA`1uB$5 1 HH=t0A`2u5 i \ f1A`1tHH=u%6 %' 1 HH=tA`2u hf1A`1tHH=u  5HQ H HHHH!H1H. DH! 1H DHHHH!H1ȃ@uH fDAWAVAUATUSGHGHD$WD?AT$AODL$D$DD|$A׃HcH RHHL$HiHyHqHY H(AЃHH@HHD$LLhL@LHLX(L` L(DLeLH0LH0L H0LH0H09T$AD9t$~ D$E[]A\A]A^A_HOHL$@AWAVAUATUSH`_oHGHWHD$8l$PHT$ ?H D$0l$TA|$,|$ADL$DD|$0T$0L$HAT$LD|$4u|$,Hl$ |$HʉA׍qHcH IHcH4vHHL HHt5HL$ȍJHt$HcHcH4vH IHcHHRHHt5HHLIH(Ht$sHcHT(LL$HcH[HL$H4vHT$HHH\ HLVH H\$Ht$LT$fDHƒI HHL!H1ЋT$4T$HcHRHHT$8LB LJH*HzLR(LZMLIIHLIMH!I!HHMH!HT$HLL!IIL!H#T$I!L|$L!L!IL!M!M Lt$L!IIL!L!III!Lt$IL|$IILt$III!L!L!L II!IL|$L4$II!LL L!H#T$H#T$L \$L#\$L D$L#D$H#l$L D$L!MI I!L#l$IIL H M!L!L#$M!Ld$ML M II I M!M L$M!M!L|$ I!ˋL$0L$M HcH IHI,Hl$K $LL$Ll$I?L|$HMK Hl$M !LL$I MH#|$I?HL$M I0I0HD$0H H HT$L!HD$0HD$0H:H|$LHI?H LH0L I?HH0H ULl$MH0I0L|$HL$9t$DDT$,H|$Hl$LL$DT$pD$0Dl$LD9l$T~Dt$HDt$DEH L$HT$PL$,\$PLl$ D$ʃLl$\$,T$ЋT$HHcH IHLHcLQLILAHi H(L[HL$HcL$,ILL$LT$MIC MsMcH IHD$HLMkHA(HyHqHYLy HD$IC(HD$HD$T$LL$ LT$HcHRHM1LL$LT$HPI1HPLL$I1HPI1I0HP H1UH0HP(H0I1II0H1H0II0H1H0IUI0H1H0I$I0H1H0LT$LL$D$ILT$I1I0IHD$0I1I0HD$0HD$0HD$0I0T$,9T$LT$LL$ T$HT$PT$,HcD$,E1Lt$ 11111ɃD$Dl$HHcH@Lt$HRLt$Lt$HLt$MHHT$ Lz LbLZLRH(HT$T$,L|$HcHRHL @Dl$,D|$EGl=McO<McOlmIO<9IO1<)L|$MnM1,$IIMoL|$M1+IMoL|$M1*IMo L|$M1/L|$Mo(L|$M1/IL, M1l 0HLlM1l8HLl2M1l1@HLl:M1l9HHLl* D$M1l)PHNl(HD$O1lXIDl$L|$HD$HD$HD$HD$D9l$PDt$,Dt$HHcT$PHcD$H1H|$8H`[]HA\A]A^A_H@HoHOHwHL$8l$PHt$ D?|$,|$H,f.H1}1H fHHHH!H1ȁuHt HHcH\$Ld$H@AHl$AHLl$IcHLt$HL|$H8AHHIHIL1HL1L}LuHEDeDmH\$Hl$Ld$Ll$ Lt$(L|$0H8Ðfffff.Hl$Ld$H-K L%D Ll$Lt$L|$H\$H8L)AIHIHt1@LLDAHH9rH\$Hl$Ld$Ll$ Lt$(L|$0H8Ð\$L$@T$ÐUHSHH Ht>`DHHHuH[ÐHHUnable to get video info: %s Resolution: %ix%i Size: %ix%i blocks. (%ix%i active cells, %li in total.) Run time: %.2f seconds Updates completed: %i Frames completed: %i Cell updates completed: %lu Average updates per second: %.2f Average frames per second: %.2f Average cell updates per second: %.2f million L&@~(@](@@(@#(@#@#@#@#@#@(@;f?;f??ư>.A;` H0` 0XppzRx .4OL1$d0UAC L4hBBB B(A0A8DD4@BGB B(A0A8G+:,,BBB B(A0A8K4\BBB B(A0A8DCID$QO^@Cp$hQ_@F06@ @ 6@@oP@@@ n ?`0@@0 o@oo@0>` @ @. @> @N @^ @n @~ @ @ @ @ @ @ @ @ @ @ @@@ GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3,06@\MY06@C6@(06@C6@wX:UX@% .: ; ' @ 4: ; I$ > iK ../../../src/libgcc/../gcc/config/i386crtfastmath.c 06@(,Z/build/buildd/gcc-4.4-4.4.3/build/x86_64-linux-gnu/libgccmxcsrunsigned intGNU C 4.4.3../../../src/libgcc/../gcc/config/i386/crtfastmath.cset_fast_math.symtab.strtab.shstrtab.interp.note.ABI-tag.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.text.fini.rodata.eh_frame_hdr.eh_frame.ctors.dtors.jcr.dynamic.got.got.plt.data.bss.comment.debug_aranges.debug_info.debug_abbrev.debug_line.debug_str8@8#T@T 1t@t$H@DoP@P<N @V@n^o@6ko@@z@00@0  @  @ 00 @0 X+6@66@6(8@8H9@H9,>`>>`>(>`(>0>`0>?`??`?@`@$@`@ 0@#@0 A`gAA'Am30BB>Lp #: `X8@T@t@@P@@@@ @ @ 0@ @ @0 @6@6@8@H9@>`>`(>`0>`?`?`@`@` \ @>`*>`8(>`E @[@`j@`x @>`p;@(>`P6@(C`@@$C`06@?`&=`7=`J0>`S @`^ @1g{5@0 @@` +@:HC`  `+@6@$8Wiw@`0C`6@4@IP @O@`@`A`4C`)2,@9@`A@`Z@`g C`{ >`5@@`8C`@` @UB` B`N@`b,C`mv@`@`4@ @.P@ @call_gmon_startcrtstuff.c__CTOR_LIST____DTOR_LIST____JCR_LIST____do_global_dtors_auxcompleted.7382dtor_idx.7384frame_dummy__CTOR_END____FRAME_END____JCR_END____do_global_ctors_auxexample.cphase.7880T.106hits_count.8338model.ccrtfastmath.cset_fast_math_GLOBAL_OFFSET_TABLE___init_array_end__init_array_start_DYNAMICdata_starttest_keymemset@@GLIBC_2.2.5__libc_csu_fini_startmouse_effect_strengthfull_random__fprintf_chk@@GLIBC_2.3.4lfsr__gmon_start___Jv_RegisterClassestime_reversegettimeofday@@GLIBC_2.2.5_finimalloc@@GLIBC_2.2.5__libc_start_main@@GLIBC_2.2.5SDL_UnlockSurfaceSDL_PollEventSDL_LockSurfacemouse_yHEIGHTSDL_FillRectSDL_SetVideoMode_IO_stdin_usedinit_lfsradd_key__data_startSDL_MapRGBSDL_GetVideoInfomomentum_unit_sizekeys_heldsaved_mouse_xSDL_Initupdatemouse_xINTERLACED_RENDER_factor__dso_handlemomentum_visibility__DTOR_END____libc_csu_init__bss_startsaved_mouse_y__stack_chk_fail@@GLIBC_2.4mouse_effect_sizeDrawScreencontrols_lockedWIDTHupdate_randomsaved_mouse_button_downmouse_button_down_endsaved_keys_heldparticle_visibilityscatteringSDL_FlipSDL_Quitstderr@@GLIBC_2.2.5SDL_GetError_edataallocate_spaceremove_keytime@@GLIBC_2.2.5main_initlattice_gas/README0000644000175000017500000000152311551377446013253 0ustar peterpeter *** THIS FILE IS IN PROGRESS! I'm only pushing it incomplete because a bloke who wants to download it is about to hop on a plane, and would like to be able to read it on his five hour plane flight back. *** Check the Makefile to see switchable features. Controls: space -- Pause and unpause. -/+ -- Decrease and increase the number of updates between rerenders. 1/2 -- Decrease and increase the interlacing factor. Control+1 -- Set the interlacing factor and number of updates per rerender both to one. 3/4 -- Decrease and increase the momentum arrow sizing. Control+3 -- Set the momentum arrow sizing to the finest pitch. Control+4 -- Toggle momentum arrows. 5 -- Toggle particle visibility. 6/7 -- Decrease and increase mouse effect strength. Control+6 -- If mouse controls are saved. Backspace -- Restart. lattice_gas/model.h0000644000175000017500000000211511551162671013632 0ustar peterpeter// Lattice gas. #ifndef _LATTICE_GAS_HEADER #define _LATTICE_GAS_HEADER #include #include #include #include #include #define WORDLENGTH 64 typedef uint64_t bitslice; typedef struct { bitslice in[6]; } cell_slice_t; typedef struct { int width; int height; int state; cell_slice_t* buffer0; cell_slice_t* buffer1; } space_t; space_t allocate_space(int width, int height); void update(const space_t* restrict s); void time_reverse(const space_t* restrict s); void init_lfsr(void); uint64_t update_random(void); uint64_t full_random(void); extern int scattering; #ifdef COUNT_RANDOM_BITS_FOR_FUN extern long random_bits_consumed; #endif // This little block of logic is here as apposed to in example.c, because it affects both example.c and model.c #ifdef PSYCHEDELIC #warning Compiling in psychedelic mode. #define LOW_PASS #define BOX_IN_THE_MIDDLE #define INITIAL_INTERLACE_FACTOR 1 #define INITIAL_PAUSED 0 #define INITIAL_RATE 4 #define RESET_LAYERS 500 #undef OVERLAY_MOMENTUM #undef WIND_TUNNEL_BOUNDARY_CONDITIONS #endif #endif