Skip to content

Commit 3e113e1

Browse files
committed
Cleaning up old files.
1 parent 6c2826b commit 3e113e1

File tree

16 files changed

+1157
-1550
lines changed

16 files changed

+1157
-1550
lines changed

.claude/commands/watt-subplan.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
Create a focused implementation sub-plan for a single phase of the WATT.jl rework.
2+
3+
## Instructions
4+
5+
The user will specify a phase number (1–8). Your job is to produce a detailed, session-scoped sub-plan that can be executed start-to-finish in one working session.
6+
7+
### Step 1: Read the long-term plan
8+
Read `plan.md` in the project root. Identify the target phase and its goals, entry/exit criteria, tasks, and dependencies.
9+
10+
### Step 2: Explore relevant source files
11+
Read the source files listed in the phase's "Critical Files" or task list. Focus on:
12+
- The exact current state of the code (what exists, what is dead, what is broken)
13+
- Function signatures, struct fields, and call sites that will be affected
14+
- Any existing tests that cover the area
15+
- Any patterns already established in the codebase that should be followed
16+
17+
Also read:
18+
- `.claude/context/GXBEAM_STYLE.md` — for style/API conventions to apply
19+
- `.claude/context/JULIA_GUIDE.md` — for Julia performance and style rules
20+
21+
### Step 3: Write the sub-plan
22+
23+
The sub-plan must include:
24+
25+
**Header**
26+
- Phase number and title
27+
- Status: In Progress
28+
- Date
29+
- Link back to `plan.md`
30+
31+
**Entry check**
32+
- Confirm the phase's entry criteria are met (or note what is blocking)
33+
- List any unresolved questions to ask the user before starting
34+
35+
**Ordered task list**
36+
- Number each task
37+
- Mark which tasks are independent and can be parallelized vs. must be sequential
38+
- For each task: file path(s), what to change, what to watch out for (AD compatibility, type stability, naming)
39+
- Flag any task that touches a known active bug from the plan
40+
41+
**Test plan**
42+
- What tests to run after each task group to verify correctness
43+
- For Phase 1: run the golden-value script (user must provide) and verify outputs match reference
44+
- For Phases 2+: list specific test files and what assertions to check
45+
- Note if AD tests should be run (only when `ENV["WATT_AD_TESTS"] == "true"`)
46+
47+
**Exit checklist**
48+
- Checklist derived from the phase's exit criteria in `plan.md`
49+
- Include: tests pass, no regressions vs. golden reference, style matches GXBEAM_STYLE.md
50+
51+
**Next session note**
52+
- One sentence on what Phase comes next and what the entry criteria will be
53+
54+
### Output format
55+
56+
Write the sub-plan as a markdown document. Do not execute any of the tasks — only produce the plan. The user will approve it before implementation begins.

.claude/context/GXBEAM_STYLE.md

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
# GXBeam.jl Style Reference
2+
3+
Patterns extracted from GXBeam.jl v0.3.1 source (`~/.julia/packages/GXBeam/525aD/src/`).
4+
Use these as the target style for WATT.jl refactoring.
5+
6+
---
7+
8+
## Struct Conventions
9+
10+
### Parametric structs — always use `{TF}` for floating point type
11+
12+
```julia
13+
struct PointState{TF}
14+
u::SVector{3, TF}
15+
theta::SVector{3, TF}
16+
F::SVector{3, TF}
17+
M::SVector{3, TF}
18+
end
19+
20+
struct Element{TF}
21+
L::TF
22+
x::SVector{3, TF}
23+
compliance::SMatrix{6,6,TF,36}
24+
mass::SMatrix{6,6,TF,36}
25+
end
26+
```
27+
28+
- Type parameter is always named `TF` (floating point type)
29+
- Additional container type parameters use `TV`, `TM`, `TP`, `TC`, `TE` etc.
30+
- Fully-constrained signatures for complex structs:
31+
```julia
32+
struct Assembly{TF, TP<:AbstractVector{<:AbstractVector{TF}},
33+
TC<:AbstractVector{<:Integer}, TE<:AbstractVector{Element{TF}}}
34+
```
35+
- Small fixed-size arrays: `SVector` / `SMatrix` from StaticArrays.jl (avoids heap allocation)
36+
- Large/variable arrays: `AbstractVector{TF}` (allows both `Vector` and sparse/offset arrays)
37+
38+
### Immutable vs mutable
39+
40+
- **Immutable** (`struct`): pure data containers — state outputs, element properties, boundary conditions, load structs
41+
- **Mutable** (`mutable struct`): system state that is updated in-place during solve — `StaticSystem`, `DynamicSystem`
42+
43+
The key distinction: if you only mutate array *contents* (not array references), immutable is fine. Use `mutable struct` only when field references themselves are reassigned.
44+
45+
### Always define `Base.eltype`
46+
47+
```julia
48+
Base.eltype(::Element{TF}) where TF = TF
49+
Base.eltype(::Type{Element{TF}}) where TF = TF # both instance and type forms
50+
```
51+
52+
### Type conversion constructor + `Base.convert`
53+
54+
```julia
55+
Element{TF}(e::Element) where {TF} = Element{TF}(e.L, e.x, e.compliance, e.mass, e.Cab, e.mu)
56+
Base.convert(::Type{Element{TF}}, e::Element) where {TF} = Element{TF}(e)
57+
```
58+
59+
This enables `convert(Element{Float32}, elem)` and type-parameterized construction from existing instances — important for AD where dual numbers replace Float64.
60+
61+
### Outer constructors infer `TF` via `promote_type`
62+
63+
```julia
64+
function Element(L, x, compliance, mass, Cab, mu)
65+
TF = promote_type(typeof(L), eltype(x), eltype(compliance), eltype(mass), eltype(Cab), eltype(mu))
66+
return Element{TF}(L, x, compliance, mass, Cab, mu)
67+
end
68+
```
69+
70+
Users call the outer constructor; the `{TF}` constructor is the canonical low-level form.
71+
72+
---
73+
74+
## Module Organization (`GXBeam.jl`)
75+
76+
### All exports live in the main module file — none in subfiles
77+
78+
```julia
79+
module GXBeam
80+
81+
# ... using statements ...
82+
83+
export AbstractSystem, StaticSystem, DynamicSystem
84+
export static_analysis, static_analysis!
85+
export steady_state_analysis, steady_state_analysis!
86+
# ... all exports grouped by category ...
87+
88+
# module-level constants
89+
const GAUSS_NODES = SVector(-0.861..., ...)
90+
91+
# includes with one comment per group
92+
include("math.jl") # common math functions
93+
include("assembly.jl") # assembly creation
94+
include("loads.jl") # prescribed conditions, distributed loads, point masses
95+
include("system.jl") # system storage and pointers
96+
include("analyses.jl") # system analyses
97+
98+
# interface extensions in subdirectory
99+
include("interfaces/diffeq.jl")
100+
include("interfaces/reversediff.jl")
101+
include("interfaces/writevtk.jl")
102+
103+
end
104+
```
105+
106+
### Private/internal functions — no leading underscore, just don't export
107+
108+
GXBeam does not use `_foo` naming for private functions. Private functions simply aren't exported. No `@private` or similar macros.
109+
110+
### RecipesBase is a hard dependency in GXBeam
111+
112+
`using RecipesBase` appears directly in the main module. For WATT.jl we intentionally differ here: use `Requires.jl` conditional loading (see `plan.md` Phase 8).
113+
114+
---
115+
116+
## Dispatch Patterns
117+
118+
### Paired allocating / non-allocating functions
119+
120+
```julia
121+
# Allocating (user-facing): creates system, calls mutating version
122+
function static_analysis(assembly; kwargs...)
123+
system = StaticSystem(assembly)
124+
return static_analysis!(system, assembly; kwargs..., reset_state=false)
125+
end
126+
127+
# Non-allocating (pre-allocated): takes pre-built system, mutates in place
128+
function static_analysis!(system::StaticSystem, assembly; kwargs...)
129+
# ... solve ...
130+
end
131+
```
132+
133+
Pattern: `foo(args)` allocates and delegates to `foo!(preallocated, args)`. The `!` version is the workhorse; the non-`!` version is the convenience wrapper.
134+
135+
### Dispatch over abstract type, then concrete type
136+
137+
```julia
138+
# First dispatch: accept any AbstractSystem
139+
function update_body_acceleration_indices!(system::AbstractSystem, prescribed_conditions)
140+
update_body_acceleration_indices!(system.indices, prescribed_conditions)
141+
return system
142+
end
143+
144+
# Second dispatch: work on the concrete SystemIndices
145+
function update_body_acceleration_indices!(indices::SystemIndices, prescribed_conditions)
146+
# actual work here
147+
return indices
148+
end
149+
```
150+
151+
No `if isa(system, StaticSystem)` branching — dispatch handles it.
152+
153+
### Mutating functions return `self`
154+
155+
```julia
156+
function update_body_acceleration_indices!(system::AbstractSystem, ...)
157+
# ... mutations ...
158+
return system # ← always return the mutated object for chaining
159+
end
160+
```
161+
162+
---
163+
164+
## Docstring Format
165+
166+
GXBeam uses `# Section` headers (with `#`), not bold `**Section**`. For WATT.jl we use `**bold**` headers per user preference — note this divergence when writing docs.
167+
168+
### GXBeam actual format (for reference):
169+
170+
```julia
171+
"""
172+
function_name(arg1, arg2; kwarg=default)
173+
174+
One-sentence or two-sentence description. May span lines.
175+
176+
# Arguments
177+
- `arg1`: Description (no type annotation in docstring)
178+
- `arg2`: Description
179+
180+
# Keyword Arguments
181+
- `kwarg = default`: Description
182+
183+
# Fields (for structs)
184+
- `field`: Description
185+
"""
186+
```
187+
188+
### WATT.jl adapted format (use this):
189+
190+
```julia
191+
"""
192+
function_name(arg1, arg2; kwarg=default) -> out1, out2
193+
194+
One-sentence description.
195+
196+
**Arguments**
197+
- `arg1::Type`: Description
198+
- `arg2::Type`: Description
199+
200+
**Keyword Arguments**
201+
- `kwarg::Type = default`: Description
202+
203+
**Returns**
204+
- `out1::Type`: Description
205+
206+
**Notes**
207+
AD compatibility notes, performance caveats, references.
208+
"""
209+
```
210+
211+
Key differences from GXBeam: bold headers, explicit return types in synopsis, type annotations on args.
212+
213+
### Struct docstring:
214+
215+
```julia
216+
"""
217+
MyStruct{TF}
218+
219+
One-sentence description.
220+
221+
**Fields**
222+
- `field1::SVector{3,TF}`: Description
223+
- `field2::TF`: Description
224+
"""
225+
struct MyStruct{TF}
226+
...
227+
end
228+
```
229+
230+
---
231+
232+
## Keyword Argument Patterns
233+
234+
### Default values use StaticArrays for zero vectors
235+
236+
```julia
237+
function foo(assembly;
238+
gravity = (@SVector zeros(3)), # ← not zeros(3)
239+
prescribed_conditions = Dict{Int, PrescribedConditions{Float64}}(),
240+
time = 0.0,
241+
reset_state = true,
242+
show_trace = false,
243+
method = :newton,
244+
ftol = 1e-9,
245+
iterations = 1000,
246+
)
247+
```
248+
249+
### Optional parameters use `nothing` + `isnothing` guard
250+
251+
```julia
252+
function Element(points, start, stop;
253+
frame = nothing,
254+
compliance = nothing,
255+
mass = nothing)
256+
257+
if isnothing(compliance)
258+
compliance = @SMatrix zeros(6,6)
259+
end
260+
...
261+
end
262+
```
263+
264+
---
265+
266+
## Other Notable Patterns
267+
268+
### `@unpack` for struct/NamedTuple destructuring
269+
270+
```julia
271+
@unpack force_scaling, indices = system
272+
```
273+
274+
Use `UnPack.jl` `@unpack` rather than manual field access when extracting multiple fields.
275+
276+
### NamedTuple packing with `(; ...)` syntax
277+
278+
```julia
279+
constants = (;
280+
assembly, indices, two_dimensional, force_scaling,
281+
x=system.x, resid=system.r, converged=converged,
282+
)
283+
```
284+
285+
Semicolon-NamedTuple syntax for grouping closure arguments.
286+
287+
### `Ref` for scalar flags passed into closures/callbacks
288+
289+
```julia
290+
converged = Ref(false)
291+
# ... pass converged into callback ...
292+
converged[] = true
293+
```
294+
295+
### Abstract type hierarchy for system variants
296+
297+
```julia
298+
abstract type AbstractSystem end
299+
mutable struct StaticSystem{...} <: AbstractSystem end
300+
mutable struct DynamicSystem{...} <: AbstractSystem end
301+
mutable struct ExpandedSystem{...} <: AbstractSystem end
302+
```
303+
304+
Define an abstract supertype even for 2–3 concrete variants — enables dispatch without coupling call sites to concrete types.
305+
306+
### Interface extensions in `interfaces/` subdirectory
307+
308+
AD interfaces (ReverseDiff overloads, ChainRules), DifferentialEquations.jl integration, and WriteVTK integration live in `src/interfaces/`. This keeps the core physics files clean of third-party integration code.
309+
310+
---
311+
312+
## What GXBeam Does NOT Do
313+
314+
- No `isa` or `typeof` checks inside function bodies — all handled by dispatch
315+
- No `@show` or `println` in any function
316+
- No `using Revise` in tests
317+
- No dead/commented code in source files
318+
- Exported symbols are all in one place (`GXBeam.jl`), not scattered across files
319+
- Does not use `NamedTuple` for primary data types — always a proper struct

0 commit comments

Comments
 (0)