Dnes sme diskutovali, či je lepšie dať si do destilovanej vody štipku Na+ alebo Mg2+ Á napadla ma známa analógia: Z ktorého alkoholu sa opijete lepšie? No z toho, ktorý Vás opíja DLHŠIE/POMALŠIE, čiže Metaxa 501 je kvalitnejšia ako Vodka 80% Ukážem prečo: Mg2+ je lepšie ako Na+ na krvnej plazme v simulácií:

Dnes sme diskutovali, či je lepšie dať si do destilovanej vody štipku Na+ alebo Mg2+ Á napadla ma známa analógia: Z ktorého alkoholu sa opijete lepšie? No z toho, ktorý Vás opíja DLHŠIE/POMALŠIE, čiže Metaxa 501 je kvalitnejšia ako Vodka 80% Ukážem prečo: Mg2+ je lepšie ako Na+ na krvnej plazme v simulácií:

Edit2: Prečo komplexované? Viď Edit1: https://www.namaximum.sk/magnezium-8-complex-kapsuly?parameters%5B2%5D=68&utm_source=chatgpt.com

Edit1:

Dnes sme diskutovali o osteo poróze a podľa mojej chemikárky z 9tej triedy ZŠ sme navrhli vyzrážať varom Ca2+ a K+ , aby kosti netvrdli a neredli. Toto bola pointa. Potom bola naša ďalšia otázka, či je lepšie cvrknúť si do tejto vody štipku Na+ alebo Mg2+ https://hrubos.tech/blogy/content/images/20260901191838-Snímka obrazovky 2026-09-01 o 18.29.48.png

No á napadla ma známa analógia: Ak je alkohol kvalitnejší, opíja vás dlhšie, teda Metaxa 501 by mala byť lepšia ako Vodka 80%, lebo ide na vás pomaly. No á toto je v skratke moja simulácia v krvnej plazme. Pozrite sa, za koľko Vás opije magnézium a za koľko sodík:

sodik krvna plazma

https://hrubos.tech/blogy/content/images/20260901192210-Sni%CC%81mka%20obrazovky%202026-09-01%20o%2019.00.35.png

sodik krvna plazma

https://hrubos.tech/blogy/content/images/20260901193247-Sni%CC%81mka%20obrazovky%202026-09-01%20o%2019.00.391.jpg

Teda na sodík 1.27-1.8 sekundy na dosiahnutie rovnováhy v krvnej plazme pri reakcii. Á teraz si pozrite KOMPLEX z tabuľky vyššie, ktorý je termodynamicky výhodnejší:

magnesium krvna plazma https://hrubos.tech/blogy/content/images/20260901192420-Sni%CC%81mka%20obrazovky%202026-09-01%20o%2019.00.34.png

Teda vidíme, že Magnézium ma "opije" za TROJNÁSOBOK ČASU, ako tá Metaxa 501 oproti Vodka 80%

No á aby som to nenaťahoval, simulácia v JuliaLang bola:

bidental chelation

# ============================================================
# MG2+ vs Na+ V KRVNEJ PLAZME
#
# Dynamicka simulacia navratu k rovnovaznemu stavu
#
# 4 panely:
#
#   [1,1] Mg2+ - koncentracia
#   [1,2] Na+  - detail viazanej koncentracie
#   [2,1] Mg2+ - percentualne zastupenie
#   [2,2] Na+  - detail viazanej frakcie
#
# Spolocny cas pre vsetky panely.
#
# Casova zvisla ciara = aktualny frame videa.
# Gulicky = aktualny stav systemu.
#
# ============================================================


# ============================================================
# 1. BALIKY
# ============================================================

using Pkg

Pkg.add("DifferentialEquations")
Pkg.add("CairoMakie")
Pkg.add("FFMPEG")

using DifferentialEquations
using CairoMakie


# ============================================================
# 2. FYZIOLOGICKE REFERENCNE HODNOTY
# ============================================================

