Device properties and a two-plugin force manifest#
Needs a CUDA GPU. A standalone, self-contained task: read the current device’s raw + derived properties, then combine two compiled force plugins — gravity and a per-sample drag model — from one manifest into a single accumulated acceleration, the way a propagator step would.
from eagle import device_props
props = device_props()
{
"name": props.name,
"compute_capability": f"{props.cc_major}.{props.cc_minor}",
"sm_count": props.sm_count,
"warp_size": props.warp_size,
"fp64_ratio": props.fp64_ratio,
}
{'name': 'Quadro P2000',
'compute_capability': '6.1',
'sm_count': 8,
'warp_size': 32,
'fp64_ratio': 32.0}
Combining two plugins from one manifest#
gravity and drag_ps are both "vector"-pattern plugins declared in the
same manifest; loading it returns both, keyed by their manifest id.
import json
import pathlib
import shutil
import tempfile
import numpy as np
FIXTURES = pathlib.Path("../_fixtures").resolve()
workdir = pathlib.Path(tempfile.mkdtemp())
for stem in ("gravity", "drag_ps"):
shutil.copy(FIXTURES / f"{stem}.ptx", workdir / f"{stem}.ptx")
shutil.copy(FIXTURES / f"{stem}.json", workdir / f"{stem}.json")
manifest = {
"schema_version": 1,
"pattern": "vector",
"aether_abi": "aether-abi/1",
"plugins": [
{"id": "gravity", "order": 0, "enabled": True, "artifact": "gravity.ptx",
"sidecar": "gravity.json", "format": "ptx"},
{"id": "drag", "order": 1, "enabled": True, "artifact": "drag_ps.ptx",
"sidecar": "drag_ps.json", "format": "ptx"},
],
}
(workdir / "manifest.json").write_text(json.dumps(manifest, indent=2))
426
from eagle.registry import load_manifest
reg = load_manifest(workdir / "manifest.json")
reg.names()
['gravity', 'drag']
MU = 3.986004418e5
N = 32
rng = np.random.default_rng(3)
position = rng.uniform(7.0e3, 4.2e4, size=(3, N))
velocity = rng.uniform(1.0, 8.0, size=(3, N))
mass = rng.uniform(100.0, 1200.0, N)
area = rng.uniform(1.0, 20.0, N)
cd = rng.uniform(2.0, 2.4, N)
a_gravity = reg["gravity"](position=position, mu=MU)
a_drag = reg["drag"](velocity=velocity, mass=mass, area=area, cd=cd)
a_total = a_gravity + a_drag
a_total.shape
(3, 32)
r = np.linalg.norm(position, axis=0)
expected_gravity = -MU * position / r**3
s = np.linalg.norm(velocity, axis=0)
expected_drag = -0.5 * (cd * area / mass) * s * velocity
np.testing.assert_allclose(a_gravity, expected_gravity)
np.testing.assert_allclose(a_drag, expected_drag)
print("both plugins, loaded from one manifest, match their closed forms")
both plugins, loaded from one manifest, match their closed forms