# Step 7: local-stiffness-kernel ## Read These Files First Read the following files before editing: - `/AGENTS.md` - `/docs/ARCHITECTURE.md` - `/docs/ADR.md` - `/docs/formulations/euler-beam-3d-formulation.md` - `/docs/numerical-reviews/euler-beam-3d-review.md` - `/docs/implementation-plans/euler-beam-3d-implementation-plan.md` Also read any files created by previous steps in this phase. ## Task Use TDD to create the local 12x12 stiffness kernel for the 3D Euler-Bernoulli beam. Create: - `/src/fesa/elements/euler_beam_3d.hpp` - `/src/fesa/elements/euler_beam_3d.cpp` - `/tests/unit/euler_beam_3d_local_stiffness_test.cpp` Required API: ```cpp namespace fesa::elements { using Vector12 = std::array; using Matrix12 = std::array; struct EulerBeam3DSection { double young_modulus; double shear_modulus; double area; double torsion_constant; double second_moment_y; double second_moment_z; }; Matrix12 euler_beam_3d_local_stiffness(double length, const EulerBeam3DSection& section); Vector12 euler_beam_3d_local_end_forces(double length, const EulerBeam3DSection& section, const Vector12& local_displacements); } // namespace fesa::elements ``` Implementation rules: - Matrix storage is row-major: index `(row, col)` is `row * 12 + col`. - Validate `length > 0` and all section constants are positive; throw `std::invalid_argument` otherwise. - Use only C++17 standard library. - Do not introduce an external linear algebra dependency. - Do not edit CMake files; source and test globs should pick up new files. ## Tests To Write First Create `/tests/unit/euler_beam_3d_local_stiffness_test.cpp` before production code. Test behavior: - For `L = 2.0`, `E = 210.0`, `G = 80.0`, `A = 3.0`, `J = 4.0`, `Iy = 5.0`, `Iz = 6.0`, verify representative matrix entries: - axial: `K(0,0) = EA/L`, `K(0,6) = -EA/L`, `K(6,6) = EA/L` - torsion: `K(3,3) = GJ/L`, `K(3,9) = -GJ/L`, `K(9,9) = GJ/L` - local `x-y` bending uses `EIz`: `K(1,1) = 12*E*Iz/L^3`, `K(1,5) = 6*E*Iz/L^2`, `K(5,5) = 4*E*Iz/L` - local `x-z` bending uses `EIy`: `K(2,2) = 12*E*Iy/L^3`, `K(2,4) = -6*E*Iy/L^2`, `K(4,4) = 4*E*Iy/L` - Verify all entries are symmetric within `1.0e-10`. - Verify `euler_beam_3d_local_end_forces` returns `K * u` for a displacement vector with at least three nonzero components. - Verify invalid length and nonpositive section constants throw `std::invalid_argument`. RED command: ```powershell ctest --test-dir build/msvc-debug --output-on-failure -C Debug -R euler_beam_3d_local_stiffness_test ``` Expected RED: test executable missing or compile failure because the header/API does not exist. Then implement the minimal API. GREEN command: ```powershell ctest --test-dir build/msvc-debug --output-on-failure -C Debug -R euler_beam_3d_local_stiffness_test ``` ## Acceptance Criteria ```powershell ctest --test-dir build/msvc-debug --output-on-failure -C Debug -R euler_beam_3d_local_stiffness_test python -m unittest discover -s scripts -p "test_*.py" python scripts/validate_workspace.py ``` ## Verification Notes 1. Confirm RED failed before production code was added. 2. Confirm no parser, assembly, or results writer code was changed. 3. Update `phases/euler-beam-3d/index.json` step 7: - success: `"status": "completed"`, `"summary": "local 3D Euler beam stiffness and local end-force kernel added"` - failure after retries: `"status": "error"`, `"error_message": ""` - blocked: `"status": "blocked"`, `"blocked_reason": ""` ## Forbidden - Do not add shear deformation or Timoshenko terms. - Do not modify reference artifacts.