# ------------------------------------------------------------
# Mg2+
# ------------------------------------------------------------

Mg_total = 0.85          # mmol/L

Mg_free_fraction    = 0.65
Mg_protein_fraction = 0.27
Mg_complex_fraction = 0.08


@assert isapprox(
    Mg_free_fraction +
    Mg_protein_fraction +
    Mg_complex_fraction,
    1.0
)


# ------------------------------------------------------------
# Na+
# ------------------------------------------------------------

Na_total = 140.0        # mmol/L

# Modelova reprezentacia velmi malej viazanej frakcie
#
# 0.02 % = 0.0002 ako podiel

Na_bound_fraction = 0.0002

Na_free_fraction =
    1.0 - Na_bound_fraction


@assert isapprox(
    Na_free_fraction +
    Na_bound_fraction,
    1.0
)


# ============================================================
# 3. ROVNOVAZNE KONCENTRACIE
# ============================================================

Mg_free_eq =
    Mg_total * Mg_free_fraction

Mg_protein_eq =
    Mg_total * Mg_protein_fraction

Mg_complex_eq =
    Mg_total * Mg_complex_fraction


Na_free_eq =
    Na_total * Na_free_fraction

Na_bound_eq =
    Na_total * Na_bound_fraction


println()
println("================================================")
println("        MG2+ vs Na+ V KRVNEJ PLAZME")
println("================================================")
println()

println("Mg2+")
println("-----------------------------------------------")

println(
    "celkove Mg2+       = ",
    round(Mg_total, digits=4),
    " mmol/L"
)

println(
    "volne Mg2+         = ",
    round(Mg_free_eq, digits=4),
    " mmol/L  (65 %)"
)

println(
    "proteinovo Mg2+    = ",
    round(Mg_protein_eq, digits=4),
    " mmol/L  (27 %)"
)

println(
    "komplexovane Mg2+  = ",
    round(Mg_complex_eq, digits=4),
    " mmol/L  (8 %)"
)

println()

println("Na+")
println("-----------------------------------------------")

println(
    "celkove Na+        = ",
    round(Na_total, digits=4),
    " mmol/L"
)

println(
    "volne Na+          = ",
    round(Na_free_eq, digits=6),
    " mmol/L  (99.98 %)"
)

println(
    "viazane Na+        = ",
    round(Na_bound_eq, digits=6),
    " mmol/L  (0.02 %)"
)

println()


# ============================================================
# 4. KINETICKE PARAMETRE Mg2+
# ============================================================

# Tieto tau su MODELOVE CASOVE KONSTANTY.
#
# Neznamenaju experimentálne namerany cas
# "navratu krvi do rovnovahy".

Mg_tau_protein = 1.8
Mg_tau_complex = 0.9


Mg_k_fp =
    1.0 / Mg_tau_protein

Mg_k_pf =
    1.0 / Mg_tau_protein

Mg_k_fc =
    1.0 / Mg_tau_complex

Mg_k_cf =
    1.0 / Mg_tau_complex


# ============================================================
# 5. Na+ - KINETIKA
# ============================================================

# Chceme, aby modelova rovnovaha bola:
#
# [Na_bound] / [Na_total] = 0.0002
#
# teda 0.02 %.
#
# Pre reakciu:
#
#       Na_free <-> Na_bound
#
# v rovnováhe platí:
#
#       k_forward * free =
#       k_backward * bound
#
# Preto:
#
#       bound/free =
#       k_forward/k_backward
#
# ------------------------------------------------------------

Na_tau = 0.5


Na_k_backward =
    1.0 / Na_tau


# Rovnovazny pomer bound/free

Na_equilibrium_ratio =
    Na_bound_fraction /
    Na_free_fraction


Na_k_forward =
    Na_equilibrium_ratio *
    Na_k_backward


println(
    "Na+ K rovnovazny pomer bound/free = ",
    Na_equilibrium_ratio
)

println(
    "Na+ k_forward  = ",
    Na_k_forward
)

println(
    "Na+ k_backward = ",
    Na_k_backward
)

println()


# ============================================================
# 6. DIFERENCIALNY MODEL Mg2+
# ============================================================

function mg_model!(du, u, p, t)

    free =
        u[1]

    protein =
        u[2]

    complex =
        u[3]


    # --------------------------------------------
    # free <-> protein
    # --------------------------------------------

    forward_protein =
        Mg_k_fp * free

    backward_protein =
        Mg_k_pf * protein


    # --------------------------------------------
    # free <-> complex
    # --------------------------------------------

    forward_complex =
        Mg_k_fc * free

    backward_complex =
        Mg_k_cf * complex


    # --------------------------------------------
    # rovnice
    # --------------------------------------------

    du[1] =
        -forward_protein +
         backward_protein -
         forward_complex +
         backward_complex


    du[2] =
         forward_protein -
         backward_protein


    du[3] =
         forward_complex -
         backward_complex

end


# ============================================================
# 7. DIFERENCIALNY MODEL Na+
# ============================================================

function na_model!(du, u, p, t)

    free =
        u[1]

    bound =
        u[2]


    forward =
        Na_k_forward * free

    backward =
        Na_k_backward * bound


    du[1] =
        -forward +
         backward


    du[2] =
         forward -
         backward

end


# ============================================================
# 8. NARUSENIE ROVNOVAHY - Mg2+
# ============================================================

# Presunieme 20 % komplexovaneho Mg2+
# docasne do volneho poolu.

Mg_perturbation =
    0.20 * Mg_complex_eq


Mg_initial_free =
    Mg_free_eq +
    Mg_perturbation


Mg_initial_protein =
    Mg_protein_eq


Mg_initial_complex =
    Mg_complex_eq -
    Mg_perturbation


Mg_u0 = [
    Mg_initial_free,
    Mg_initial_protein,
    Mg_initial_complex
]


# ============================================================
# 9. NARUSENIE ROVNOVAHY - Na+
# ============================================================

# Presunieme polovicu velmi malej viazanej frakcie
# do volneho Na+ poolu.

Na_perturbation =
    0.50 * Na_bound_eq


Na_initial_free =
    Na_free_eq +
    Na_perturbation


Na_initial_bound =
    Na_bound_eq -
    Na_perturbation


Na_u0 = [
    Na_initial_free,
    Na_initial_bound
]


# ============================================================
# 10. CAS SIMULACIE
# ============================================================

t_start = 0.0
t_end   = 10.0

tspan =
    (t_start, t_end)


# ============================================================
# 11. ODE PROBLEMY
# ============================================================

Mg_prob =
    ODEProblem(
        mg_model!,
        Mg_u0,
        tspan
    )


Na_prob =
    ODEProblem(
        na_model!,
        Na_u0,
        tspan
    )


# ============================================================
# 12. VYRIESENIE ODE
# ============================================================

Mg_sol =
    solve(
        Mg_prob,
        Tsit5(),
        saveat = 0.01
    )


Na_sol =
    solve(
        Na_prob,
        Tsit5(),
        saveat = 0.01
    )


# ============================================================
# 13. DATA Mg2+
# ============================================================

time =
    Mg_sol.t


Mg_free =
    [u[1] for u in Mg_sol.u]

Mg_protein =
    [u[2] for u in Mg_sol.u]

Mg_complex =
    [u[3] for u in Mg_sol.u]


Mg_free_percent =
    100 .* Mg_free ./ Mg_total

Mg_protein_percent =
    100 .* Mg_protein ./ Mg_total

Mg_complex_percent =
    100 .* Mg_complex ./ Mg_total


# ============================================================
# 14. DATA Na+
# ============================================================

Na_free =
    [u[1] for u in Na_sol.u]

Na_bound =
    [u[2] for u in Na_sol.u]


Na_free_percent =
    100 .* Na_free ./ Na_total

Na_bound_percent =
    100 .* Na_bound ./ Na_total


# ============================================================
# 15. KONTROLA KONECNEHO STAVU
# ============================================================

println("================================================")
println("KONTROLA ROVNOVAHY")
println("================================================")

println()

println("Mg2+ konec:")
println(
    "  free    = ",
    round(Mg_free[end], digits=6)
)

println(
    "  protein = ",
    round(Mg_protein[end], digits=6)
)

println(
    "  complex = ",
    round(Mg_complex[end], digits=6)
)

println()

println("Ocakavane:")
println(
    "  free    = ",
    round(Mg_free_eq, digits=6)
)

println(
    "  protein = ",
    round(Mg_protein_eq, digits=6)
)

println(
    "  complex = ",
    round(Mg_complex_eq, digits=6)
)

println()

println("Na+ konec:")
println(
    "  free  = ",
    round(Na_free[end], digits=8)
)

println(
    "  bound = ",
    round(Na_bound[end], digits=8)
)

println()

println("Ocakavane:")
println(
    "  free  = ",
    round(Na_free_eq, digits=8)
)

println(
    "  bound = ",
    round(Na_bound_eq, digits=8)
)

println()


# ============================================================
# 16. FIGURE
# ============================================================

fig =
    Figure(
        size = (1800, 1200),
        fontsize = 20
    )


# ============================================================
# 17. Mg2+ KONCENTRACIA
# ============================================================

ax_Mg_conc =
    Axis(
        fig[1, 1],

        title =
            "Mg2+ — koncentracia",

        xlabel =
            "cas [s]",

        ylabel =
            "mmol/L",

        limits =
            (
                0,
                10,
                0,
                Mg_total * 1.15
            )
    )


lines!(
    ax_Mg_conc,
    time,
    Mg_free,
    linewidth = 4,
    label = "volne Mg2+"
)


lines!(
    ax_Mg_conc,
    time,
    Mg_protein,
    linewidth = 4,
    label = "proteinovo viazane"
)


lines!(
    ax_Mg_conc,
    time,
    Mg_complex,
    linewidth = 4,
    label = "komplexovane"
)


hlines!(
    ax_Mg_conc,
    [Mg_free_eq],
    linestyle = :dash
)


hlines!(
    ax_Mg_conc,
    [Mg_protein_eq],
    linestyle = :dash
)


hlines!(
    ax_Mg_conc,
    [Mg_complex_eq],
    linestyle = :dash
)


axislegend(
    ax_Mg_conc,
    position = :rt
)


# ============================================================
# 18. Na+ KONCENTRACIA - ZOOM
# ============================================================

ax_Na_conc =
    Axis(
        fig[1, 2],

        title =
            "Na+ — detail redistribucie",

        xlabel =
            "cas [s]",

        ylabel =
            "viazany Na+ [mmol/L]",

        limits =
            (
                0,
                10,

                0,

                max(
                    Na_bound_eq * 3,
                    0.001
                )
            )
    )


lines!(
    ax_Na_conc,
    time,
    Na_bound,
    linewidth = 4,
    label = "viazany Na+"
)


hlines!(
    ax_Na_conc,
    [Na_bound_eq],
    linestyle = :dash
)


axislegend(
    ax_Na_conc,
    position = :rt
)


# ============================================================
# 19. Mg2+ PERCENT
# ============================================================

ax_Mg_percent =
    Axis(
        fig[2, 1],

        title =
            "Mg2+ — relativne zastupenie",

        xlabel =
            "cas [s]",

        ylabel =
            "podiel [%]",

        limits =
            (
                0,
                10,
                0,
                75
            )
    )


lines!(
    ax_Mg_percent,
    time,
    Mg_free_percent,
    linewidth = 4,
    label = "volne"
)


lines!(
    ax_Mg_percent,
    time,
    Mg_protein_percent,
    linewidth = 4,
    label = "proteinovo viazane"
)


