Skip to content

Build a KiteGeometry SystemDefinition from KPS3 and KPS4 and carry it in the log - #327

Open
1-Bort-1 wants to merge 30 commits into
mainfrom
agent/322-one-kite-system-definition-across-the-ki
Open

1-Bort-1 wants to merge 30 commits into
mainfrom
agent/322-one-kite-system-definition-across-the-ki

Conversation

@1-Bort-1

@1-Bort-1 1-Bort-1 commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Depends-On: OpenSourceAWE/KiteGeometry.jl release after v0.3.0

Until now a KPS3 or KPS4 run described its system only through a segment count and a few settings. Nothing that reads a system definition could draw it, KiteViewers included. Now the model can describe itself as a KiteGeometry system definition: its points, the springs it integrates as segments, one tether and one winch. That definition can be saved in the log, so a viewer reading the log gets the topology the run actually integrated. KiteGeometry is re-exported, as KiteModels already does for KitePodModels, WinchModels and AtmosphericModels.

integrator = init!(kps4)
definition = system_definition(kps4)         # new
# ... simulate and log! ...
save_log(logger, definition, "sim_log")      # stores the definition in the log
KiteGeometry.definition(load_log("sim_log")) # reads it back

What the definition holds:

  • Points. One point per model point, named "1" upwards. Point 1 is the winch and is static.
  • Segments. For KPS4 these are the model's own spring list: 6 tether springs and 9 bridle springs, with their endpoints, rest lengths and diameters. The connectivity is therefore what the model integrates, not a second copy of the spring table. Of the 9 kite springs, the 3 that end at the KCU are named as bridle lines and the 6 that join two kite points as struts. All 9 are massless, as KPS4 treats them. They keep the line diameter KPS4 takes their stiffness and drag from, so the definition describes the system that was simulated. KPS3 has no spring list, so its segments join neighbouring points.
  • Materials. Each segment names a linear material holding its density and Young's modulus, chosen so that the modulus times the line's cross-section gives the nominal stiffness the model integrates. KPS4 has two: the tether and the massless kite lines. KPS3 has one, the tether.
  • Masses. For KPS4 the KCU mass sits on the KCU point and the kite mass on points A–D. For KPS3 both sit on the last point. Tether mass comes from the tether material's density and the segments' diameter.
  • Tether and winch. The tether runs from the winch to the KCU. Point 1, the winch, is the only fixed point. Gear ratio and drum radius come from the settings.
  • Pose and stiffness. The pose is wherever the points are when the definition is built, so build it right after init!. The stiffness is the nominal value. The model only scales it below nominal during a start-up ramp.
  • Log format. Saving and reading the definition in a log are KiteGeometry's, so every model that builds a definition logs it the same way. The log stores it as JSON under the key topology. The definition carries its connectivity checksum, so a reader can tell when a log's states were recorded against a different topology.

Where I'd push back:

  • The example is not literally unchanged. The torque-control reel-out example changes two lines: it builds the definition after init! and passes it to save_log. Its logger never sees the model, and KiteUtils' logger has nowhere to keep metadata, so an untouched script cannot carry the definition without global state. The simulation itself is unchanged.
  • The issue says this repo writes aero_force_b and tether_induced_force every step. It writes neither, so the KiteUtils state rename has nothing to change here.
  • The pose is not moved to the zenith. By the awesIO convention a structure file places its kite at 90° elevation. This definition keeps the points where init! put them, so its positions match the first logged state. Rotating them would be one more step that a viewer would have to undo.
  • The struts are labelled, not modelled. Giving them their own stiffness and diameter would change simulation results, so it belongs in a separate change to KPS4.

Dependencies: this builds on KiteGeometry 0.3, whose segments name a material rather than carry their own density and stiffness. The metadata is built by keyword, which KiteGeometry 0.3.0 does not have yet. Until a release carries it, Project.toml pins KiteGeometry through [sources] to OpenSourceAWE/KiteGeometry.jl@ea27241, the head of OpenSourceAWE/KiteGeometry.jl#58, which adds the keyword constructor on top of 0.3.0, so CI installs it. KiteModels cannot be registered with that pin, so this waits for OpenSourceAWE/KiteGeometry.jl#58 to merge and be released, then moves to that release. Both manifests are main's after a minimal resolve against this branch's Project.toml, and differ from main's only by the KiteGeometry entry. The Julia 1.13 manifest keeps main's Julia 1.13.2 standard-library entries, because the resolve ran on Julia 1.13.0.

