Dnes vodný olej so soľou á milá študentka á čistíme mikroplasty: https://hrubos.tech/simulacie/olej_voda_nacl_simulacia.mp4

Dnes vodný olej so soľou á milá študentka á čistíme mikroplasty: https://hrubos.tech/simulacie/olej_voda_nacl_simulacia.mp4

Simulácia ako jednoducho odstrániť mikro plasty z vody: https://hrubos.tech/simulacie/olej_voda_nacl_simulacia.mp4

Obrázok: https://hrubos.tech/blogy/content/images/20260903153534-elektro_olej_cistenie_mikroplastov.jpg

Zdroj: https://vedanadosah.cvtisr.sk/priroda/zivotne-prostredie/studentka-strednej-skoly-v-usa-vymyslela-vodny-filter-ktory-zachytava-az-955-percenta-mikroplastov/

Pred odsolením rozhýbeme vodivú vrstvu soľou, aby sme mali mega Brownov pohyb častíc á olej prichádzajúci prídavkom vždy odspodu zachytí mikro plasty. Je to nezávadné Voda, Soľ, Slnečnicový olej á následné odsolenie po zbere mikroplastov. Díkes profesóres, sme team. Prečo je hore mínus elektróda, lebo oleje sú nepolárne zlúčeniny a ako z gymnázia vieme, voda je polárne rozpúšťadlo. Čiže filter sa nám nekazí.

# olej_voda_nacl_simulacia_mp4.jl
#
# Julia + GLMakie + FFMPEG
#
# OLEJ + VODA + NaCl + ŠPINA + ELEKTRICKÉ POLE
#
# Priamo renderuje MP4:
#   olej_voda_nacl_simulacia.mp4
#
# 1920 × 1080
# 60 FPS
# 30 sekúnd
#
# Spustenie:
#   julia olej_voda_nacl_simulacia_mp4.jl

using GLMakie
using Random
using Printf

Random.seed!(11)

# ============================================================
# VIDEO
# ============================================================

const VIDEO_WIDTH  = 1920
const VIDEO_HEIGHT = 1080
const FPS = 60
const VIDEO_SECONDS = 30
const N_FRAMES = VIDEO_SECONDS * FPS

const OUTPUT_FILE = "olej_voda_nacl_simulacia.mp4"

# ============================================================
# PARAMETRE SIMULÁCIE
# ============================================================

const W = 10.0
const H = 16.0
const DT = 0.018

const WATER_LEVEL = 11.2
const OIL_LEVEL = 14.1
const OIL_TOP = 14.9

const EFIELD = 0.65

# Ióny
const N_IONS = 170
const ION_MOBILITY = 0.045
const ION_DIFFUSION = 0.12

# Olejové kvapky
const N_DROPS = 22
const DROP_R = 0.16
const DROP_BUOYANCY = 0.18
const DROP_DRAG = 0.055
const DROP_BROWNIAN = 0.020

# Nečistoty
const N_DIRT = 115
const DIRT_R = 0.055
const DIRT_SETTLING = 0.030
const DIRT_DIFFUSION = 0.045
const DIRT_DRAG = 0.80

# Zachytávanie špiny olejom
const CAPTURE_RADIUS = 0.24
const CAPTURE_PROB = 0.055
const CARRY_DRAG = 0.92

# ============================================================
# STAV ČASTÍC
# ============================================================

drop_x = rand(N_DROPS) .* (W - 1.0) .+ 0.5
drop_y = rand(N_DROPS) .* 2.2 .+ 0.5
drop_vy = zeros(Float64, N_DROPS)

ion_x = rand(N_IONS) .* (W - 0.4) .+ 0.2
ion_y = rand(N_IONS) .* (H - 0.4) .+ 0.2

ion_charge = [
    isodd(i) ? 1.0 : -1.0
    for i in 1:N_IONS
]

dirt_x = rand(N_DIRT) .* (W - 0.5) .+ 0.25
dirt_y = rand(N_DIRT) .* (H - 5.0) .+ 0.3

dirt_vx = zeros(Float64, N_DIRT)
dirt_vy = zeros(Float64, N_DIRT)

captured = falses(N_DIRT)
captured_by = zeros(Int, N_DIRT)

