From 3d8bb87be6c157b39351f62f1d85abbde40b85c4 Mon Sep 17 00:00:00 2001 From: Bruno Date: Mon, 30 Dec 2024 08:00:22 +0100 Subject: [PATCH 01/12] Added lbm example. --- examples/lbm/.gitignore | 0 examples/lbm/cell.v | 169 ++++++++++++++ examples/lbm/colormap.v | 48 ++++ examples/lbm/lattice.v | 278 +++++++++++++++++++++++ examples/lbm/main.v | 330 ++++++++++++++++++++++++++++ examples/lbm/profiles/asymetric.png | Bin 0 -> 5794 bytes examples/lbm/profiles/barrier.png | Bin 0 -> 5271 bytes examples/lbm/profiles/circle.png | Bin 0 -> 4934 bytes examples/lbm/profiles/septum.png | Bin 0 -> 6904 bytes examples/lbm/profiles/test.png | Bin 0 -> 6676 bytes examples/lbm/readme.md | 32 +++ examples/lbm/v.mod | 7 + 12 files changed, 864 insertions(+) create mode 100644 examples/lbm/.gitignore create mode 100644 examples/lbm/cell.v create mode 100644 examples/lbm/colormap.v create mode 100644 examples/lbm/lattice.v create mode 100644 examples/lbm/main.v create mode 100644 examples/lbm/profiles/asymetric.png create mode 100644 examples/lbm/profiles/barrier.png create mode 100644 examples/lbm/profiles/circle.png create mode 100644 examples/lbm/profiles/septum.png create mode 100644 examples/lbm/profiles/test.png create mode 100644 examples/lbm/readme.md create mode 100644 examples/lbm/v.mod diff --git a/examples/lbm/.gitignore b/examples/lbm/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/examples/lbm/cell.v b/examples/lbm/cell.v new file mode 100644 index 00000000..3843675e --- /dev/null +++ b/examples/lbm/cell.v @@ -0,0 +1,169 @@ +module main + +import math +import rand + +// vfmt off +// +// This file contains Code and data structures for a Lattice-Boltzmann-Method (LBM) +// fluid flow simulation. The simulation is 2 Dimension, with 9 possible directions (D2Q9) +// +// 8 1 2 +// +// 7 0 3 +// +// 6 5 4 + +// Vi is an enum for direction vector of D2Q9 Lattice. +pub enum Vi as int { + center =0 + north = 1 + north_east =2 + east=3 + south_east=4 + south= 5 + south_west = 6 + west=7 + north_west = 8 +} + +// opposite returns vector of opposite direction. Yes Enum can have methods in V. +// Warning: This array must be coherent with Vi enum order ! +fn (v Vi) opposite() Vi { + opp :=[Vi.center, Vi.south, Vi.south_west, + Vi.west, Vi.north_west, Vi.north, + Vi.north_east, Vi.east, Vi.south_east] + + return opp[int(v)] +} + +//Array defined here in order to loop over a Vi enum. +// Warning: This array must be coherent with Vi enum order ! +const vi = [Vi.center, Vi.north, Vi.north_east, + Vi.east, Vi.south_east, Vi.south, + Vi.south_west, Vi.west, Vi.north_west] + +// Discrete velocity vectors, by component, with respect to SDL display orientation (North is negative on y axis) +// f64 and int are provided to avoid unnecessary casts. +// Warning: These vectors must be coherent with Vi enum order ! +const dvx_f = [0.0, 0.0, 1.0, 1.0, 1.0, 0.0, -1.0, -1.0, -1.0] +const dvy_f = [0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 0.0, -1.0] +const dvx_i = [0, 0, 1, 1, 1, 0, -1, -1, -1] +const dvy_i = [0, -1, -1, 0, 1, 1, 1, 0, -1] + +// wi is the weight of mini-cells. +// Warning: This array must be coherent with Vi enum order ! +const wi = [f64(16.0 / 36.0), 4.0 / 36.0, 1.0 / 36.0, + 4.0 / 36.0, 1.0 / 36.0, 4.0 / 36.0, + 1.0 / 36.0, 4.0 / 36.0, 1.0 / 36.0 +] + +// vfmt on + +struct Cell { +mut: + obstacle bool + sp [9]f64 +} + +// Cell.new built, and initializes a default Cell. +// Warning: sp values must be coherent with Vi enum order ! +fn Cell.new(o bool) Cell { + return Cell{ + obstacle: o + sp: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]! + } // ! means fixed size array ! Will change a day ! +} + +// Return a Cell with all mini-cell set to Zero +fn Cell.zero(o bool) Cell { + return Cell{ + obstacle: o + sp: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]! + } +} + +// normalize perform a normalisation on the cell so that average desnsity is rho0 +fn (mut c Cell) normalize() { + rho := c.rho() + for mut v in c.sp { + v *= (rho0 / rho) + } +} + +// randomize add some randomness on the cell. +fn (mut c Cell) randomize(i f64) { + for v in vi { + r := rand.f64() * i + c.sum(v, r) + } +} + +// get returns mini-cell depending on the given speed vector. +fn (c &Cell) get(v Vi) f64 { + return c.sp[int(v)] +} + +// set forces a mini-cell value given its speed vector. +fn (mut c Cell) set(v Vi, value f64) { + c.sp[int(v)] = value +} + +// increase (add value) to a mini-cell value given its speed vector. +fn (mut c Cell) sum(v Vi, value f64) { + c.sp[int(v)] += value +} + +// rho computes whole cell's density +fn (c &Cell) rho() f64 { + mut sum := 0.0 + for v in c.sp { + sum += v + } + assert math.is_nan(sum) == false + return sum +} + +// ux computes x (horizontal) component of cell speed vector. +fn (c &Cell) ux() f64 { + rho := c.rho() + r := 1.0 / rho * (c.sp[Vi.north_east] + c.sp[Vi.east] + c.sp[Vi.south_east] - c.sp[Vi.south_west] - c.sp[Vi.west] - c.sp[Vi.north_west]) + assert math.is_nan(r) == false + return r +} + +// uy computes y (vertical) component of cell speed vector. +fn (c &Cell) uy() f64 { + rho := c.rho() + r := 1.0 / rho * (-c.sp[Vi.north] - c.sp[Vi.north_east] - c.sp[Vi.north_west] + c.sp[Vi.south_east] + c.sp[Vi.south] + c.sp[Vi.south_west]) + assert math.is_nan(r) == false + return r +} + +// ux_no_rho computes x (horizontal) component of cell speed vector, when rho is already known and passed as param. +fn (c &Cell) ux_no_rho(rho f64) f64 { + r := 1.0 / rho * (c.sp[Vi.north_east] + c.sp[Vi.east] + c.sp[Vi.south_east] - c.sp[Vi.south_west] - c.sp[Vi.west] - c.sp[Vi.north_west]) + return r +} + +// uy_no_rho computes y (vertical) component of cell speed vector, when rho is already known and passed as param. +fn (c &Cell) uy_no_rho(rho f64) f64 { + r := 1.0 / rho * (-c.sp[Vi.north] - c.sp[Vi.north_east] - c.sp[Vi.north_west] + c.sp[Vi.south_east] + c.sp[Vi.south] + c.sp[Vi.south_west]) + return r +} + +// equ computes result of equilibrium function. +fn (c &Cell) equ(i Vi) f64 { + rho := c.rho() + ux := c.ux_no_rho(rho) + uy := c.uy_no_rho(rho) + + t1 := 3.0 * (ux * dvx_f[i] +uy * dvy_f[i]) + mut t2 := (ux * dvx_f[i] +uy * dvy_f[i]) + + t2 *= t2 // t2^2 + t2 *= (9.0 / 2.0) + t3 := (3.0 / 2.0) * (ux * ux + uy * uy) + r := wi[i] * rho * (1.0 + t1 + t2 - t3) + return r +} diff --git a/examples/lbm/colormap.v b/examples/lbm/colormap.v new file mode 100644 index 00000000..317d1ebb --- /dev/null +++ b/examples/lbm/colormap.v @@ -0,0 +1,48 @@ +module main + +import arrays + +struct Colormap {} + +// build a linear color map ARGB8888 from color c1 to c2, of steps colors +pub fn Colormap.build(c1 u32, c2 u32, steps int) []u32 { + assert steps > 1, 'Error, generating colormap needs at least two steps.' + mut cm := []u32{cap: steps} + + // split c1 & c2 to RGB channels. + mut c1_r := f64((c1 & 0xFF0000) >> 16) + mut c1_g := f64((c1 & 0xFF00) >> 8) + mut c1_b := f64((c1 & 0xFF)) + + c2_r := f64((c2 & 0xFF0000) >> 16) + c2_g := f64((c2 & 0xFF00) >> 8) + c2_b := f64((c2 & 0xFF)) + + delta_r := (c2_r - c1_r) / f64(steps - 1) + delta_g := (c2_g - c1_g) / f64(steps - 1) + delta_b := (c2_b - c1_b) / f64(steps - 1) + + cm << (0xFF000000 | c1) // Emit exact start color. + for _ in 1 .. steps - 1 { + c1_r += delta_r + c1_g += delta_g + c1_b += delta_b + + // Recompose 3 channels to ARGB8888 color. + mut c := u32(0xFF_00_00_00) + c |= u32(c1_r) << 16 + c |= u32(c1_g) << 8 + c |= u32(c1_b) + cm << c + } + cm << (0xFF000000 | c2) // Emit exact end color. + return cm +} + + + +// dual creates a color map with start color, intermediate color and final color, equaly sized. +fn Colormap.dual(c1 u32, c2 u32, c3 u32, steps int) []u32 { + assert steps > 2, 'Error, generating dual-colormap needs at least three steps.' + return arrays.append(Colormap.build(c1, c2, steps / 2), Colormap.build(c2, c3, steps - (steps / 2))) +} diff --git a/examples/lbm/lattice.v b/examples/lbm/lattice.v new file mode 100644 index 00000000..672b18d8 --- /dev/null +++ b/examples/lbm/lattice.v @@ -0,0 +1,278 @@ +module main + +import math + +pub struct Lattice { + w int + h int +mut: + m []Cell +} + +// Allocate x*y Cells Lattice +pub fn Lattice.new(x int, y int, profile &u8) Lattice { + mut ret := Lattice{x, y, []Cell{cap: x * y}} + + for i in 0 .. (x * y) { + e := unsafe { profile[i] != 0 } + mut c := Cell.new(e) + ret.m << c + } + return ret +} + +pub fn (l Lattice) str() string { + return 'Lattice[${l.w}x${l.h}]' +} + +// total_rho compute the total density on the Lattice. This value is conserved. +pub fn (l Lattice) total_rho() f64 { + mut t := 0.0 + for c in l.m { + if c.obstacle { + continue + } + t += c.rho() + } + return t +} + +// clear the Lattice : File fields with zeros. +pub fn (mut l Lattice) clear() { + unsafe{vmemset(l.m.data, 0, u32(l.m.len) * sizeof(Cell) )} +} + +// add_flow create an artificial flow of i intensity in v direction +// It impacts all lattice cells. It's usually a good thing to call normalize() +// method after that. +pub fn (mut l Lattice) add_flow(i f64, v Vi) { + for mut c in l.m { + if c.obstacle { + continue + } + c.sum(v, i) + } +} + +// normalize normalizes all lattice cells against rho0 so that average density +// is equal to rho0. +pub fn (mut l Lattice) normalize() { + for mut c in l.m { + if c.obstacle { + continue + } + c.normalize() + } +} + +// max_ux returns maximal horizontal speed in the whole lattice +pub fn (l Lattice) max_ux() f64 { + mut ux := 0.0 + + for c in l.m { + if c.obstacle { + continue + } + u := c.ux() + + if u > ux { + ux = u + } + } + return ux +} + +// min_ux returns minimal horizontal speed in the whole lattice +pub fn (l Lattice) min_ux() f64 { + mut ux := 0.0 + + for c in l.m { + if c.obstacle { + continue + } + u := c.ux() + + if u < ux { + ux = u + } + } + return ux +} + +// max_uy returns maximal horizontal speed in the whole lattice +pub fn (l Lattice) max_uy() f64 { + mut uy := 0.0 + + for c in l.m { + if c.obstacle { + continue + } + u := c.uy() + + if u > uy { + uy = u + } + } + return uy +} + +// min_uy returns minimal horizontal speed in the whole lattice +pub fn (l Lattice) min_uy() f64 { + mut uy := 0.0 + + for c in l.m { + if c.obstacle { + continue + } + u := c.uy() + + if u < uy { + uy = u + } + } + return uy +} + +// max_rho returns maximal cell density in the whole lattice +pub fn (l Lattice) max_rho() f64 { + mut r := 0.0 + + for c in l.m { + if c.obstacle { + continue + } + rho := c.rho() + + if rho > r { + r = rho + } + } + return r +} + +// min_rho returns maximal cell density in the whole lattice +pub fn (l Lattice) min_rho() f64 { + mut r := 1_000_000.0 + + for c in l.m { + if c.obstacle { + continue + } + rho := c.rho() + + if rho < r { + r = rho + } + } + return r +} + +// mean_rho returns the mean rho value over all lattice +fn (l Lattice) mean_rho() f64 { + mut i := 0.0 + for c in l.m { + if c.obstacle { + continue + } + i += c.rho() + } + + return i / l.m.len +} + +// vorticity computes vorticity at given position. +fn (l Lattice) vorticity(x int, y int) f64 { + if x > 0 && x < l.w - 1 { + if y > 0 && y < l.h - 1 { + ind := y * l.w + x + omega := (l.m[ind + 1].uy() - l.m[ind - 1].uy()) - (l.m[ind + l.w].ux() - l.m[ind - l.w].ux()) + return omega + } + } + return 0 +} + +// randomize add random noise everywhere given i intensity. +// It's usually a good thing to call normalize() method after that. +pub fn (mut l Lattice) randomize(i f64) { + for mut c in l.m { + if c.obstacle { + continue + } + c.randomize(i) + } +} + +// move applies simulation movements handling borders and profile collisions. +// Note that the rightmost column is handled differently, and outgoing mini-particle +// are re-injected on the left. +pub fn (l Lattice) move(mut output Lattice) { + mut index := 0 + output.clear() + + for y in 0 .. l.h { + for x in 0 .. l.w { + output.m[index].obstacle = l.m[index].obstacle // Copy src reachable state to output + for m in vi { // For this cell, for all direction vectors or mini particles + mini_part := l.m[index].get(m) + if dst_ind := l.reachable(x, y, m) { + output.m[dst_ind].sum(m, mini_part) // move mini-particle + } else { + output.m[index].sum(m.opposite(), mini_part) // rebound mini-particle, don't move but invert direction vector. + } + } + index++ + } + } +} + +// collide performs the most sensible step: Collision between mini-particles. +pub fn (mut l Lattice) collide() { + for mut c in l.m { + if c.obstacle == false { + mut new_cell := Cell.zero(false) + + for m in vi { + f := c.get(m) + feq := c.equ(m) + assert math.is_nan(feq) == false + assert math.is_nan(f) == false + new_cell.set(m, f - ((1.0 / tau) * (f - feq))) + } + c = new_cell + } + } +} + +// reachable test if destination Cell (base on x,y and Direction vector) +// is cross-able or reachable. Lattice edge is limiting, as the profile as +// well, none is returned on these case. For reachable, index of the +// reachable Cell (in Lattice) is returned, for an easy update. +fn (l Lattice) reachable(x int, y int, v Vi) ?int { + assert x >= 0 + assert y >= 0 + + // Add direction vector to current position to get destination position. + mut nx := x + dvx_i[int(v)] + ny := y + dvy_i[int(v)] + + if ny < 0 || ny >= l.h { + return none + } + + if nx < 0 { + nx = nx + l.w + } + + if nx >= l.w { + nx = nx - l.w + } + + ind := nx + (l.w * ny) // Get 1D index in lattice. + + return if l.m[ind].obstacle { + none + } else { + ind // Destination cell is obstacle free. Return it's index. + } +} diff --git a/examples/lbm/main.v b/examples/lbm/main.v new file mode 100644 index 00000000..7d8df0a8 --- /dev/null +++ b/examples/lbm/main.v @@ -0,0 +1,330 @@ +/** + This program is about D2Q9 Lattice Boltzmann Method: + See : https://en.wikipedia.org/wiki/Lattice_Boltzmann_methods + + It's a pet project in order to use V language: https://vlang.io/ + + The simulation is single threaded, probably buggy and should not be used + for serious things. It's very sensible to tau parameter that should be + carefully set. This parameter is related to fluid viscosity, and is set so + that the fluid speed doesn't exceed a speed limit that breaks simulation. + Too narrow passage (speed increased) may reach this limit. + + profiles files MUST be of the same size of defined width and weight and + should be 8bits per pixels. Every non zero value is considered as an + obstacle. + + to compile the program from within source directory: + + v -prod . + + or if you want gcc as compiler: + + v -prod -cc gcc . + + SDL module must be installed: https://vpm.vlang.io/packages/sdl + and post install script executed, see link. + + The simulation is quite slow, but would you like to slow it down, just + uncomment the sdl.delay(...) in file. + + + + This program is released under MIT license. + */ +module main + +import sdl +import sdl.image as img +import os +import time + +const tau = 0.6 // Relaxation time, related to fluid viscosity. +const rho0 = 32.0 // Average normalised density. +const width = 512 +const height = 128 +const len_in_bytes = width * height * sizeof(u32) +const obstacle_color = u32(0xFF004000) +const low_color = u32(0xFFFFFF00) +const middle_color = u32(0xFF000000) +const high_color = u32(0xFF00FFFF) + +// Type for rendering methods, used as parameter. +type Renderer = fn (l Lattice, cm []u32, mut output []u32) + +const renderers = [vorticity, v_speed, h_speed, densities] +const renderers_names = ['vorticity', 'vertical speed', 'horizontal speed', 'density'] + +fn main() { + argv := os.args.len + + if argv != 2 { + println('Usage: lbm profile_file.png') + println(' e.g: ./lbm profiles/circle.png') + println('During simulation press "v" to show different parameters.') + return + } + + if sdl.init(sdl.init_video) < 0 { + eprintln('sdl.init() error: ${unsafe { cstring_to_vstring(sdl.get_error()) }}') + return + } + + flags := u32(sdl.WindowFlags.opengl) | u32(sdl.WindowFlags.resizable) + window := sdl.create_window(c'Lattice Boltzmann Method [D2Q9]', sdl.windowpos_centered, + sdl.windowpos_centered, width * 2, height * 2, flags) + + if window == sdl.null { + eprintln('sdl.create_window() error: ${unsafe { cstring_to_vstring(sdl.get_error()) }}') + return + } + + r_flags := u32(sdl.RendererFlags.accelerated) + renderer := sdl.create_renderer(window, -1, r_flags) + + if renderer == sdl.null { + eprintln('sdl.create_renderer() error: ${unsafe { cstring_to_vstring(sdl.get_error()) }}') + return + } + + mut tex := sdl.create_texture(renderer, sdl.Format.argb8888, sdl.TextureAccess.streaming, + width, height) + + if tex == sdl.null { + eprintln('sdl.create_texture() error: ${unsafe { cstring_to_vstring(sdl.get_error()) }}') + return + } + + defer { + sdl.destroy_texture(tex) + sdl.destroy_renderer(renderer) + sdl.destroy_window(window) + } + + profile := img.load(os.args[1].str) + if profile == sdl.null { + eprintln('Error trying to load profile .png file: ${unsafe { cstring_to_vstring(sdl.get_error()) }}') + return + } + + // Check size compatibility. + if profile.w != width || profile.h != height { + eprintln('Error, "${os.args[1]}" profile image must match lbm lattice size : ${profile.w}x${profile.h}') + return + } + + // Check profile is 1 byte / pixel. + if (profile.pitch / width) != 1 { + eprintln('Error profile file must be 1 byte per pixel') + return + } + + // Build a colormap to be used + cm := Colormap.dual(low_color, middle_color, high_color, 384) + + // Now create Lattices, with respect to loaded profile. + mut src := Lattice.new(width, height, profile.pixels) + + src.add_flow(1.0, Vi.east) + src.randomize(0.2) + src.normalize() + + mut dst := Lattice.new(width, height, profile.pixels) + + // Allocate pixel buffer to draw in. + mut pixel_buffer := []u32{len: width * height} // Dyn array heap allocated. + + mut should_close := false + mut frame := 0 + mut render_method := vorticity + + println('Showing vorticiy. Press "v" to show different parameters.') + + for { + evt := sdl.Event{} + for 0 < sdl.poll_event(&evt) { + match evt.@type { + .quit { + should_close = true + } + .keydown { + key := unsafe { sdl.KeyCode(evt.key.keysym.sym) } + if key == sdl.KeyCode.escape { + should_close = true + break + } + // Show next view + if key == sdl.KeyCode.v { + mut i := renderers.index(render_method) + i++ + if i >= renderers.len { + i = 0 + } + render_method = renderers[i] + println('Rendering : ${renderers_names[i]}') + } + } + else {} + } + } + if should_close { + break + } + + mut stop_watch := time.new_stopwatch() + src.move(mut dst) + dst.collide() + render_method(dst, cm, mut pixel_buffer) // render_method can point different method ! + draw_colormap(cm, mut pixel_buffer) + + // swap src and dst buffers. + tmp := src + src = dst + dst = tmp + + blit_pixels(tex, pixel_buffer) + frame++ + stop_watch.stop() + // println('Frame ${frame}, loop : ${stop_watch.elapsed().milliseconds()} milliseconds. ') + + sdl.render_clear(renderer) + sdl.render_copy(renderer, tex, sdl.null, sdl.null) + sdl.render_present(renderer) + // sdl.delay(10) + } +} + +// No bound checking here +// blit_pixels from buffer to texture. +@[direct_array_access] +fn blit_pixels(t &sdl.Texture, data []u32) { + mut pixels := unsafe { voidptr(nil) } + mut pitch := int(0) + + success := sdl.lock_texture(t, sdl.null, &pixels, &pitch) + if success < 0 { + panic('sdl.lock_texture error: ${sdl.get_error()}') + } + unsafe { vmemcpy(pixels, data.data, len_in_bytes) } + sdl.unlock_texture(t) +} + +fn draw_colormap(cm []u32, mut data []u32) { + data[0] = 0xFF000000 + data[width] = 0xFF000000 + data[2 * width] = 0xFF000000 + for i in 0 .. cm.len { + data[i + 1] = 0xFF000000 + data[i + width + 1] = cm[i] + data[i + 1 + 2 * width] = 0xFF000000 + } + data[cm.len] = 0xFF000000 + data[width + cm.len] = 0xFF000000 + data[2 * width + cm.len] = 0xFF000000 +} + +// densities is a Renderer type function +fn densities(l Lattice, cm []u32, mut output []u32) { + mut ind := 0 + + min_rho := l.min_rho() + max_rho := l.max_rho() + linear := (max_rho - min_rho) / (cm.len - 1) + + for c in l.m { + if c.obstacle == true { + output[ind] = obstacle_color + ind++ + continue + } + + rho := int((c.rho() - min_rho) / linear) + output[ind] = cm[rho] + ind++ + } +} + +// h_speed is a Renderer type function +fn h_speed(l Lattice, cm []u32, mut output []u32) { + mut ind := 0 + + min_ux := l.min_ux() + max_ux := l.max_ux() + linear := (max_ux - min_ux) / (cm.len - 1) + + for c in l.m { + if c.obstacle == true { + output[ind] = obstacle_color + ind++ + continue + } + + rho := int((c.ux() - min_ux) / linear) + output[ind] = cm[rho] + ind++ + } +} + +// h_speed is a Renderer type function +fn v_speed(l Lattice, cm []u32, mut output []u32) { + mut ind := 0 + + min_uy := l.min_uy() + max_uy := l.max_uy() + linear := (max_uy - min_uy) / (cm.len - 1) + + for c in l.m { + if c.obstacle == true { + output[ind] = obstacle_color + ind++ + continue + } + + rho := int((c.uy() - min_uy) / linear) + output[ind] = cm[rho] + ind++ + } +} + +// vorticity is a Renderer type function +fn vorticity(l Lattice, cm []u32, mut output []u32) { + mut min := 0.0 + mut max := 0.0 + cm2 := u32(cm.len / 2) + mut vorticity_table := []f64{len: l.w * l.h} + + for y in 0 .. l.h { + for x in 0 .. l.w { + out := (y * l.w) + x + if l.m[out].obstacle { + vorticity_table[out] = -1000000.0 + } else { + v := l.vorticity(x, y) + vorticity_table[out] = v + if min > v { + min = v + } + if max < v { + max = v + } + } + } + } + + linear := (max - min) / f64(cm.len - 1) + + for ind, v in vorticity_table { + if v < -100.0 { + output[ind] = obstacle_color + } else { + mut id := cm2 + u32(v / linear) + + if id < 0 { + id = 0 + } else if id >= cm.len { + id = u32(cm.len - 1) + } + output[ind] = cm[id] + } + } +} diff --git a/examples/lbm/profiles/asymetric.png b/examples/lbm/profiles/asymetric.png new file mode 100644 index 0000000000000000000000000000000000000000..9b03ed46a47cf3739c7a7f6a2b074b39c20139f4 GIT binary patch literal 5794 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 literal 0 HcmV?d00001 diff --git a/examples/lbm/profiles/septum.png b/examples/lbm/profiles/septum.png new file mode 100644 index 0000000000000000000000000000000000000000..3035703e18f50db19b36bfb10255b3cceb575d41 GIT binary patch literal 6904 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 literal 0 HcmV?d00001 diff --git a/examples/lbm/profiles/test.png b/examples/lbm/profiles/test.png new file mode 100644 index 0000000000000000000000000000000000000000..98aea1e42a11c5892b674dd3afe953c7aef5b66b GIT binary patch literal 6676 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 TAH3WH0ms~>l_k69E?xaUz>ZeI literal 0 HcmV?d00001 diff --git a/examples/lbm/readme.md b/examples/lbm/readme.md new file mode 100644 index 00000000..ac95f716 --- /dev/null +++ b/examples/lbm/readme.md @@ -0,0 +1,32 @@ +This program is about D2Q9 Lattice Boltzmann Method: +See : https://en.wikipedia.org/wiki/Lattice_Boltzmann_methods + +It's a pet project in order to use V language: https://vlang.io/ + +The simulation is single threaded, probably buggy and should not be used +for serious things. It's very sensible to tau parameter that should be +carefully set. This parameter is related to fluid viscosity, and is set so +that the fluid speed doesn't exceed a speed limit that breaks simulation. +Too narrow passage (speed increased) may reach this limit. + +profiles files MUST be of the same size of defined width and weight and +should be 8bits per pixels. Every non zero value is considered as an +obstacle. + +to compile the program from within source directory: + +v -prod . + +or if you want gcc as compiler: + +v -prod -cc gcc . + +SDL module must be installed: https://vpm.vlang.io/packages/sdl +and post install script executed, see link. + +The simulation is quite slow, but would you like to slow it down, just +uncomment the sdl.delay(...) in file. + + + +This program is released under MIT license. diff --git a/examples/lbm/v.mod b/examples/lbm/v.mod new file mode 100644 index 00000000..5ed17dab --- /dev/null +++ b/examples/lbm/v.mod @@ -0,0 +1,7 @@ +Module { + name: 'lbm' + description: 'Lattice Boltzmann simulation, used as toy projet to learn about V language' + version: '0.0.1' + license: 'MIT' + dependencies: [] +} From 812f1b7e7be7aa2740eca544a81364c626f4d9f0 Mon Sep 17 00:00:00 2001 From: Bruno Date: Tue, 31 Dec 2024 06:57:56 +0100 Subject: [PATCH 02/12] Run v fmt -w on all lbm files. --- examples/lbm/cell.v | 12 +++++++----- examples/lbm/colormap.v | 2 -- examples/lbm/lattice.v | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/lbm/cell.v b/examples/lbm/cell.v index 3843675e..eb182623 100644 --- a/examples/lbm/cell.v +++ b/examples/lbm/cell.v @@ -71,7 +71,7 @@ mut: fn Cell.new(o bool) Cell { return Cell{ obstacle: o - sp: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]! + sp: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]! } // ! means fixed size array ! Will change a day ! } @@ -135,7 +135,8 @@ fn (c &Cell) ux() f64 { // uy computes y (vertical) component of cell speed vector. fn (c &Cell) uy() f64 { rho := c.rho() - r := 1.0 / rho * (-c.sp[Vi.north] - c.sp[Vi.north_east] - c.sp[Vi.north_west] + c.sp[Vi.south_east] + c.sp[Vi.south] + c.sp[Vi.south_west]) + r := 1.0 / rho * (-c.sp[Vi.north] - c.sp[Vi.north_east] - c.sp[Vi.north_west] + + c.sp[Vi.south_east] + c.sp[Vi.south] + c.sp[Vi.south_west]) assert math.is_nan(r) == false return r } @@ -148,7 +149,8 @@ fn (c &Cell) ux_no_rho(rho f64) f64 { // uy_no_rho computes y (vertical) component of cell speed vector, when rho is already known and passed as param. fn (c &Cell) uy_no_rho(rho f64) f64 { - r := 1.0 / rho * (-c.sp[Vi.north] - c.sp[Vi.north_east] - c.sp[Vi.north_west] + c.sp[Vi.south_east] + c.sp[Vi.south] + c.sp[Vi.south_west]) + r := 1.0 / rho * (-c.sp[Vi.north] - c.sp[Vi.north_east] - c.sp[Vi.north_west] + + c.sp[Vi.south_east] + c.sp[Vi.south] + c.sp[Vi.south_west]) return r } @@ -158,8 +160,8 @@ fn (c &Cell) equ(i Vi) f64 { ux := c.ux_no_rho(rho) uy := c.uy_no_rho(rho) - t1 := 3.0 * (ux * dvx_f[i] +uy * dvy_f[i]) - mut t2 := (ux * dvx_f[i] +uy * dvy_f[i]) + t1 := 3.0 * (ux * dvx_f[i] + uy * dvy_f[i]) + mut t2 := (ux * dvx_f[i] + uy * dvy_f[i]) t2 *= t2 // t2^2 t2 *= (9.0 / 2.0) diff --git a/examples/lbm/colormap.v b/examples/lbm/colormap.v index 317d1ebb..716dc457 100644 --- a/examples/lbm/colormap.v +++ b/examples/lbm/colormap.v @@ -39,8 +39,6 @@ pub fn Colormap.build(c1 u32, c2 u32, steps int) []u32 { return cm } - - // dual creates a color map with start color, intermediate color and final color, equaly sized. fn Colormap.dual(c1 u32, c2 u32, c3 u32, steps int) []u32 { assert steps > 2, 'Error, generating dual-colormap needs at least three steps.' diff --git a/examples/lbm/lattice.v b/examples/lbm/lattice.v index 672b18d8..e03b8551 100644 --- a/examples/lbm/lattice.v +++ b/examples/lbm/lattice.v @@ -39,7 +39,7 @@ pub fn (l Lattice) total_rho() f64 { // clear the Lattice : File fields with zeros. pub fn (mut l Lattice) clear() { - unsafe{vmemset(l.m.data, 0, u32(l.m.len) * sizeof(Cell) )} + unsafe { vmemset(l.m.data, 0, u32(l.m.len) * sizeof(Cell)) } } // add_flow create an artificial flow of i intensity in v direction @@ -211,10 +211,10 @@ pub fn (l Lattice) move(mut output Lattice) { output.clear() for y in 0 .. l.h { - for x in 0 .. l.w { + for x in 0 .. l.w { output.m[index].obstacle = l.m[index].obstacle // Copy src reachable state to output for m in vi { // For this cell, for all direction vectors or mini particles - mini_part := l.m[index].get(m) + mini_part := l.m[index].get(m) if dst_ind := l.reachable(x, y, m) { output.m[dst_ind].sum(m, mini_part) // move mini-particle } else { @@ -271,8 +271,8 @@ fn (l Lattice) reachable(x int, y int, v Vi) ?int { ind := nx + (l.w * ny) // Get 1D index in lattice. return if l.m[ind].obstacle { - none + none } else { - ind // Destination cell is obstacle free. Return it's index. + ind // Destination cell is obstacle free. Return it's index. } } From d4da2e7e79d8ab0ca8f58ccb5a0e28a784fa2740 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 13 Jan 2025 14:27:23 +0200 Subject: [PATCH 03/12] fix macos job, use SDL2_VERSION: 2.30.11, since that is the one available from brew --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f33529e6..a09d6e59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,6 +100,8 @@ jobs: uses: actions/checkout@v4 with: path: sdl + ref: "2.30.0" + fetch-depth: 0 - name: Link local SDL folder in ~/.vmodules/sdl run: | From b129d8b925f4d22f6c3e60766ccf8cdd57d6d0a3 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 13 Jan 2025 14:50:04 +0200 Subject: [PATCH 04/12] reduce `// vfmt off` usage --- examples/lbm/cell.v | 64 +++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/examples/lbm/cell.v b/examples/lbm/cell.v index eb182623..19a122aa 100644 --- a/examples/lbm/cell.v +++ b/examples/lbm/cell.v @@ -3,8 +3,6 @@ module main import math import rand -// vfmt off -// // This file contains Code and data structures for a Lattice-Boltzmann-Method (LBM) // fluid flow simulation. The simulation is 2 Dimension, with 9 possible directions (D2Q9) // @@ -15,34 +13,51 @@ import rand // 6 5 4 // Vi is an enum for direction vector of D2Q9 Lattice. -pub enum Vi as int { - center =0 - north = 1 - north_east =2 - east=3 - south_east=4 - south= 5 +pub enum Vi { + center = 0 + north = 1 + north_east = 2 + // + east = 3 + south_east = 4 + south = 5 + // south_west = 6 - west=7 + west = 7 north_west = 8 } +// vfmt off +const opp = [ + Vi.center, Vi.south, Vi.south_west, + Vi.west, Vi.north_west, Vi.north, + Vi.north_east, Vi.east, Vi.south_east, +]! + +// Array defined here in order to loop over a Vi enum. +// Warning: This array must be coherent with Vi enum order ! +const vi = [ + Vi.center, Vi.north, Vi.north_east, + Vi.east, Vi.south_east, Vi.south, + Vi.south_west, Vi.west, Vi.north_west, +]! + +// wi is the weight of mini-cells. +// Warning: This array must be coherent with Vi enum order ! +// vfmt off +const wi = [ + f64(16.0 / 36.0), 4.0 / 36.0, 1.0 / 36.0, + 4.0 / 36.0, 1.0 / 36.0, 4.0 / 36.0, + 1.0 / 36.0, 4.0 / 36.0, 1.0 / 36.0, +] +// vfmt on + // opposite returns vector of opposite direction. Yes Enum can have methods in V. // Warning: This array must be coherent with Vi enum order ! fn (v Vi) opposite() Vi { - opp :=[Vi.center, Vi.south, Vi.south_west, - Vi.west, Vi.north_west, Vi.north, - Vi.north_east, Vi.east, Vi.south_east] - return opp[int(v)] } -//Array defined here in order to loop over a Vi enum. -// Warning: This array must be coherent with Vi enum order ! -const vi = [Vi.center, Vi.north, Vi.north_east, - Vi.east, Vi.south_east, Vi.south, - Vi.south_west, Vi.west, Vi.north_west] - // Discrete velocity vectors, by component, with respect to SDL display orientation (North is negative on y axis) // f64 and int are provided to avoid unnecessary casts. // Warning: These vectors must be coherent with Vi enum order ! @@ -51,15 +66,6 @@ const dvy_f = [0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 0.0, -1.0] const dvx_i = [0, 0, 1, 1, 1, 0, -1, -1, -1] const dvy_i = [0, -1, -1, 0, 1, 1, 1, 0, -1] -// wi is the weight of mini-cells. -// Warning: This array must be coherent with Vi enum order ! -const wi = [f64(16.0 / 36.0), 4.0 / 36.0, 1.0 / 36.0, - 4.0 / 36.0, 1.0 / 36.0, 4.0 / 36.0, - 1.0 / 36.0, 4.0 / 36.0, 1.0 / 36.0 -] - -// vfmt on - struct Cell { mut: obstacle bool From 94a10f3dde4fdded8318d6ce247a91a08e03f3e2 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 13 Jan 2025 14:51:37 +0200 Subject: [PATCH 05/12] use a fixed array for the wi const as well --- examples/lbm/cell.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lbm/cell.v b/examples/lbm/cell.v index 19a122aa..c3fc0055 100644 --- a/examples/lbm/cell.v +++ b/examples/lbm/cell.v @@ -49,7 +49,7 @@ const wi = [ f64(16.0 / 36.0), 4.0 / 36.0, 1.0 / 36.0, 4.0 / 36.0, 1.0 / 36.0, 4.0 / 36.0, 1.0 / 36.0, 4.0 / 36.0, 1.0 / 36.0, -] +]! // vfmt on // opposite returns vector of opposite direction. Yes Enum can have methods in V. From 2387c59b2a363d7ea6578e2860fecbd412b7e6a1 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 13 Jan 2025 14:53:06 +0200 Subject: [PATCH 06/12] more cleanup --- examples/lbm/cell.v | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/lbm/cell.v b/examples/lbm/cell.v index c3fc0055..40a82685 100644 --- a/examples/lbm/cell.v +++ b/examples/lbm/cell.v @@ -44,7 +44,6 @@ const vi = [ // wi is the weight of mini-cells. // Warning: This array must be coherent with Vi enum order ! -// vfmt off const wi = [ f64(16.0 / 36.0), 4.0 / 36.0, 1.0 / 36.0, 4.0 / 36.0, 1.0 / 36.0, 4.0 / 36.0, From a8f64c84fff4f8ca12973e15e239d765bf4a8793 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 13 Jan 2025 14:54:39 +0200 Subject: [PATCH 07/12] turn more consts to fixed arrays --- examples/lbm/cell.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/lbm/cell.v b/examples/lbm/cell.v index 40a82685..ded634e7 100644 --- a/examples/lbm/cell.v +++ b/examples/lbm/cell.v @@ -60,10 +60,10 @@ fn (v Vi) opposite() Vi { // Discrete velocity vectors, by component, with respect to SDL display orientation (North is negative on y axis) // f64 and int are provided to avoid unnecessary casts. // Warning: These vectors must be coherent with Vi enum order ! -const dvx_f = [0.0, 0.0, 1.0, 1.0, 1.0, 0.0, -1.0, -1.0, -1.0] -const dvy_f = [0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 0.0, -1.0] -const dvx_i = [0, 0, 1, 1, 1, 0, -1, -1, -1] -const dvy_i = [0, -1, -1, 0, 1, 1, 1, 0, -1] +const dvx_f = [0.0, 0.0, 1.0, 1.0, 1.0, 0.0, -1.0, -1.0, -1.0]! +const dvy_f = [0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 0.0, -1.0]! +const dvx_i = [0, 0, 1, 1, 1, 0, -1, -1, -1]! +const dvy_i = [0, -1, -1, 0, 1, 1, 1, 0, -1]! struct Cell { mut: From cbb51ecc0e5c639f4652dcedd4bd2e5697cbc1f3 Mon Sep 17 00:00:00 2001 From: lmp Date: Tue, 14 Jan 2025 10:50:43 +0100 Subject: [PATCH 08/12] replace profile images with optimized ones (~94-98% saved) --- examples/lbm/profiles/asymetric.png | Bin 5794 -> 195 bytes examples/lbm/profiles/barrier.png | Bin 5271 -> 123 bytes examples/lbm/profiles/circle.png | Bin 4934 -> 249 bytes examples/lbm/profiles/septum.png | Bin 6904 -> 373 bytes examples/lbm/profiles/test.png | Bin 6676 -> 385 bytes 5 files changed, 0 insertions(+), 0 deletions(-) diff --git a/examples/lbm/profiles/asymetric.png b/examples/lbm/profiles/asymetric.png index 9b03ed46a47cf3739c7a7f6a2b074b39c20139f4..cf6f6d3112e9dc10b1c9ef8f9de7476feec381fc 100644 GIT binary patch delta 168 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 Y0GkpkdBrYT4P^xL2nfL^!P+iX*o(H{i)TPgW9 zkmsdrbbk_j^PoQtjRJWF^k<-{>yq>S1!VooG5(xUMbs1-jjLJg1o*#wdjNIOcB0?7#k3yG}VoQ>QMKDVKnc8|sjx9RK7ndplp7r=gv z>U4TsPA3|PhW%-izbqgNsLx(o*5k9P_c%b#0>pc&BU_LBt zd;4$Gci6r&-||9dYj5waQwP^<=sA*qq!YcBF?4Bg@26N%|JIpHPu?2*Yw6h)pF{?p zUiJPV>cW*8`^8unR$H{7kNHIA^9KIj_ETiw>QKq=hx>Q6dW!!v zEvNcqu77F%^{LnUUXh~xb7wX+{h{l-^*H3mKO9s*mQ@ADgknT$g(a zyY@`wz>C>yL#wYXT@iXY_EIU*wB!4?r*d58>6#aRdF95H)%|b&bH#r8ox;b?MYsRr z*N{d>(JgU?$U+k5Zw@SQ>Eh;saBm@8mDw>EUf`L#>NH{P9R{&X8TQSry(OMl? zBNUr6992-8#bzP!iiFxuVWnoYBr5xby7I~t1l&2W7EOx?R%<*Sx5Q~nINEF_d7ift zl$D}zu)t#-Ax%u+q1YT9B8gG1#H6Si(bRAV)iFh1xJ`3l7>uJM@dYDpcN#tvOR)fa zSQBEzN?HhOFlZg?5z{K#0VEaBS9-*}9TCM^r^Lc-QAw$2S3=sHu@JJ9_K&nh14cTs zWK{x65KLn*D>-gTeOsnIbPAf)V8rkOvd39!s(+NMak1$mMml2y0rxcSIO~zz4P&r! zyM^+w)TW2$DtBP|{DK^oR9P@YhW2wL%`!M|7wx!>q6wUnCVJQRz@J zK*@GaBy9jdND__PIG>3701GF1nPF_SLesp>fRZJlG8_$xu$*d8Y*wt1P_r?h6E2i_ zTn>z~5ThDTK-B!;;J|9tP+MYjz^ew8dQH^XBw5-<*;$TbS-YJi$x)*pDA5>HqK;`C zu*QhKECM70#EN>I0)U~1Tm<734M)AHwNPti2`Bva!1uGKTh5yZv(2al~B~!6oM!vQ;3P} zifqIQSji!&MGQ47aC)T5bwsazMJd>MlAw90AsbIfxQ!J3I46rT&Po(*qZvk0?Eirt z3;VUW7*)!efk)s9%F}p^q4SJ|nm<04c#ER10uY9i6i%>Sf)MQR&!h;m-u)D5#?Nwg z8-x3NJ}6O!^n=7gJT%WyETi~Dd$JDF1b&?qNxNPX1S3%F|1U*Zq9mJ0@i;@XkfN-J zu%TH6=V6EN1e^@A$cm8MyG#K-!fYndx;1L8*G;8{i zmMRNalDm1OcGTUR0!1e$nGnB|bWPGVAqFO7JXu|nbWMnX2^mjT*Z+(z^XN;l5`yot zad_pe{IjVUUYMtPYP}WE55tc&!#}}5GWlw%%8{ zGFx-GE3!YGHr-s1{Yb-+6QH_Zt7z1m;h_Gah1~HgO2g{>SzvU)RbJ+8>A$@7Sl+wD zw9McekqY3-kA68-hCT>Re0~`=awN4{r2%!i>qBL^Vf92^|r+CK|6Neh(*y} zyaVgqvFvE(p&TifLAO16wCCZY%)%nBX;xF=`GRGRteXXy{d2S}2c8UcUfz&Z|BXw- z3%BhY^z24*SJp1NKKF~lg)5ma3a@f|2A_Yne)idJ?&m{?`pyacv#y=)j6Zzh^=_E( d%({eWXF+ktuU{?u3}QxH6^qM{eDBH5e*^YccESJv diff --git a/examples/lbm/profiles/septum.png b/examples/lbm/profiles/septum.png index 3035703e18f50db19b36bfb10255b3cceb575d41..808e0b0aee0d1939296a00d6e80d79d3fb273c4b 100644 GIT binary patch delta 347 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 diff --git a/examples/lbm/profiles/test.png b/examples/lbm/profiles/test.png index 98aea1e42a11c5892b674dd3afe953c7aef5b66b..4a8a74e778fef01b8e34d1401dae89b652452f3c 100644 GIT binary patch delta 345 zcmbPY(#SkPd2*11P(7oWr;B4q#=W;UHuka@a6& z;xLEt_Jlt?Pc}|}#I(vhc+TrTH+~B}tCBpw*X&H`-0N{&#l27Ocz<+dIOw2vV0Znu zw2z$(uj>>XcC#{GVrO~9%UExiAj d28arI=KVKAzsy;xYHq*)1fH&bF6*2UngCAPei{G( literal 6676 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 TAH3WH0ms~>l_k69E?xaUz>ZeI From a89a053ce0e840d1b4955630ea3676d7a98fa157 Mon Sep 17 00:00:00 2001 From: lmp Date: Tue, 14 Jan 2025 10:51:08 +0100 Subject: [PATCH 09/12] delete unneeded `.gitignore` --- .gitignore | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 31bad7b1..00000000 --- a/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Ignore binary files -*.so -*.exe -*.tmp.obj -*.dll -thirdparty/ - -windows_install_dependencies -setup From deffefb6ff223f624dc8c4a68718bd011e07b4d4 Mon Sep 17 00:00:00 2001 From: lmp Date: Tue, 14 Jan 2025 10:55:38 +0100 Subject: [PATCH 10/12] Revert "delete unneeded `.gitignore`" This reverts commit 145a1556c89aa91349b3d1b4e7ca18899b45898a. --- .gitignore | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..31bad7b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Ignore binary files +*.so +*.exe +*.tmp.obj +*.dll +thirdparty/ + +windows_install_dependencies +setup From f4866d82d65f4a087be2a8d49e6b4fc2fa072456 Mon Sep 17 00:00:00 2001 From: lmp Date: Tue, 14 Jan 2025 10:56:23 +0100 Subject: [PATCH 11/12] delete unneeded `.gitignore` in `lbm` example --- examples/lbm/.gitignore | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 examples/lbm/.gitignore diff --git a/examples/lbm/.gitignore b/examples/lbm/.gitignore deleted file mode 100644 index e69de29b..00000000 From 5e0558632bb3bc60fff322e0ca1db783dd0d022c Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Tue, 14 Jan 2025 12:56:52 +0200 Subject: [PATCH 12/12] add changes from the yml file on master back here --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a09d6e59..f33529e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,8 +100,6 @@ jobs: uses: actions/checkout@v4 with: path: sdl - ref: "2.30.0" - fetch-depth: 0 - name: Link local SDL folder in ~/.vmodules/sdl run: |