| Name | mini-ode JSON |
| Version |
0.1.3
JSON |
| download |
| home_page | None |
| Summary | A minimalistic ODE solvers library built on top of PyTorch |
| upload_time | 2025-10-26 19:10:27 |
| maintainer | None |
| docs_url | None |
| author | None |
| requires_python | <3.15,>=3.14 |
| license | GPL-2.0 |
| keywords |
simulation
math
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
# mini-ode
A minimalistic, multi-language library for solving Ordinary Differential Equations (ODEs). `mini-ode` is designed with a shared Rust core and a consistent interface for both **Rust** and **Python** users. It supports explicit, implicit, fixed step and adaptive step algorithms.
[](CRATESIO_VERSION) [](CRATESIO_DOWNLOADS)
[](PYPI_VERSION) [](PYPI_MONTHLY_DOWNLOADS)
[](LICENSE)
## ✨ Features
- **Dual interface**: call the same solvers from Rust or Python
- **PyTorch-compatible**: define the derivative function using PyTorch
- **Multiple solver methods**: includes explicit, implicit, and adaptive-step solvers
- **Modular optimizers**: implicit solvers allow flexible optimizer configuration
## 🧠 Supported Solvers
| Solver Class | Method | Suitable For | Implicit | Adaptive Step |
|----------------------------|----------------------------------------|----------------------------------------------|----------|----------------|
| `EulerMethodSolver` | Euler | Simple, fast, and educational use. | ❌ | ❌ |
| `RK4MethodSolver` | Runge-Kutta 4th Order (RK4) | General-purpose with fixed step size. | ❌ | ❌ |
| `ImplicitEulerMethodSolver`| Implicit Euler | Stiff or ill-conditioned problems. | ✅ | ❌ |
| `GLRK4MethodSolver` | Gauss-Legendre RK (Order 4) | High-accuracy, stiff problems. | ✅ | ❌ |
| `RKF45MethodSolver` | Runge-Kutta-Fehlberg 4(5) | Adaptive step size control. | ❌ | ✅ |
| `ROW1MethodSolver` | Rosenbrock-Wanner (Order 1) | Fast semi-implicit method for stiff systems. | semi | ❌ |
## 📦 Building the Library
### Rust
To build the core Rust library:
```bash
cd mini-ode
cargo build --release
```
### Python
To build and install the Python package (in a virtual environment or Conda environment):
```bash
cd mini-ode-python
LIBTORCH_USE_PYTORCH=1 maturin develop
```
> This builds the Python bindings using [`maturin`](https://github.com/PyO3/maturin) and installs the package locally.
## 🐍 Python Usage Overview
To use `mini-ode` from Python:
1. Define the derivative function using `torch.Tensor` inputs.
2. **Trace** the function using `torch.jit.trace`.
3. Pass the traced function and initial conditions to a solver instance.
4. For implicit solvers, pass an optimizer at construction.
Example usage flow (not full code):
```python
import torch
import mini_ode
# 1. Define derivative function using PyTorch
def f(x: torch.Tensor, y: torch.Tensor):
return y.flip(0) - torch.tensor([0, 1]) * (y.flip(0) ** 3)
# 2. Trace the function to TorchScript
traced_f = torch.jit.trace(f, (torch.tensor(0.), torch.tensor([[0., 0.]])))
# 3. Create a solver instance
solver = mini_ode.RK4MethodSolver(step=0.01)
# 4. Solve the ODE
xs, ys = solver.solve(traced_f, torch.tensor([0., 5.]), torch.tensor([1.0, 0.0]))
```
### 🔧 Using Optimizers (Implicit Solvers Only)
Some solvers like `GLRK4MethodSolver` or `ImplicitEulerMethodSolver` require an optimizer for nonlinear system solving:
```python
optimizer = mini_ode.optimizers.CG(
max_steps=5,
gtol=1e-8,
linesearch_atol=1e-6
)
solver = mini_ode.GLRK4MethodSolver(step=0.2, optimizer=optimizer)
```
## 🦀 Rust Usage Overview
In Rust, solvers use the same logic as in Python - but you pass in a `tch::CModule` representing the TorchScripted derivative function.
**Example 1:** Load a TorchScript model from file
This approach uses a model traced in Python (e.g., with `torch.jit.trace`) and saved to disk.
```rust
use mini_ode::Solver;
use tch::{Tensor, CModule};
fn main() -> anyhow::Result<()> {
let solver = Solver::Euler { step: 0.01 };
let model = CModule::load("my_traced_function.pt")?;
let x_span = Tensor::from_slice(&[0.0f64, 2.0]);
let y0 = Tensor::from_slice(&[1.0f64, 0.0]);
let (xs, ys) = solver.solve(model, x_span, y0)?;
println!("{:?}", xs);
Ok(())
}
```
**Example 2:** Trace the derivative function directly in Rust
You can also define and trace the derivative function in Rust using `CModule::create_by_tracing`.
```rust
use mini_ode::Solver;
use tch::{Tensor, CModule};
fn main() -> anyhow::Result<()> {
// Initial value for tracing
let y0 = Tensor::from_slice(&[1.0f64, 0.0]);
// Define the derivative function closure
let mut closure = |inputs: &[Tensor]| {
let x = &inputs[0];
let y = &inputs[1];
let flipped = y.flip(0);
let dy = &flipped - &(&flipped.pow_tensor_scalar(3.0) * Tensor::from_slice(&[0.0, 1.0]));
vec![dy]
};
// Trace the model directly in Rust
let model = CModule::create_by_tracing(
"ode_fn",
"forward",
&[Tensor::from(0.0), y0.shallow_clone()],
&mut closure,
)?;
// Use an adaptive solver, for example
let solver = Solver::RKF45 {
rtol: 0.00001,
atol: 0.00001,
min_step: 1e-9,
safety_factor: 0.9
};
let x_span = Tensor::from_slice(&[0.0f64, 5.0]);
let (xs, ys) = solver.solve(model, x_span, y0)?;
println!("Final state: {:?}", ys);
Ok(())
}
```
## 📁 Project Structure
```
mini-ode/ # Core Rust implementation of solvers
mini-ode-python/ # Python bindings using PyO3 + maturin
example.ipynb # Jupyter notebook demonstrating usage
```
## 📄 License
This project is licensed under the [GPL-2.0 License](LICENSE).
## 👤 Author
**Antoni Przybylik**
📧 [antoni@taon.io](mailto:antoni@taon.io)
📧 [antoni.przybylik@wp.pl](mailto:antoni.przybylik@wp.pl)
🔗 [https://github.com/antoniprzybylik](https://github.com/antoniprzybylik)
Raw data
{
"_id": null,
"home_page": null,
"name": "mini-ode",
"maintainer": null,
"docs_url": null,
"requires_python": "<3.15,>=3.14",
"maintainer_email": null,
"keywords": "simulation, math",
"author": null,
"author_email": "Antoni Przybylik <antoni.przybylik@wp.pl>",
"download_url": null,
"platform": null,
"description": "# mini-ode\n\nA minimalistic, multi-language library for solving Ordinary Differential Equations (ODEs). `mini-ode` is designed with a shared Rust core and a consistent interface for both **Rust** and **Python** users. It supports explicit, implicit, fixed step and adaptive step algorithms.\n\n[](CRATESIO_VERSION) [](CRATESIO_DOWNLOADS) \n[](PYPI_VERSION) [](PYPI_MONTHLY_DOWNLOADS) \n[](LICENSE)\n\n## \u2728 Features\n\n- **Dual interface**: call the same solvers from Rust or Python\n- **PyTorch-compatible**: define the derivative function using PyTorch\n- **Multiple solver methods**: includes explicit, implicit, and adaptive-step solvers\n- **Modular optimizers**: implicit solvers allow flexible optimizer configuration\n\n## \ud83e\udde0 Supported Solvers\n\n| Solver Class | Method | Suitable For | Implicit | Adaptive Step |\n|----------------------------|----------------------------------------|----------------------------------------------|----------|----------------|\n| `EulerMethodSolver` | Euler | Simple, fast, and educational use. | \u274c | \u274c |\n| `RK4MethodSolver` | Runge-Kutta 4th Order (RK4) | General-purpose with fixed step size. | \u274c | \u274c |\n| `ImplicitEulerMethodSolver`| Implicit Euler | Stiff or ill-conditioned problems. | \u2705 | \u274c |\n| `GLRK4MethodSolver` | Gauss-Legendre RK (Order 4) | High-accuracy, stiff problems. | \u2705 | \u274c |\n| `RKF45MethodSolver` | Runge-Kutta-Fehlberg 4(5) | Adaptive step size control. | \u274c | \u2705 |\n| `ROW1MethodSolver` | Rosenbrock-Wanner (Order 1) | Fast semi-implicit method for stiff systems. | semi | \u274c |\n\n## \ud83d\udce6 Building the Library\n\n### Rust\n\nTo build the core Rust library:\n\n```bash\ncd mini-ode\ncargo build --release\n```\n\n### Python\n\nTo build and install the Python package (in a virtual environment or Conda environment):\n\n```bash\ncd mini-ode-python\nLIBTORCH_USE_PYTORCH=1 maturin develop\n```\n\n> This builds the Python bindings using [`maturin`](https://github.com/PyO3/maturin) and installs the package locally.\n\n## \ud83d\udc0d Python Usage Overview\n\nTo use `mini-ode` from Python:\n\n1. Define the derivative function using `torch.Tensor` inputs.\n2. **Trace** the function using `torch.jit.trace`.\n3. Pass the traced function and initial conditions to a solver instance.\n4. For implicit solvers, pass an optimizer at construction.\n\nExample usage flow (not full code):\n\n```python\nimport torch\nimport mini_ode\n\n# 1. Define derivative function using PyTorch\ndef f(x: torch.Tensor, y: torch.Tensor):\n return y.flip(0) - torch.tensor([0, 1]) * (y.flip(0) ** 3)\n\n# 2. Trace the function to TorchScript\ntraced_f = torch.jit.trace(f, (torch.tensor(0.), torch.tensor([[0., 0.]])))\n\n# 3. Create a solver instance\nsolver = mini_ode.RK4MethodSolver(step=0.01)\n\n# 4. Solve the ODE\nxs, ys = solver.solve(traced_f, torch.tensor([0., 5.]), torch.tensor([1.0, 0.0]))\n```\n\n### \ud83d\udd27 Using Optimizers (Implicit Solvers Only)\n\nSome solvers like `GLRK4MethodSolver` or `ImplicitEulerMethodSolver` require an optimizer for nonlinear system solving:\n\n```python\noptimizer = mini_ode.optimizers.CG(\n max_steps=5,\n gtol=1e-8,\n linesearch_atol=1e-6\n)\n\nsolver = mini_ode.GLRK4MethodSolver(step=0.2, optimizer=optimizer)\n```\n\n## \ud83e\udd80 Rust Usage Overview\n\nIn Rust, solvers use the same logic as in Python - but you pass in a `tch::CModule` representing the TorchScripted derivative function.\n\n**Example 1:** Load a TorchScript model from file\n\nThis approach uses a model traced in Python (e.g., with `torch.jit.trace`) and saved to disk.\n\n```rust\nuse mini_ode::Solver;\nuse tch::{Tensor, CModule};\n\nfn main() -> anyhow::Result<()> {\n let solver = Solver::Euler { step: 0.01 };\n let model = CModule::load(\"my_traced_function.pt\")?;\n let x_span = Tensor::from_slice(&[0.0f64, 2.0]);\n let y0 = Tensor::from_slice(&[1.0f64, 0.0]);\n\n let (xs, ys) = solver.solve(model, x_span, y0)?;\n println!(\"{:?}\", xs);\n Ok(())\n}\n```\n\n**Example 2:** Trace the derivative function directly in Rust\n\nYou can also define and trace the derivative function in Rust using `CModule::create_by_tracing`.\n\n```rust\nuse mini_ode::Solver;\nuse tch::{Tensor, CModule};\n\nfn main() -> anyhow::Result<()> {\n // Initial value for tracing\n let y0 = Tensor::from_slice(&[1.0f64, 0.0]);\n\n // Define the derivative function closure\n let mut closure = |inputs: &[Tensor]| {\n let x = &inputs[0];\n let y = &inputs[1];\n let flipped = y.flip(0);\n let dy = &flipped - &(&flipped.pow_tensor_scalar(3.0) * Tensor::from_slice(&[0.0, 1.0]));\n vec![dy]\n };\n\n // Trace the model directly in Rust\n let model = CModule::create_by_tracing(\n \"ode_fn\",\n \"forward\",\n &[Tensor::from(0.0), y0.shallow_clone()],\n &mut closure,\n )?;\n\n // Use an adaptive solver, for example\n let solver = Solver::RKF45 {\n rtol: 0.00001,\n atol: 0.00001,\n min_step: 1e-9,\n safety_factor: 0.9\n };\n let x_span = Tensor::from_slice(&[0.0f64, 5.0]);\n\n let (xs, ys) = solver.solve(model, x_span, y0)?;\n println!(\"Final state: {:?}\", ys);\n Ok(())\n}\n```\n\n## \ud83d\udcc1 Project Structure\n\n```\nmini-ode/ # Core Rust implementation of solvers\nmini-ode-python/ # Python bindings using PyO3 + maturin\nexample.ipynb # Jupyter notebook demonstrating usage\n```\n\n## \ud83d\udcc4 License\n\nThis project is licensed under the [GPL-2.0 License](LICENSE).\n\n## \ud83d\udc64 Author\n\n**Antoni Przybylik** \n\ud83d\udce7 [antoni@taon.io](mailto:antoni@taon.io) \n\ud83d\udce7 [antoni.przybylik@wp.pl](mailto:antoni.przybylik@wp.pl) \n\ud83d\udd17 [https://github.com/antoniprzybylik](https://github.com/antoniprzybylik)\n\n",
"bugtrack_url": null,
"license": "GPL-2.0",
"summary": "A minimalistic ODE solvers library built on top of PyTorch",
"version": "0.1.3",
"project_urls": {
"Homepage": "https://github.com/antoniprzybylik/mini-ode",
"Source": "https://github.com/antoniprzybylik/mini-ode"
},
"split_keywords": [
"simulation",
" math"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "2a0a4f16cc01d81d692f0131969f7a8c5852264c7191e45a6674384f5946eaa0",
"md5": "15d52ff8e5a9212117b6686cc5084a54",
"sha256": "bdbb69d346d3c48ec51b6be3b1d104750eca842af6fdb2d2a57a60eb46ba09da"
},
"downloads": -1,
"filename": "mini_ode-0.1.3-cp313-abi3-manylinux_2_39_x86_64.whl",
"has_sig": false,
"md5_digest": "15d52ff8e5a9212117b6686cc5084a54",
"packagetype": "bdist_wheel",
"python_version": "cp313",
"requires_python": "<3.15,>=3.14",
"size": 470322,
"upload_time": "2025-10-26T19:10:27",
"upload_time_iso_8601": "2025-10-26T19:10:27.539987Z",
"url": "https://files.pythonhosted.org/packages/2a/0a/4f16cc01d81d692f0131969f7a8c5852264c7191e45a6674384f5946eaa0/mini_ode-0.1.3-cp313-abi3-manylinux_2_39_x86_64.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-26 19:10:27",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "antoniprzybylik",
"github_project": "mini-ode",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "mini-ode"
}