Skip to content
Get started

Get started

Run a small model, then change it and see the difference. You need two files and a Python environment. The example below works with the published Eqiora 0.1.3 package; no source checkout, Rust compiler, mesh generator or editor extension is needed.

Prebuilt wheels support Linux x86-64 and ordinary-GIL CPython 3.11–3.14. These commands select CPython 3.13. Install uv if you do not have it, then create a project:

Terminal windowbash
uv init --python 3.13 first-eqiora-model
cd first-eqiora-model
uv add eqiora

In an existing uv project, just run uv add eqiora. This installs the published package from PyPI and records the dependency in pyproject.toml and uv.lock. Use uv add eqiora==0.1.3 if you want to select the release used for this walkthrough explicitly. Keep the lockfile with your project to reproduce its environment.

Save the following files in the project folder, beside pyproject.toml. No shell activation is needed: uv run uses the project’s environment. Lessons that run repository scripts use the optional example files. Downloading those files does not require rebuilding Eqiora.

Let a dimensionless quantity xx start at 1 and decay at rate k=1 s−1k=1\,\mathrm{s}^{-1}:

dxdt+kx=0,x(0)=1.\frac{\mathrm{d}x}{\mathrm{d}t}+kx=0,\qquad x(0)=1.

The solution is x(t)=exp⁡(−kt)x(t)=\exp(-kt). After one second, predict x(1)=exp⁡(−1)≈0.367879x(1)=\exp(-1)\approx0.367879—about 37% of the initial value.

Download decay.eqi, or copy this complete source into a file named decay.eqi:

decay.eqi
// A minimal implicit ODE: x decays at the rate supplied by the user.
model decay() {
// `x` is dimensionless and starts at 1. `rate` has inverse-time units.
state x: 1;
initial { x = 1; }
parameter rate: 1 / s = 1;
// Eqiora writes the evolution law as a residual equal to zero.
relation flow {
derivative(x) + rate * x = 0;
}
}

The .eqi file describes the model. state x declares the evolving unknown and initial { x = 1; } sets its initial condition, parameter rate has inverse-second units, and relation states the equation. The numerical method is chosen in the run script, not here.

Download run.py, or copy this complete script into run.py in the same folder:

run.py
"""Run the decay model shared by Get started and the ODE lesson."""
from __future__ import annotations
import argparse
from pathlib import Path
import eqiora
OUTPUT_TIMES_S = (0.25, 0.5, 1.0)
def solve(source_path: Path) -> tuple[tuple[float, float], ...]:
"""Return the requested (time in seconds, dimensionless value) samples."""
model = eqiora.compile(path=source_path)
field = model.field(model.field_ids[0])
plan = eqiora.resolve(
model,
temporal=eqiora.time.Tsitouras45(
initial_step_s=0.01,
relative_tolerance=1.0e-9,
absolute_tolerances={(field, 0, 0, False): 1.0e-11},
),
)
result = eqiora.run(
plan,
state=eqiora.State.initial(plan),
until_s=OUTPUT_TIMES_S[-1],
output_times_s=OUTPUT_TIMES_S,
)
series = result.series(field)
times = series.time.numpy()
values = series.values.numpy()
return tuple(
(float(time_s), float(value))
for time_s, value in zip(times, values, strict=True)
)
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("model", nargs="?", type=Path, default=Path("decay.eqi"))
args = parser.parse_args()
for time_s, value in solve(args.model):
print(f"t={time_s:.2f}, x={value:.10f}")
if __name__ == "__main__":
main()

The script compiles decay.eqi, chooses an adaptive time method, starts from the model’s initial state and requests three observations. The returned Result contains a time series selected by the model’s field handle. The two NumPy arrays hold times in seconds and the corresponding dimensionless values.

Terminal windowbash
uv run python run.py

You should see values close to:

text
t=0.25, x=0.7788007829
t=0.50, x=0.6065306597
t=1.00, x=0.3678794412

The last line agrees with the hand prediction. The result is printed in the terminal; this small script does not create a plot or save a result file.