Verification

  • Reproduced first: n/a, new feature. Against KiteGeometry 0.2.0 the old definition fails to build: UndefVarError: STATIC not defined, then MethodError: no method matching Metadata(; name::String, n_points::Int64) without the pinned commit.
  • test/test-system-definition.jl checks fixed points, rest lengths, the stiffness from each material, the massless kite lines and the segment names. It errored before the move to KiteGeometry's materials table and passes after it.
  • Acceptance: examples/reel_out_4p_torque_control.jl runs to the end and logs 1800 rows of 11 points. KiteGeometry.definition on the loaded log gives 11 points (length(kps4.pos) is 11) and 15 segments whose endpoints equal the model's springs (true): tether_1–tether_6, then bridle_1, strut_2, strut_3, strut_4, bridle_5, bridle_6, strut_7, strut_8, strut_9. Two materials, tether (724 kg/m³) and kite_line (0 kg/m³). The stiffness from the materials matches the springs at stiffness_factor 1.0, and the drum radius is 0.1615.
  • Docs build clean on 6a1de63, not rebuilt for the dependency bump · mergeable with main · REUSE lint: CI only (no reuse on the box).
  • On KiteGeometry 0.3.0 (59d66e1): test/test-system-definition.jl, test/test-aqua.jl, test/test-update-sys-state.jl and test/test-kps4.jl together give 564 passes, 0 failures and 0 errors (juliaserver, Julia 1.13.0, test project). The acceptance run below was repeated on 0.3.0 with the same result.
  • Local full suite on 59d66e1: started (Julia 1.13.0) · GitHub CI on 59d66e1: running.
  • Benchmark: the simulation step is untouched. Building the definition takes 178 µs and 141 kB, once per run. Saving an 1800-step log takes 11.21 ms with the definition against 11.26 ms and 10.96 ms without it, allocates 14.08 MB instead of 13.92 MB, and writes 342 kB instead of 329 kB. Loading KiteModels takes about 38 ms longer (KiteGeometry and the JSON package) out of about 2.2 s. BenchmarkTools medians and @time_imports, Julia 1.13.0, one cold session, measured on KiteGeometry 0.1.
    Box: quiet. 1 of 20 cores busy, 2.6–2.7 GHz, 57 GB free.
  • Risk: a definition built after the run has started records the current pose, not the initial one. The docstring says to build it after init!.

Opened elsewhere

Opened by 1-Bort-1, an AI agent working for @1-Bart-1.
Closes #322 · task KiteModels.jl-322

1-Bort-1 and others added 3 commits September 30, 2026 16:26
system_definition(s) takes the points and the springs the model integrates;
topology_metadata(s) carries its structure document in a log under topology.
KiteGeometry is pinned through [sources] until it is registered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@1-Bort-1 1-Bort-1 added agent:running Agent task state agent:ci Agent task state agent:review Agent task state and removed agent:running Agent task state agent:ci Agent task state labels Sep 30, 2026

@1-Bort-1 1-Bort-1 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent review (advisory)

Verdict: APPROVE WITH COMMENTS · 3 inline, 0 off the diff

Good

  • Connectivity comes straight from s.springs, so there is no second copy of SPRINGS_INPUT, as the card says; checked against init_springs!/loop! in src/KPS4.jl
  • KCU extra mass is set.kcu_mass and not s.masses[segments+1], so the tether half-masses that loop! adds at KPS4.jl:484 are not counted twice
  • pos_ENU is an SVector field in KiteGeometry's Point, so the definition copies the pose and does not alias the live MVectors; confirmed in _structure.jl:73
  • unit_stiffness = axial_stiffness * length gives the stiffness per length that the schema field asks for (N); matches the set.axial_stiffness / L_0 construction
  • Both model methods share one 3-argument assembler, so there is one path from model to definition
  • Deferring connectivity_sha and to_json to KiteGeometry and not adding a third preimage writer is the right call; the reason is in the card
  • The round-trip testset protects the actual contract, a saved log parsing back to the same structure document

