Skip to content

feat(stressmodel): generate the satellite network as a fleet of occurrences - #308

Merged
HuiJun merged 30 commits into
developfrom
feature/fleet-mode-stress-model
Sep 26, 2026
Merged

HuiJun merged 30 commits into
developfrom
feature/fleet-mode-stress-model

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

What and why

First of two pull requests implementing one definition, many occurrences from
docs/project/large-model-scaling-design.md §6.
This one rewrites the stress-test constellation in that form and measures what the current
runtime does with it; the second (shared derived defaults and verification over distinct shapes
in internal/exec/runtime) is #324, stacked on this branch.

Merge order: PR #308 first, then Part B (#324).

tools/cmd/stress-model -fleet generates the satellite network as a fleet:

part def BlockA :> Spacecraft {            // one of four blocks; as-built values as defaults
    attribute :>> catalogId default = 40000;
    part :>> comms { part :>> crosslinkTerminal { attribute :>> mass default = 2.0 [kg]; … } }
    …
}
part def OrbitalPlane {
    part sats : Spacecraft[400] ordered;
    interface ring : RFLink connect [1] sats.comms.crosslinkTx to [1] sats.comms.crosslinkRx;
}
part plane0 : OrbitalPlane {
    part :>> sats : BlockA { attribute :>> plane = 0; }
    part unit16 :> sats {                  // every sixteenth unit diverges from its block
        attribute :>> catalogId = 40016;
        attribute :>> slot = 16;
        part :>> comms { part :>> crosslinkTerminal { attribute :>> mass = 19.9 [kg]; … } }
    }
}
satisfy blockAMass by blockAConfig;        // one check per block …
satisfy blockAMass by network.plane0.unit16;  // … and one per diverging unit

instead of part def Sat0 :> Spacecraft { … } … Sat12799. The spacecraft (subsystems,
components, budgets, connections, mode machine), the ground segment and the three requirements
are the ones the single-definition form declares, and every as-built value a block states is a
default so a diverging unit can redefine any of it; that form's output is byte-for-byte
unchanged. Fleet mode composes with the split of tests/stressmodel/split.go and the CLI's
-split-planes: the fleet declares its planes inside the network, so
SatelliteNetwork{Fleet: true}.Split() writes the library and the constellation as two
documents, and their statistics add up to the whole file's. Stats gains Definitions, Units and
Assertions — Requirements stays the number of requirement usages, Assertions the number of
satisfy assertions, which in fleet form is three per block plus three per diverging unit — so
the two forms compare:

satellites form definitions units requirements assertions elements source
1 600 (8 × 200) one part def per satellite 1 600 1 600 4 800 4 800 294 627 18.1 MB
1 600 (8 × 200) fleet 4 104 12 324 3 203 193 KB
12 800 (32 × 400) one part def per satellite 12 800 12 800 38 400 38 400 2 354 827 145 MB
12 800 (32 × 400) fleet 4 800 12 2 412 12 467 771 KB

Where the implementation differs from the design. §6 has the per-unit data in a value table
the fleet binds to. Two things stop that today, both documented in the guide chapter and the
stress-test record rather than worked around:

  • A binding bind sats.comms.crosslinkTerminal.serialNumber = serialNumbers onto a feature that
    already has a block-level default is reported as a binding conflict (the default and the table
    are both values of the same feature), and a feature without a default has nothing for the
    non-diverging units to inherit.
  • A literal sequence of 12 800 values is the same size as the declarations it replaces.