# ============================================================
# OBSERVABLES
# ============================================================

simtime = Observable(0.0)

n_captured = Observable(0)
n_positive = Observable(0)
n_negative = Observable(0)

drop_pts = Observable(Point2f.(drop_x, drop_y))
ion_pts = Observable(Point2f.(ion_x, ion_y))
dirt_pts = Observable(Point2f.(dirt_x, dirt_y))

status = Observable("Spúšťam simuláciu…")

# Pravý graf:
# vektor Point2f zabezpečí, že čas aj hodnota ostanú synchronizované
stat_cap_pts = Observable(Point2f[])
stat_pos_pts = Observable(Point2f[])
stat_neg_pts = Observable(Point2f[])

# ============================================================
# STENY
# ============================================================

function reflect_wall!(x, y, vx, vy, r)

    if x < r
        x = r
        vx = abs(vx) * 0.35
    elseif x > W - r
        x = W - r
        vx = -abs(vx) * 0.35
    end

    if y < r
        y = r
        vy = abs(vy) * 0.15
    elseif y > H - r
        y = H - r
        vy = -abs(vy) * 0.15
    end

    return x, y, vx, vy
end

# ============================================================
# OLEJOVÉ KVAPKY
# ============================================================

function update_drops!()

    for i in 1:N_DROPS

        buoy = DROP_BUOYANCY

        vx = (rand() - 0.5) * 0.035

        drop_vy[i] += DT * (
            buoy -
            DROP_DRAG * drop_vy[i]
        )

        drop_vy[i] += sqrt(DT) * DROP_BROWNIAN * randn()

        drop_x[i] += DT * vx
        drop_y[i] += DT * drop_vy[i]

        # Olejová vrstva
        if drop_y[i] > OIL_TOP
            drop_y[i] = OIL_TOP
            drop_vy[i] *= -0.10
        end

        drop_x[i],
        drop_y[i],
        _,
        drop_vy[i] = reflect_wall!(
            drop_x[i],
            drop_y[i],
            vx,
            drop_vy[i],
            DROP_R
        )
    end
end

# ============================================================
# ŠPINA
# ============================================================

function update_dirt!()

    for j in 1:N_DIRT

        # ----------------------------------------------------
        # ZACHYTENÁ ŠPINA
        # ----------------------------------------------------

        if captured[j]

            i = captured_by[j]

            if i < 1 || i > N_DROPS
                captured[j] = false
                captured_by[j] = 0
                continue
            end

            dirt_x[j] += CARRY_DRAG * (drop_x[i] - dirt_x[j])
            dirt_y[j] += CARRY_DRAG * (drop_y[i] - dirt_y[j])

            # Po dosiahnutí olejovej vrstvy sa špina uvoľní
            if dirt_y[j] > OIL_TOP - 0.7

                captured[j] = false
                captured_by[j] = 0

                dirt_y[j] = 14.1 + 0.25 * rand()

                dirt_x[j] = clamp(
                    dirt_x[j] + 0.12 * randn(),
                    0.3,
                    W - 0.3
                )
            end

            continue
        end

        # ----------------------------------------------------
        # SEDIMENTÁCIA
        # ----------------------------------------------------

        dirt_vy[j] += DT * (
            -DIRT_SETTLING -
            DIRT_DRAG * dirt_vy[j]
        )

        dirt_vy[j] += sqrt(DT) * DIRT_DIFFUSION * randn()

        dirt_x[j] += sqrt(DT) * 0.035 * randn()
        dirt_y[j] += DT * dirt_vy[j]

        # Bočné steny
        if dirt_x[j] < DIRT_R
            dirt_x[j] = DIRT_R
            dirt_vx[j] = abs(dirt_vx[j]) * 0.25
        elseif dirt_x[j] > W - DIRT_R
            dirt_x[j] = W - DIRT_R
            dirt_vx[j] = -abs(dirt_vx[j]) * 0.25
        end

        # Dno
        if dirt_y[j] < DIRT_R

            dirt_y[j] = DIRT_R
            dirt_vy[j] *= -0.10
        end

        # ----------------------------------------------------
        # INTERAKCIA OLEJ – ŠPINA
        # ----------------------------------------------------

        for i in 1:N_DROPS

            dx = dirt_x[j] - drop_x[i]
            dy = dirt_y[j] - drop_y[i]
            d2 = dx * dx + dy * dy

            if d2 < CAPTURE_RADIUS^2 &&
               rand() < CAPTURE_PROB

                captured[j] = true
                captured_by[j] = i

                break
            end
        end
    end

    n_captured[] = count(captured)
