Three related gaps in how the engine orders work.
1. input_dependencies is never populated. property_engine.h:174 iterates prop->traits().input_dependencies to add edges, but nothing in the tree writes to it. Ordering therefore happens per material rather than per property, which
- reports cycles that do not exist at property level (A.x -> B.y and B.z -> A.w is fine, but reads as A <-> B);
- makes the cycle error useless: it names no material and no property.
2. EdgeKind::Local edges create no ordering at all. Only Global edges are added at :174. A solver that reads a material over a Local edge, and a material that reads the solver back, are ordered only by accident: the sort is a FIFO BFS, so an indegree-0 key pops before any level-1 key. The kinematic-hardening rig in #55 works for exactly this reason (solver::g has indegree 0, kin::stress has indegree 1 via the stepper). A model that takes its strain over a Local edge gets no such protection.
3. EdgeKind::Local is not checked. linear_isotropic_hardening binds its callback to hardening_stress only, so hardening_modulus is fresh only if hardening_stress happened to be pulled first.
Fix
Populate input_dependencies when an input_property is wired, make the cycle error print the property path, and either order Local edges or verify at finalize that every Local read has a producer that runs before it.
All references are to main at 91bd26f.
Three related gaps in how the engine orders work.
1.
input_dependenciesis never populated.property_engine.h:174iteratesprop->traits().input_dependenciesto add edges, but nothing in the tree writes to it. Ordering therefore happens per material rather than per property, which2.
EdgeKind::Localedges create no ordering at all. Only Global edges are added at:174. A solver that reads a material over a Local edge, and a material that reads the solver back, are ordered only by accident: the sort is a FIFO BFS, so an indegree-0 key pops before any level-1 key. The kinematic-hardening rig in #55 works for exactly this reason (solver::ghas indegree 0,kin::stresshas indegree 1 via the stepper). A model that takes its strain over a Local edge gets no such protection.3.
EdgeKind::Localis not checked.linear_isotropic_hardeningbinds its callback tohardening_stressonly, sohardening_modulusis fresh only ifhardening_stresshappened to be pulled first.Fix
Populate
input_dependencieswhen aninput_propertyis wired, make the cycle error print the property path, and either order Local edges or verify at finalize that every Local read has a producer that runs before it.All references are to
mainat 91bd26f.