The closest conforming form — a member subsetting the fleet (part unit16 :> sats { … }) for
each unit that diverges, inheriting everything else from the block — is what the generator
emits. The runtime places subsetting units as the leading members of sats (sats#(1) is
unit0, sats#(2) is unit16, sats#(3) onward read the block's defaults); the collection
keeps its declared size. Units between the diverging ones carry their block's catalog ID and
as-built values: a fleet in which every unit restates its values is the per-satellite form
again, so the stride is the fidelity the fleet form gives up until a per-occurrence
dataset/binding mechanism exists. The guide states this where it introduces the stride.

The links are not the same topology. The single-definition form writes every pair: ring
i → i+1 closing each plane, slot i of one plane to slot i of the next, satellite i to
station i mod G. A connector end is a feature chain, not an expression (sats#(1).comms.crosslinkTx
is not an end), so the fleet form cannot state those pairs without naming every occurrence; it
declares one connector over each collection instead — connect [1] sats.comms.crosslinkTx to [1] sats.comms.crosslinkRx, one per adjacent pair of planes, one per plane and station — whose [1]
ends say each link joins one satellite to one satellite or station, not which. The runtime
realizes such a connector as one link whose ends hold the collections (network.plane0.ring.a is
every transmitter of the plane), whatever the end multiplicities declare. The guide chapter and
the stress-test record say so; the fleet figures below are for that model, not for a pairwise one.

What the current runtime does with the fleet (measured; #324 changes this). Instantiation
still creates an object with a value slot per feature for every occurrence, and materialization
of the created network is bounded by maxMaterializeBudget. A satisfy whose subject is a
collection (plane0.sats) is rejected — the subject must denote one object — so the assertions
target each block's configuration and each diverging unit. A usage whose multiplicity lower
bound exceeds 1 000 cannot be materialized, so the fleet is laid out as 32 planes of 400 rather
than 8 of 1 600.

Measurements

Intel Xeon Platinum 8559C, 8 CPUs, 31 GiB RAM, no swap, Linux amd64, Go 1.25.0, GOMAXPROCS=8,
on this branch (current develop plus the fleet generator). Wall is sysml wall-clock,
allocated is runtime.MemStats.TotalAlloc, RSS is /usr/bin/time maximum resident set. Same
plane/station layout in each pair of rows.

-validate:

satellites form elements wall allocated peak RSS
1 600 one part def per satellite 294 627 22.7 s 6.2 GiB 2.5 GB
1 600 fleet 3 203 0.22 s 102 MiB 108 MB
12 800 one part def per satellite 2 354 827 331 s 49.8 GiB 20.3 GB
12 800 fleet 12 467 0.70 s 289 MiB 184 MB

The stress-test record's earlier 12 800-satellite figure (318 s / 44.0 GiB / 20.6 GB) was taken
with a different plane/station split and is kept beside these, labelled as such.

Current runtime on the fleet form:

satellites operation wall allocated peak RSS
1 600 -instantiate the network 0.44 s 238 MiB 195 MB
1 600 -satisfy, 324 assertions 0.71 s 666 MiB 306 MB
1 600 %eval of plane<i>.sats.dryMass, all 8 planes 1.85 s 2.9 GiB 737 MB
12 800 -instantiate the network 2.06 s 1.1 GiB 801 MB
12 800 -satisfy, 2 412 assertions 8.84 s 23.4 GiB 1.49 GB
12 800 %eval of plane<i>.sats.dryMass, all 32 planes 42.7 s 141.3 GiB 5.2 GB

go test ./tests/stressmodel -run '^$' -bench Fleet -benchmem -benchtime 3x:

BenchmarkFleetInstantiate/satellites=32/elements=1179-8      3   28953157 ns/op   904786 ns/satellite   19282802 B/op   121451 allocs/op
BenchmarkFleetInstantiate/satellites=128/elements=1715-8     3   86653242 ns/op   676978 ns/satellite   97622034 B/op   364417 allocs/op
BenchmarkFleetInstantiate/satellites=512/elements=3947-8     3  460017619 ns/op   898472 ns/satellite  924930853 B/op  1339407 allocs/op
BenchmarkFleetSatisfy/satellites=32/assertions=24-8          3     870627 ns/op                          484184 B/op     6840 allocs/op
BenchmarkFleetSatisfy/satellites=128/assertions=36-8         3    1236262 ns/op                         1077768 B/op    10538 allocs/op
BenchmarkFleetSatisfy/satellites=512/assertions=108-8        3    8466733 ns/op                         7632229 B/op    31885 allocs/op

Recorded in docs/project/satellite-network-stress-test.md (new section) and
docs/internals/performance.md; docs/guide/modeling-fleets.md is the new guide chapter, linked
from the guide index and the mkdocs.yml nav.

How it was verified

  • tests/stressmodel/satnet_test.go: TestFleetValidates loads a 2 × 32 fleet strictly with
    no diagnostics, checks that the number of satisfy verdicts is Stats.Assertions and every
    one holds, and reads inherited values (sats#(3).catalogId, sats#(3).plane,
    sats#(3).comms.crosslinkTerminal.dataRate, sats#(3).eps.solarArray.area), diverging values
    (unit0, unit16, sats#(1), sats#(2), unit16.comms.crosslinkTerminal.dataRate) and
    satelliteCount through the instantiated network, and checks the block details are written
    default = and the collection connectors declare [1] ends; TestFleetScales checks that
    more occurrences add no definitions, that only diverging units add declarations, that more
    planes add definitions and links, and that the fleet source is far smaller than the
    single-definition source; TestFleetFilesValidate validates the two-document split of a fleet,
    compares its summed statistics with the whole file's and checks every verdict holds.
  • tests/stressmodel/bench_test.go: BenchmarkFleetInstantiate, BenchmarkFleetSatisfy.
  • The single-definition generator's output was diffed byte-for-byte against develop's for the
    test layouts: identical.
  • gofmt -l . prints nothing; go build ./..., go vet ./... (root and tools modules),
    go test ./..., go test -race ./... pass.
  • Corpus gates with the corpora present:
    OPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 go test -count=1 ./tests/corpus
    — training 100/100 clean, training_examples_expected.txt unchanged and empty; pilot ratchets
    unchanged; go test -count=1 ./tests/identity -run TestPilotLibraryXMI with the pilot XMI
    present passes.
  • make docs-check (links, internal-label scan) passes; make docs-counts regenerated the test
    counts for the new tests; python3 scripts/changelog.py check passes.

Checklist

  • make test and make lint pass locally
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (see CONTRIBUTING.md)
  • Changelog entry added as changes/unreleased/<slug>.<section>.md, not as an edit to CHANGELOG.md
  • baselines regenerated and make docs-counts run if a gate count moved (compliance rows need nothing: the census is counted at docs build)
  • No internal work-item labels (waves, slices, F4, K5) in the body, docs, or changelog

…rences

Add a fleet form to the stress-model generator (cmd/stress-model -fleet):
four spacecraft blocks carry the as-built values as defaults, each orbital
plane is 'part sats : Block[N] ordered', and only every sixteenth unit states
values of its own, as a member subsetting the plane's fleet. The spacecraft,
ground segment, requirements, mode machine, ring, inter-plane and downlink
connectors are those of the single-definition form, whose output is
unchanged. Stats gains Definitions and Units so the forms compare.

At 12 800 satellites the fleet declares 11 667 elements against 2 354 827
and validates in 0.57 s and 185 MB rather than 301 s and 20.1 GB. The guide
chapter on modeling fleets shows both forms, the stress-test record and the
performance notes carry the measurements, including what the current
runtime pays to instantiate, check and read the occurrences, and
BenchmarkFleetInstantiate and BenchmarkFleetSatisfy time it.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review September 15, 2026 07:20
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 3 commits September 15, 2026 07:40
… state link cardinality

Block component details (array area, battery capacity, terminal data rate, …)
are now defaults like the masses and serial numbers, so a diverging unit can
redefine them; the crosslink terminal of every diverging unit states its data
rate. The ring and inter-plane collection connectors declare [1] ends, and the
guide, stress-test record and changelog say what a collection connector does
and does not state about the per-pair topology. Fleet figures re-measured.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 15, 2026 16:54
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 4 commits September 15, 2026 16:58
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
…-end fix

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/satellite-network-stress-test.md
#	docs/project/spec-compliance.md
#	internal/stressmodel/satnet_test.go
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 15, 2026 18:17
…tellation

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration Bot and others added 3 commits September 15, 2026 19:59
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
devin-ai-integration Bot and others added 4 commits September 15, 2026 22:41
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration Bot and others added 7 commits September 16, 2026 03:28
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
devin-ai-integration Bot and others added 2 commits September 25, 2026 20:46
…-stress-model

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	mkdocs.yml
#	tests/stressmodel/satnet.go
#	tests/stressmodel/satnet_test.go
…n the current tree

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 25, 2026 21:12
…ages

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
@HuiJun
HuiJun merged commit 9cd9b3d into develop Sep 26, 2026
18 checks passed
@HuiJun
HuiJun deleted the feature/fleet-mode-stress-model branch September 26, 2026 05:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant