121 lines
4.2 KiB
Lua
121 lines
4.2 KiB
Lua
-- ============================================================================
|
|
-- SPDX-License-Identifier: GPL-3.0-or-later
|
|
-- Copyright (C) 2026 Alexander Allan (MDMAchine) -- A&E Concepts
|
|
--
|
|
-- This program is free software: you can redistribute it and/or modify
|
|
-- it under the terms of the GNU General Public License as published by
|
|
-- the Free Software Foundation, either version 3 of the License, or
|
|
-- (at your option) any later version.
|
|
--
|
|
-- This program is distributed in the hope that it will be useful,
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
-- GNU General Public License for more details: https://www.gnu.org/licenses/
|
|
-- ============================================================================
|
|
|
|
-- MD HAP Scheduler v1.0 — Hamiltonian Action-Principle
|
|
-- MDMAchine | A&E Concepts © 2026
|
|
--
|
|
-- Port of hap_scheduler_core.py calculate_hap_sigmas() to HOT-Step-CPP Lua.
|
|
--
|
|
-- WHAT THIS DOES:
|
|
-- Simulates a particle falling through a gravitational potential well with
|
|
-- atmospheric drag. Maps the particle's velocity to sigma step sizes.
|
|
--
|
|
-- velocity(t) = (1 + kinetic_energy * t) * exp(-damping_friction * t)
|
|
--
|
|
-- - kinetic_energy: initial boost — stretches steps in the middle of the run
|
|
-- (particle accelerates as it falls into the well)
|
|
-- - damping_friction: atmospheric drag — compresses steps at the end
|
|
-- (particle slows as drag increases with velocity)
|
|
--
|
|
-- distance = cumsum(velocity) → normalize → map to sigma space
|
|
--
|
|
-- HIGH kinetic_energy: more steps in the mid-sigma zone (structure formation)
|
|
-- HIGH damping_friction: more steps compressed toward the end (detail refinement)
|
|
--
|
|
-- This is the HAP component of the HT scheduler (used standalone here).
|
|
-- ============================================================================
|
|
|
|
scheduler = {
|
|
name = "md_hap",
|
|
display = "MD HAP (Hamiltonian Potential Well)",
|
|
description = "Particle-in-potential-well sigma schedule. Kinetic energy stretches mid steps, damping friction compresses end steps. Port of hap_scheduler_core v1.0.",
|
|
params = {
|
|
{
|
|
key = "kinetic_energy",
|
|
type = "slider",
|
|
label = "Kinetic Energy",
|
|
default = 1.0,
|
|
min = 0.0,
|
|
max = 5.0,
|
|
step = 0.1,
|
|
hint = "Initial velocity boost. Stretches steps in the middle of the trajectory (structure formation zone).",
|
|
},
|
|
{
|
|
key = "damping_friction",
|
|
type = "slider",
|
|
label = "Damping Friction",
|
|
default = 0.5,
|
|
min = 0.0,
|
|
max = 8.0,
|
|
step = 0.1,
|
|
hint = "Atmospheric drag. Compresses steps toward the end (detail refinement zone). Higher=more end compression.",
|
|
},
|
|
},
|
|
}
|
|
|
|
local EPSILON = 1e-6
|
|
|
|
local function clamp(v, lo, hi)
|
|
if v < lo then return lo end
|
|
if v > hi then return hi end
|
|
return v
|
|
end
|
|
|
|
function schedule(output, num_steps, shift)
|
|
local ke = (params and params.kinetic_energy) or 1.5
|
|
local df = (params and params.damping_friction) or 3.0
|
|
|
|
-- Compute velocity at each normalized time point
|
|
local velocity = {}
|
|
for i = 0, num_steps - 1 do
|
|
local t = i / math.max(num_steps - 1, 1)
|
|
local v = (1.0 + ke * t) * math.exp(-df * t)
|
|
velocity[i] = math.max(v, EPSILON) -- never negative
|
|
end
|
|
|
|
-- Integrate: cumulative distance
|
|
local distance = {}
|
|
distance[0] = 0.0
|
|
local running = 0.0
|
|
for i = 0, num_steps - 1 do
|
|
running = running + velocity[i]
|
|
distance[i + 1] = running
|
|
end
|
|
|
|
-- Normalize and map to sigma [1.0 → 0.0]
|
|
local total = distance[num_steps]
|
|
if total < EPSILON then total = EPSILON end
|
|
|
|
local sigmas = {}
|
|
for i = 0, num_steps do
|
|
sigmas[i] = 1.0 - (distance[i] / total)
|
|
end
|
|
|
|
sigmas[0] = 1.0
|
|
sigmas[num_steps] = 0.0
|
|
|
|
-- Shift warp
|
|
if shift ~= 1.0 then
|
|
for i = 0, num_steps do
|
|
local t = sigmas[i]
|
|
sigmas[i] = shift * t / (1.0 + (shift - 1.0) * t)
|
|
end
|
|
end
|
|
|
|
for i = 0, num_steps - 1 do
|
|
output[i] = sigmas[i]
|
|
end
|
|
end
|