In decay.eqi, change just the rate declaration to:

eqiora
parameter rate: 1 / s = 2;

Before rerunning, predict x(1)=exp⁡(−2)≈0.135335x(1)=\exp(-2)\approx0.135335: doubling the rate makes the quantity decay faster. Run the same command and script again. Its last line should now be close to t=1.00, x=0.1353352833.

You changed the model, not the time method. Restore rate to 1 when following the ODE lesson.

Some lessons run scripts or model packages from the repository. Downloading those examples is separate from installing Eqiora: keep using the published package in your uv project. With Git installed, run these commands from the project folder to get the files linked by this site:

Optional: download the example files
git init eqiora-source
git -C eqiora-source remote add origin https://github.com/eqiora/eqiora.git
git -C eqiora-source fetch --depth 1 origin 21fe50654fe7afcae0d14d313d6c3fb588d52057
git -C eqiora-source checkout --detach FETCH_HEAD

Keep eqiora-source beside .venv for the lessons that use repository paths. The decay, voltage-divider, heated-body and mixed-boundary elasticity examples run with the published 0.1.3 package. Add optional dependencies to that package as needed, for example uv add 'eqiora[matplotlib]'. Gmsh examples also need uv add 'eqiora[gmsh,matplotlib]' and the system GLU library; on Ubuntu, install it with sudo apt-get install libglu1-mesa.

You only need a development build for features or results marked as newer than the published release. The equation-derived transport and outlet flux used by the Kármán wake are included in 0.1.3.

After downloading the example files, install Rust stable with Cargo and a C compiler/linker. On Ubuntu, build-essential supplies the compiler and linker. Then replace the project’s published dependency with the checkout:

Terminal windowbash
uv add ./eqiora-source

The checked-out revision now supplies the installed package. uv records this local source in the project, so later uv run commands keep using it. For this development build, add extras to the same source, for example uv add './eqiora-source[gmsh,matplotlib]'. Building takes longer than installing a prebuilt wheel.

  • uv: command not found: install uv using its linked instructions, reopen the terminal and check uv --version.
  • Source build fails: check cargo --version and cc --version, then repeat the development-build command. Use CPython 3.13 and the checked-out source revision.
  • macOS import fails with mis-aligned LINKEDIT string pool: see the source-build workaround below.
  • Wrong Python or missing eqiora: run uv run python -c "import eqiora; print(eqiora.__version__)" from the project folder. For the optional source build, also compare git -C eqiora-source rev-parse HEAD with the revision in the example-download command; the version alone does not identify it.
  • Model file not found: keep decay.eqi beside run.py and run from their project folder, or pass its path: uv run python run.py path/to/decay.eqi.
  • A source diagnostic: misspelling rate as missing_rate in the relation produces EQ0603: unresolved expression symbol. Correct the name to match the declaration. Changing the rate’s unit to m instead produces an addition/subtraction dimension mismatch: the two terms must both have inverse-time units.

A source build can succeed on macOS 27 while import eqiora fails with mis-aligned LINKEDIT string pool when loading _eqiora. This matches a Rust/LLVM stripping defect; Rust has merged an upstream fix.

For an affected source build, add the following to the consuming project’s pyproject.toml, beside run.py. If the table already exists, add only the eqiora entry. This passes both stripping overrides to Eqiora’s build backend:

toml
[tool.uv.config-settings-package]
eqiora = { build-args = "--strip=false --config profile.release.strip=false" }

Rebuild the existing source dependency, then check the import and rerun the model:

Terminal windowbash
uv sync --reinstall-package eqiora
uv run python -c "import eqiora; print(eqiora.__version__)"
uv run python run.py

The reported workaround restored import and the decay example on macOS 27.0 arm64 with CPython 3.13.11, uv 0.12.15, Rust 1.96.0 and Apple clang 21.0.0, using Eqiora 0.1.0a7. Both overrides were applied together; neither has been tested alone. Prebuilt wheels are still Linux x86-64 only. Once your toolchain includes the upstream fix, remove the override, rebuild, and repeat the checks.