lines!(
    ax_Mg_percent,
    time,
    Mg_complex_percent,
    linewidth = 4,
    label = "komplexovane"
)


axislegend(
    ax_Mg_percent,
    position = :rt
)


# ============================================================
# 20. Na+ PERCENT - ZOOM
# ============================================================

ax_Na_percent =
    Axis(
        fig[2, 2],

        title =
            "Na+ — detail viazanej frakcie",

        xlabel =
            "cas [s]",

        ylabel =
            "viazany Na+ [%]",

        limits =
            (
                0,
                10,

                0,

                max(
                    0.06,
                    Na_bound_fraction * 100 * 3
                )
            )
    )


lines!(
    ax_Na_percent,
    time,
    Na_bound_percent,
    linewidth = 4,
    label = "viazany Na+"
)


hlines!(
    ax_Na_percent,
    [Na_bound_fraction * 100],
    linestyle = :dash
)


axislegend(
    ax_Na_percent,
    position = :rt
)


# ============================================================
# 21. SPOLOCNY CAS
# ============================================================

current_time =
    Observable(0.0)


# ============================================================
# 22. CASOVE CARY
# ============================================================

function create_time_line(
    axis,
    ymin,
    ymax
)

    x =
        Observable(
            [0.0, 0.0]
        )

    y =
        Observable(
            [ymin, ymax]
        )

    lines!(
        axis,
        x,
        y,
        linewidth = 3,
        linestyle = :dash
    )

    return x, y

end


MgConcX, MgConcY =
    create_time_line(
        ax_Mg_conc,
        0.0,
        Mg_total * 1.15
    )


NaConcX, NaConcY =
    create_time_line(
        ax_Na_conc,
        0.0,
        max(
            Na_bound_eq * 3,
            0.001
        )
    )


MgPercentX, MgPercentY =
    create_time_line(
        ax_Mg_percent,
        0.0,
        75.0
    )


NaPercentX, NaPercentY =
    create_time_line(
        ax_Na_percent,
        0.0,
        max(
            0.06,
            Na_bound_fraction * 100 * 3
        )
    )


# ============================================================
# 23. GULICKY Mg2+
# ============================================================

Mg_dot_time =
    Observable(0.0)


Mg_dot_free =
    Observable(Mg_initial_free)


Mg_dot_protein =
    Observable(Mg_initial_protein)


Mg_dot_complex =
    Observable(Mg_initial_complex)


scatter!(
    ax_Mg_conc,
    Mg_dot_time,
    Mg_dot_free,
    markersize = 18
)


scatter!(
    ax_Mg_conc,
    Mg_dot_time,
    Mg_dot_protein,
    markersize = 18
)


scatter!(
    ax_Mg_conc,
    Mg_dot_time,
    Mg_dot_complex,
    markersize = 18
)


# ============================================================
# 24. GULICKY Na+
# ============================================================

Na_dot_time =
    Observable(0.0)


Na_dot_bound =
    Observable(Na_initial_bound)


scatter!(
    ax_Na_conc,
    Na_dot_time,
    Na_dot_bound,
    markersize = 18
)


# ============================================================
# 25. GULICKY Mg2+ %
# ============================================================

Mg_dot_free_percent =
    Observable(
        100 *
        Mg_initial_free /
        Mg_total
    )


Mg_dot_protein_percent =
    Observable(
        100 *
        Mg_initial_protein /
        Mg_total
    )


Mg_dot_complex_percent =
    Observable(
        100 *
        Mg_initial_complex /
        Mg_total
    )


scatter!(
    ax_Mg_percent,
    Mg_dot_time,
    Mg_dot_free_percent,
    markersize = 18
)


scatter!(
    ax_Mg_percent,
    Mg_dot_time,
    Mg_dot_protein_percent,
    markersize = 18
)


scatter!(
    ax_Mg_percent,
    Mg_dot_time,
    Mg_dot_complex_percent,
    markersize = 18
)


# ============================================================
# 26. GULICKA Na+ %
# ============================================================