Not good

  • src/system_definition.jl:17 — All 9 kite springs get d_line and rho_tether, but KPS4 puts no mass on them (the kite points already hold all of set.mass), and several are canopy struts, not lines. Anything that sums segment mass will read a heavier system than the one that was simulated.
  • src/system_definition.jl:52 — A 7-argument positional Metadata(...) with two empty strings, a version literal and another empty string can't be reviewed from the diff. Keyword construction, or a KiteGeometry default, would name connectivity_sha and make the placeholder visible.
  • test/test-system-definition.jl:31 — This compares an immutable snapshot with spring endpoints that loop! never changes, so it passes whatever the step does. The next_step! and the assertion add runtime but protect nothing beyond a check before the step.
  • The [sources] pin to an unregistered KiteGeometry means ./bin/release cannot register KiteModels until the pin comes out; merging to main blocks releases until then
  • @reexport using KiteGeometry is only in the changelog; the card never gives a reason for pushing Point, Segment, Tether, Winch, Metadata into every user's namespace
  • The "1.0.0" and "structure_schema.yml" literals copy constants KiteGeometry owns and will drift when its schema version moves
  • stiffness_factor is left out of unit_stiffness, so the example (stiffness_factor=0.1) logs 10x the stiffness it actually simulated; the docstring says nothing about this
  • The 3-argument system_definition(s, segments, extra_masses) is a helper, but it becomes a documented method of an exported function
  • Prose in docs/src/functions.md and the changelog is hard-wrapped, against §6

claude, rubric CLEAN_CODE.md. A different lab from the implementer
on purpose: a reviewer sharing its blind spots would not flag its mistakes.

Comment thread src/system_definition.jl Outdated
Comment thread src/system_definition.jl Outdated
Comment thread test/test-system-definition.jl Outdated
@1-Bort-1 1-Bort-1 added agent:queued Agent task state and removed agent:review Agent task state labels Sep 30, 2026
@1-Bort-1

1-Bort-1 commented Sep 30, 2026 •

Copy link
Copy Markdown
Member Author

Local full suite: PASS (4 min, Julia 1.13.0, one cell of the matrix)

@1-Bort-1 1-Bort-1 added agent:running Agent task state and removed agent:queued Agent task state labels Sep 30, 2026
…nwrapped prose

The bridle springs carry no mass in KPS4, so their segments get zero
density. The shared constructor becomes assemble_system_definition
instead of a third method of the exported system_definition. The
KPS4 test drops a next_step! that no assertion depended on and pins
unit_stiffness at the nominal value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@1-Bort-1 1-Bort-1 added agent:ci Agent task state agent:review Agent task state agent:queued Agent task state agent:running Agent task state and removed agent:running Agent task state agent:ci Agent task state agent:review Agent task state agent:queued Agent task state labels Sep 30, 2026
@1-Bart-1

Copy link
Copy Markdown
Member

save_log should get a method override, automatically adding the metadata. I think this method override should be in KiteGeometry.jl. Also a convenience method to easily get the system definition from a loaded log.

save_log(logger, system_definition(s), name) and KiteGeometry.definition(log)
now live in KiteGeometry, so topology_metadata goes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@1-Bort-1

Copy link
Copy Markdown
Member Author

Done. The save_log method and the log reader are in OpenSourceAWE/KiteGeometry.jl@b9583dd, whose pull request opens with this turn: save_log(logger, system, name) stores the definition, and KiteGeometry.definition(load_log(name)) reads it back. #327 switches to them in b44220a and drops its own helper. It is in draft until a KiteGeometry release carries the change.

1-Bort-1 and others added 7 commits October 12, 2026 17:46
Main moved the default manifests to DSP 0.8.6. Both .defaults are main's plus a resolve that adds KiteGeometry; 1.13 was resolved under Julia 1.13.0, the newest on the box, so julia_version and LibSSH2_jll go back to 1.13.0's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@1-Bart-1

Copy link
Copy Markdown
Member

Fix the failing test

1-Bort-1 and others added 4 commits October 14, 2026 17:32
CI installs registered KiteGeometry 0.1.0, which has no
save_log(logger, ::SystemDefinition, name), so test-system-definition
errors with a MethodError. Pin KiteGeometry through [sources] to
b9583dd, the head of OpenSourceAWE/KiteGeometry.jl#50, until a release
carries it. Both .defaults move only the KiteGeometry entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's manifests re-resolved against this branch's Project.toml: the only move is the KiteGeometry [sources] entry. Main's Julia 1.13.1 stamp is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
KiteGeometry 0.1.1 carries the save_log method and log reader from
OpenSourceAWE/KiteGeometry.jl#50, so the [sources] pin to that pull
request's commit goes and the compat entry rises to 0.1.1. Both
.defaults move only the KiteGeometry entry and project_hash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ufechner7

Copy link
Copy Markdown
Member

Done. The save_log method and the log reader are in OpenSourceAWE/KiteGeometry.jl@b9583dd, whose pull request opens with this turn: save_log(logger, system, name) stores the definition, and KiteGeometry.definition(load_log(name)) reads it back. #327 switches to them in b44220a and drops its own helper. It is in draft until a KiteGeometry release carries the change.

What is the performance overhead by this change?

@ufechner7

Copy link
Copy Markdown
Member
  • src/system_definition.jl:17 — All 9 kite springs get d_line and rho_tether, but KPS4 puts no mass on them (the kite points already hold all of set.mass), and several are canopy struts, not lines. Anything that sums segment mass will read a heavier system than the one that was simulated.

Was this addressed? How could this be addressed?

@ufechner7 ufechner7 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments must be addressed.

The six kite springs that join two kite points are canopy struts, the
three ending at the KCU bridle lines; the definition now says which,
without changing what KPS4 integrates. Metadata is built by keyword,
which needs KiteGeometry at OpenSourceAWE/KiteGeometry.jl@50b05ac until
a release carries it, so [sources] pins that commit and both manifests
move only the KiteGeometry entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@1-Bort-1

1-Bort-1 commented Oct 15, 2026 •

Copy link
Copy Markdown
Member Author

Left out of draft as @ufechner7 set it, though its card waits on Depends-On: OpenSourceAWE/KiteGeometry.jl release after v0.3.0.

@1-Bort-1

Copy link
Copy Markdown
Member Author

All three are addressed. Bridle mass: f100446. Strut labels: 40e5ca0. Metadata by keyword: 40e5ca0, through OpenSourceAWE/KiteGeometry.jl@50b05ac (its pull request opens with this turn). Test without the no-op step: f100446. Each comment has a reply under it.

@1-Bort-1

Copy link
Copy Markdown
Member Author

None per simulation step: the step code and the model are unchanged. The cost comes once, when you build the definition and when you save the log. Measured on KPS4 with system.yaml (Julia 1.13.0, BenchmarkTools medians, quiet box):

  • Building the definition with system_definition(kps4): 178 µs and 141 kB, once per run.
  • Saving an 1800-step log: 11.21 ms with the definition, against 11.26 ms and 10.96 ms without it (measured before and after), so within noise. It allocates 14.08 MB instead of 13.92 MB.
  • Log file: 342 kB instead of 329 kB.
  • using KiteModels: about 38 ms more out of about 2.2 s, for KiteGeometry and the JSON package it loads (@time_imports, one cold session).

The numbers are now on the Benchmark line of the description of #327.

@1-Bort-1

Copy link
Copy Markdown
Member Author

Yes, both parts are now addressed.

  • Mass, in f100446: the 9 kite springs have density 0, so summing segment mass gives only the tether. The kite mass sits on points A–D and the KCU mass on the KCU point, as in KPS4. The test asserts both.
  • Struts, in 40e5ca0: the 3 springs ending at the KCU are named bridle_i and the 6 that join two kite points (A–B, A–C, A–D, B–C, B–D, C–D) strut_i. The test asserts the names and that there are 6 struts.

Their diameter and stiffness stay as KPS4 simulates them: all 9 use d_line (src/KPS4.jl:1138, :324). Giving struts their own properties would change simulation results, so that is a KPS4 change for a separate issue.

1-Bort-1 and others added 3 commits October 17, 2026 16:31
# Conflicts:
#	src/KiteModels.jl
KiteGeometry 0.2.0 follows the slimmer awesIO core: a point is fixed or
not, a segment has a rest_length, and density and stiffness move into a
linear material. The KPS3 and KPS4 definitions now fill a materials table
(the tether, and for KPS4 the massless kite lines) instead of per-segment
density and unit_stiffness.

The keyword Metadata constructor is not in 0.2.0, so [sources] pins
OpenSourceAWE/KiteGeometry.jl@9c9dfd2, its merge onto 0.2.0. Both
.default manifests move only the KiteGeometry entry and project_hash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	Manifest-v1.12.toml.default
#	Manifest-v1.13.toml.default
OpenSourceAWE/KiteGeometry.jl#58 conflicted with KiteGeometry main after
v0.3.0; its branch now merges main (ea27241). Point [sources] at that
commit and raise compat to 0.3. The manifests move only the KiteGeometry
entry and project_hash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:review Agent task state

Projects

None yet

Development

Successfully merging this pull request may close these issues.

KiteModels.jl: a definition for KPS3 and KPS4

4 participants