end

# ============================================================
# IÓNY
# ============================================================

function update_ions!()

    np = 0
    nn = 0

    for i in 1:N_IONS

        q = ion_charge[i]

        drift = ION_MOBILITY * q * EFIELD

        ion_y[i] += (
            DT * drift +
            sqrt(DT * 2.0 * ION_DIFFUSION) * randn()
        )

        ion_x[i] += (
            sqrt(DT * 2.0 * ION_DIFFUSION) * randn()
        )

        # Bočné steny
        if ion_x[i] < 0.2
            ion_x[i] = 0.2
        elseif ion_x[i] > W - 0.2
            ion_x[i] = W - 0.2
        end

        # Horná a dolná stena
        if ion_y[i] < 0.2
            ion_y[i] = 0.2
        elseif ion_y[i] > H - 0.2
            ion_y[i] = H - 0.2
        end

        if q > 0
            np += 1
        else
            nn += 1
        end
    end

    n_positive[] = np
    n_negative[] = nn
end

# ============================================================
# GRAFIKA
# ============================================================

fig = Figure(
    size = (VIDEO_WIDTH, VIDEO_HEIGHT),
    fontsize = 16
)

# ============================================================
# HLAVNÝ GRAF
# ============================================================

ax = Axis(
    fig[1, 1],
    title = "VODA + OLEJ + NaCl + ŠPINA + ELEKTRICKÉ POLE",
    xlabel = "šírka nádoby",
    ylabel = "výška",
    limits = (0, W, 0, H)
)

# Voda
water_poly = Point2f[
    Point2f(0, 0),
    Point2f(W, 0),
    Point2f(W, WATER_LEVEL),
    Point2f(0, WATER_LEVEL)
]

poly!(
    ax,
    water_poly,
    color = (:deepskyblue, 0.18),
    strokewidth = 0
)

# Olejová vrstva
oil_poly = Point2f[
    Point2f(0, OIL_LEVEL),
    Point2f(W, OIL_LEVEL),
    Point2f(W, H),
    Point2f(0, H)
]

poly!(
    ax,
    oil_poly,
    color = (:gold, 0.18),
    strokewidth = 0
)

# Rozhranie voda – olej
lines!(
    ax,
    [0, W],
    [WATER_LEVEL, WATER_LEVEL],
    linewidth = 3,
    color = :steelblue
)

# Olejové kvapky
scatter!(
    ax,
    drop_pts,
    markersize = 25,
    color = (:orange, 0.85),
    strokewidth = 1,
    strokecolor = :darkorange
)

# Ióny
ion_colors = [
    ion_charge[i] > 0 ? :crimson : :dodgerblue
    for i in 1:N_IONS
]

scatter!(
    ax,
    ion_pts,
    markersize = 9,
    color = ion_colors
)

# Špina
scatter!(
    ax,
    dirt_pts,
    markersize = 7,
    color = :black
)

# Elektrické pole
for x in 1.0:1.0:9.0
    for y in 2.0:2.0:10.0
        arrows!(
            ax,
            [x],
            [y],
            [0.0],
            [0.65],
            arrowsize = 8,
            lengthscale = 0.45,
            linewidth = 1.3,
            color = (:purple, 0.30)
        )
    end
end

# Elektródy
lines!(
    ax,
    [0.5, 9.5],
    [0.15, 0.15],
    linewidth = 8,
    color = :gray20
)

lines!(
    ax,
    [0.5, 9.5],
    [15.85, 15.85],
    linewidth = 8,
    color = :gray20
)

text!(
    ax,
    5.0,
    15.45,
    text = "−  HORNÁ ELEKTRÓDA",
    align = (:center, :center),
    color = :gray20
)

text!(
    ax,
    5.0,
    0.55,
    text = "+  DOLNÁ ELEKTRÓDA",
    align = (:center, :center),
    color = :gray20
)

# Popisy
text!(
    ax,
    0.6,
    12.0,
    text = "VODA",
    color = :steelblue,
    fontsize = 20
)

text!(
    ax,
    0.6,
    14.65,
    text = "OLEJOVÁ VRSTVA",
    color = :darkorange,
    fontsize = 20
)

text!(
    ax,
    0.6,
    10.8,
    text = "rozhranie",
    color = :gray30,
    fontsize = 12
)

# ============================================================
# PRAVÝ GRAF – ŠTATISTIKY
# ============================================================

ax2 = Axis(
    fig[1, 2],
    title = "ŠTATISTIKY",
    xlabel = "čas [s]",
    ylabel = "počet",
    limits = (
        0,
        VIDEO_SECONDS + 1,
        0,
        max(N_IONS + 5, 120)
    )
)

lines!(
    ax2,
    stat_cap_pts,
    linewidth = 3,
    color = :black,
    label = "zachytená špina"
)

lines!(
    ax2,
    stat_pos_pts,
    linewidth = 2,
    color = :crimson,
    label = "Na⁺"
)

lines!(
    ax2,
    stat_neg_pts,
    linewidth = 2,
    color = :dodgerblue,
    label = "Cl⁻"
)

axislegend(
    ax2,
    position = :lt
)

# Stavový riadok
Label(
    fig[2, 1:2],
    status,
    tellwidth = false,
    fontsize = 18
)

# ============================================================
# JEDEN SIMULAČNÝ KROK
# ============================================================

function simulation_step!()

    update_drops!()
    update_dirt!()
    update_ions!()

    t = simtime[] + DT
    simtime[] = t

    # Pridanie nových bodov do pravého grafu
    push!(
        stat_cap_pts[],
        Point2f(t, n_captured[])
    )

    push!(
        stat_pos_pts[],
        Point2f(t, n_positive[])
    )

    push!(
        stat_neg_pts[],
        Point2f(t, n_negative[])
    )

    # Dôležité: push! mení obsah vektora priamo
    notify(stat_cap_pts)
    notify(stat_pos_pts)
    notify(stat_neg_pts)

    # Aktualizácia pozícií častíc
    drop_pts[] = Point2f.(drop_x, drop_y)
    dirt_pts[] = Point2f.(dirt_x, dirt_y)
    ion_pts[] = Point2f.(ion_x, ion_y)

    # Aktualizácia textu
    status[] = @sprintf(
        "t = %.2f s     olejové kvapky = %d     zachytená špina = %d     Na⁺ = %d     Cl⁻ = %d",
        t,
        N_DROPS,
        n_captured[],
        n_positive[],
        n_negative[]
    )
end

# ============================================================
# MP4 RENDER
# ============================================================

println()
println("================================================")
println(" OLEJ + VODA + NaCl — MP4 RENDER")
println("================================================")
println("Výstup:     ", OUTPUT_FILE)
println("Rozlíšenie: ", VIDEO_WIDTH, " × ", VIDEO_HEIGHT)
println("FPS:        ", FPS)
println("Dĺžka:      ", VIDEO_SECONDS, " s")
println("Snímky:     ", N_FRAMES)
println("================================================")
println()

record(
    fig,
    OUTPUT_FILE,
    1:N_FRAMES;
    framerate = FPS
) do frame

    simulation_step!()

    if frame % FPS == 0

        seconds_done = frame ÷ FPS

        @printf(
            "Render: %3d / %3d s\n",
            seconds_done,
            VIDEO_SECONDS
        )
    end
end

println()
println("================================================")
println(" HOTOVO")
println("================================================")
println("MP4 súbor:")
println(abspath(OUTPUT_FILE))
println("================================================")

Za simuláciu ako vždy vďaka GPT, perplexity AI podľa mojich príkazov v Julia Lang ^^^


Author: AarNoma

The first Slovak cyborg 1 system

Comments “Dnes vodný olej so soľou á milá študentka á čistíme mikroplasty: https://hrubos.tech/simulacie/olej_voda_nacl_simulacia.mp4”