Na_dot_bound_percent =
    Observable(
        100 *
        Na_initial_bound /
        Na_total
    )


scatter!(
    ax_Na_percent,
    Na_dot_time,
    Na_dot_bound_percent,
    markersize = 18
)


# ============================================================
# 27. HLAVNY CASOVY TEXT
# ============================================================

time_label =
    Observable(
        "t = 0.00 s"
    )


Label(
    fig[3, 1:2],

    time_label,

    fontsize = 30,

    tellwidth = false,

    halign = :center
)


# ============================================================
# 28. MP4
# ============================================================

output_file =
    "mg2_vs_na_plasma_equilibrium.mp4"


println()
println("================================================")
println("START RENDEROVANIA MP4")
println("================================================")

println(
    "Subor: ",
    output_file
)

println(
    "Pocet framov: ",
    length(time)
)

println()


# ============================================================
# 29. ANIMACIA
# ============================================================

record(
    fig,
    output_file,
    1:length(time);

    framerate = 30
) do i


    # ========================================================
    # JEDEN SPOLOCNY CAS
    # ========================================================

    t =
        time[i]


    current_time[] =
        t


    time_label[] =
        "t = $(round(t, digits=2)) s"


    # ========================================================
    # CASOVE CARY
    # ========================================================

    MgConcX[] =
        [t, t]


    MgConcY[] =
        [
            0.0,
            Mg_total * 1.15
        ]


    NaConcX[] =
        [t, t]


    NaConcY[] =
        [
            0.0,
            max(
                Na_bound_eq * 3,
                0.001
            )
        ]


    MgPercentX[] =
        [t, t]


    MgPercentY[] =
        [0.0, 75.0]


    NaPercentX[] =
        [t, t]


    NaPercentY[] =
        [
            0.0,
            max(
                0.06,
                Na_bound_fraction * 100 * 3
            )
        ]


    # ========================================================
    # Mg2+ KONCENTRACIA
    # ========================================================

    Mg_dot_time[] =
        t


    Mg_dot_free[] =
        Mg_sol.u[i][1]


    Mg_dot_protein[] =
        Mg_sol.u[i][2]


    Mg_dot_complex[] =
        Mg_sol.u[i][3]


    # ========================================================
    # Na+ KONCENTRACIA
    # ========================================================

    Na_dot_time[] =
        t


    Na_dot_bound[] =
        Na_sol.u[i][2]


    # ========================================================
    # Mg2+ PERCENT
    # ========================================================

    Mg_dot_free_percent[] =
        100 *
        Mg_sol.u[i][1] /
        Mg_total


    Mg_dot_protein_percent[] =
        100 *
        Mg_sol.u[i][2] /
        Mg_total


    Mg_dot_complex_percent[] =
        100 *
        Mg_sol.u[i][3] /
        Mg_total


    # ========================================================
    # Na+ PERCENT
    # ========================================================

    Na_dot_bound_percent[] =
        100 *
        Na_sol.u[i][2] /
        Na_total

end


# ============================================================
# 30. KONIEC
# ============================================================

println()
println("================================================")
println("HOTOVO")
println("================================================")

println(
    "Vystupny subor:"
)

println(
    abspath(output_file)
)

println()

Za pomoc ďakujem: Mojej mamine za prednášku, ako sa mám opíjať pomaly á za simuláciu podľa príkazov ďakujem GPT a Ideogram AI :)


Author: AarNoma

The first Slovak cyborg 1 system

Comments “Dnes sme diskutovali, či je lepšie dať si do destilovanej vody štipku Na+ alebo Mg2+ Á napadla ma známa analógia: Z ktorého alkoholu sa opijete lepšie? No z toho, ktorý Vás opíja DLHŠIE/POMALŠIE, čiže Metaxa 501 je kvalitnejšia ako Vodka 80% Ukážem prečo: Mg2+ je lepšie ako Na+ na krvnej plazme v simulácií:”