Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 45 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@ cargo --version

Verify: `python --version`

**just** (recommended)

`just` is a command runner that provides short recipes for the most common
development tasks. It is optional — all commands it wraps can be run directly
— but it ensures the Python extension is always rebuilt before tests run,
which prevents hard-to-diagnose stale-extension failures.

```sh
cargo install just
# or on Windows with winget:
winget install Casey.Just
```

Verify: `just --version`

---

### First-Time Setup
Expand All @@ -50,16 +65,20 @@ Install dependencies:
Build the Rust extension and install it into the virtual environment:

```sh
# With just (recommended):
just develop

# Without just:
# Windows
.venv\Scripts\maturin develop

# Linux / macOS
.venv/bin/maturin develop
```

This compiles all Rust crates and produces an importable `arcanum` Python
module in the virtual environment. Re-run this command whenever you change
Rust source code before running Python tests.
Rust source code before running Python tests. If you use `just test` or
`just test-python`, this step runs automatically as a prerequisite.

---

Expand All @@ -68,36 +87,44 @@ Rust source code before running Python tests.
### Rust unit tests

```sh
# With just:
just test-rust

# Without just:
cargo test --workspace
```

Runs 33 unit tests in `arcanum-nec-import` covering V-PARSE, V-FMT, V-ERR,
Runs 35 unit tests in `arcanum-nec-import` covering V-PARSE, V-FMT, V-ERR,
V-WARN, and V-REAL cases from `docs/nec-import/validation.md`. No separate
build step is needed — `cargo test` compiles and runs in one command.

### Python integration tests

Build the extension first (see above), then:

```sh
# With just (rebuilds extension automatically):
just test-python

# Without just — build the extension first, then:
# Windows
.venv\Scripts\pytest tests/ -v

# Linux / macOS
.venv/bin/pytest tests/ -v
```

These tests exercise the same validation cases end-to-end through the PyO3
Python bindings. They require the extension to be current with the Rust
source; run `maturin develop` before `pytest` if you have changed any Rust
code since the last build.
source. `just test-python` handles this automatically via its `develop`
prerequisite.

### Running both together (matches CI)

```sh
# With just:
just test

# Without just:
# Linux / macOS
cargo test --workspace && .venv/bin/maturin develop && .venv/bin/pytest tests/ -v

# Windows
cargo test --workspace && .venv\Scripts\maturin develop && .venv\Scripts\pytest tests/ -v
```
Expand All @@ -109,12 +136,21 @@ cargo test --workspace && .venv\Scripts\maturin develop && .venv\Scripts\pytest
### Formatting check

```sh
# With just:
just check

# Without just:
cargo fmt --check
cargo clippy --workspace -- -D warnings
```

To auto-apply formatting:

```sh
# With just:
just fmt

# Without just:
cargo fmt
```

Expand Down
43 changes: 41 additions & 2 deletions crates/arcanum-nec-import/src/cards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,16 +228,55 @@ pub struct SimulationInput {
/// Wire geometry and ground boundary condition consumed by Phase 1.
#[derive(Debug, Clone, Default)]
pub struct MeshInput {
/// Wire descriptions after GS and GM transformations have been applied.
/// Raw wire descriptions as declared in the deck, before any GS/GM
/// transformations. Phase 1 is responsible for applying `transforms`.
pub wires: Vec<WireDescription>,
/// Ground plane boundary condition (geometric only).
pub ground: GeometricGround,
/// Ground plane flag from GE card.
pub gpflag: i32,
/// GS scale and GM operations to be applied by Phase 1.
pub transforms: GeometryTransforms,
}

/// GS and GM transformation data passed through to Phase 1.
///
/// The nec-import parser records these cards verbatim; it does not apply them.
/// Phase 1 applies GS scaling then GM operations (in deck order) to produce
/// final segment coordinates.
#[derive(Debug, Clone, Default)]
pub struct GeometryTransforms {
/// GS XSCALE — uniform scale factor. `None` if no GS card was present.
/// Applied before GM operations. Does not scale wire radii.
pub gs_scale: Option<f64>,
/// GM operations in deck order.
pub gm_ops: Vec<GmOperation>,
}

/// One GM card — a rotation, translation, and optional replication.
#[derive(Debug, Clone)]
pub struct GmOperation {
/// ITAG — wire tag to transform. 0 = all wires.
pub tag: u32,
/// NRPT — number of additional copies to generate. 0 = transform in place.
pub n_copies: u32,
/// ROX — rotation about x-axis, degrees.
pub rot_x: f64,
/// ROY — rotation about y-axis, degrees.
pub rot_y: f64,
/// ROZ — rotation about z-axis, degrees.
pub rot_z: f64,
/// XS — translation along x-axis.
pub trans_x: f64,
/// YS — translation along y-axis.
pub trans_y: f64,
/// ZS — translation along z-axis.
pub trans_z: f64,
/// ITS — tag increment applied to each generated copy.
pub tag_increment: u32,
}

/// A single wire element — straight, arc, or helix.
/// Coordinates reflect any GS/GM transformations applied by the router.
#[derive(Debug, Clone)]
pub enum WireDescription {
Straight(StraightWire),
Expand Down
6 changes: 3 additions & 3 deletions crates/arcanum-nec-import/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub fn parse_file(path: &Path) -> Result<(SimulationInput, ParseWarnings), Parse
pub use errors::{ParseError, ParseErrorKind, ParseWarning, ParseWarningKind, ParseWarnings};

pub use cards::{
ArcWire, GeometricGround, GroundElectrical, GroundModel, GroundType, HelixWire, LoadDefinition,
MeshInput, NearFieldRequest, OutputRequests, RadiationPatternRequest, SimulationInput,
SourceDefinition, StraightWire, WireDescription,
ArcWire, GeometricGround, GeometryTransforms, GmOperation, GroundElectrical, GroundModel,
GroundType, HelixWire, LoadDefinition, MeshInput, NearFieldRequest, OutputRequests,
RadiationPatternRequest, SimulationInput, SourceDefinition, StraightWire, WireDescription,
};
Loading
Loading