sciforge 0.0.3

A comprehensive scientific computing library in pure Rust with zero dependencies
Documentation
use crate::constants::{E_CHARGE, EPSILON_0, FARADAY, K_B, R_GAS};

pub fn nernst_potential(
    z: f64,
    temperature: f64,
    concentration_out: f64,
    concentration_in: f64,
) -> f64 {
    let t_k = temperature + 273.15;
    (R_GAS * t_k / (z * FARADAY)) * (concentration_out / concentration_in).ln()
}

pub fn goldman_hodgkin_katz(
    pk: f64,
    k_out: f64,
    k_in: f64,
    pna: f64,
    na_out: f64,
    na_in: f64,
    pcl: f64,
    cl_out: f64,
    cl_in: f64,
    temperature: f64,
) -> f64 {
    let t_k = temperature + 273.15;
    let rt_f = K_B * t_k / E_CHARGE;
    let numerator = pk * k_out + pna * na_out + pcl * cl_in;
    let denominator = pk * k_in + pna * na_in + pcl * cl_out;
    rt_f * (numerator / denominator).ln() * 1000.0
}

pub fn cable_equation_steady_state(v0: f64, x: f64, lambda: f64) -> f64 {
    v0 * (-x.abs() / lambda).exp()
}

pub fn membrane_time_constant(rm: f64, cm: f64) -> f64 {
    rm * cm
}

pub fn length_constant(rm: f64, ri: f64) -> f64 {
    (rm / ri).sqrt()
}

pub fn gap_junction_conductance(
    n_channels: f64,
    single_channel_conductance: f64,
    open_probability: f64,
) -> f64 {
    n_channels * single_channel_conductance * open_probability
}

pub fn electrodiffusion_flux(
    permeability: f64,
    z: f64,
    vm: f64,
    c_out: f64,
    c_in: f64,
    temperature: f64,
) -> f64 {
    let t_k = temperature + 273.15;
    let u = z * E_CHARGE * vm / (K_B * t_k);
    if u.abs() < 1e-6 {
        return permeability * z * FARADAY * (c_out - c_in);
    }
    permeability * z * FARADAY * u * (c_in * u.exp() - c_out) / (u.exp() - 1.0)
}

pub fn hodgkin_huxley_sodium_current(g_na: f64, m: f64, h: f64, v: f64, e_na: f64) -> f64 {
    g_na * m.powi(3) * h * (v - e_na)
}

pub fn hodgkin_huxley_potassium_current(g_k: f64, n: f64, v: f64, e_k: f64) -> f64 {
    g_k * n.powi(4) * (v - e_k)
}

pub fn hodgkin_huxley_leak_current(g_l: f64, v: f64, e_l: f64) -> f64 {
    g_l * (v - e_l)
}

pub fn hodgkin_huxley_dv_dt(cm: f64, i_ext: f64, i_na: f64, i_k: f64, i_l: f64) -> f64 {
    (i_ext - i_na - i_k - i_l) / cm
}

pub fn gating_alpha_n(v: f64) -> f64 {
    let dv = v + 55.0;
    if dv.abs() < 1e-6 {
        return 0.1;
    }
    0.01 * dv / (1.0 - (-0.1 * dv).exp())
}

pub fn gating_beta_n(v: f64) -> f64 {
    0.125 * (-(v + 65.0) / 80.0).exp()
}

pub fn gating_alpha_m(v: f64) -> f64 {
    let dv = v + 40.0;
    if dv.abs() < 1e-6 {
        return 1.0;
    }
    0.1 * dv / (1.0 - (-0.1 * dv).exp())
}

pub fn gating_beta_m(v: f64) -> f64 {
    4.0 * (-(v + 65.0) / 18.0).exp()
}

pub fn gating_alpha_h(v: f64) -> f64 {
    0.07 * (-(v + 65.0) / 20.0).exp()
}

pub fn gating_beta_h(v: f64) -> f64 {
    1.0 / (1.0 + (-(v + 35.0) / 10.0).exp())
}

pub fn gating_steady_state(alpha: f64, beta: f64) -> f64 {
    alpha / (alpha + beta)
}

pub fn gating_time_constant(alpha: f64, beta: f64) -> f64 {
    1.0 / (alpha + beta)
}

pub fn reversal_potential_two_ion(g1: f64, e1: f64, g2: f64, e2: f64) -> f64 {
    (g1 * e1 + g2 * e2) / (g1 + g2)
}

pub fn membrane_capacitance_current(cm: f64, dv_dt: f64) -> f64 {
    cm * dv_dt
}

pub fn ion_channel_open_probability(v: f64, v_half: f64, slope: f64) -> f64 {
    1.0 / (1.0 + (-(v - v_half) / slope).exp())
}

pub fn synaptic_conductance_alpha(g_max: f64, t: f64, tau: f64) -> f64 {
    g_max * (t / tau) * (-1.0 + t / tau).exp().recip() * (-(t / tau)).exp()
}

pub fn synaptic_current(g_syn: f64, v_post: f64, e_syn: f64) -> f64 {
    g_syn * (v_post - e_syn)
}

pub fn calcium_nernst(temperature: f64, ca_out: f64, ca_in: f64) -> f64 {
    nernst_potential(2.0, temperature, ca_out, ca_in)
}

pub fn chloride_equilibrium(temperature: f64, cl_out: f64, cl_in: f64) -> f64 {
    nernst_potential(-1.0, temperature, cl_out, cl_in)
}

pub fn resting_potential_contribution(
    conductance: f64,
    reversal: f64,
    total_conductance: f64,
) -> f64 {
    conductance * reversal / total_conductance
}

pub fn space_clamp_error(distance: f64, lambda: f64) -> f64 {
    1.0 - (-distance / lambda).exp()
}

pub fn action_potential_threshold_estimate(v_rest: f64, depolarization: f64) -> f64 {
    v_rest + depolarization
}

pub fn conduction_velocity(diameter: f64, myelinated: bool) -> f64 {
    if myelinated {
        6.0 * diameter
    } else {
        diameter.sqrt()
    }
}

pub fn saltatory_conduction_delay(internode_distance: f64, velocity: f64) -> f64 {
    internode_distance / velocity
}

pub fn membrane_resistance_per_area(resistivity: f64, thickness: f64) -> f64 {
    resistivity * thickness
}

pub fn specific_membrane_capacitance(epsilon_r: f64, thickness: f64) -> f64 {
    epsilon_r * EPSILON_0 / thickness
}