.. _architecture_io: ============================ I/O and CLI pipeline ============================ This document describes how data enters GenSec (YAML input), how it is processed (CLI orchestration), and how results leave (JSON, CSV, plots). Data flow ---------- .. mermaid:: flowchart LR subgraph INPUT YAML["input.yaml"] end subgraph PARSE["io_yaml.py"] PM["Parse materials"] PS["Parse section"] PD["Parse demands"] PC["Parse combinations"] PE["Parse envelopes"] PO["Parse output flags"] end subgraph COMPUTE["solver/"] FS["FiberSolver"] NM["NMDiagram"] VE["VerificationEngine"] end subgraph EXPORT["output/"] JSON["JSON files"] CSV["CSV files"] PNG["PNG plots"] end YAML --> PM & PS & PD & PC & PE & PO PM --> FS PS --> FS FS --> NM --> VE PD & PC & PE --> VE PO --> VE VE --> JSON & CSV NM --> JSON & CSV JSON --> PNG Each box is a distinct software module. The arrows show data dependencies: "A → B" means "B needs output from A". YAML input structure --------------------- A GenSec YAML file has up to six top-level blocks: .. mermaid:: graph TD YAML["input.yaml"] YAML --> MAT["materials:
concrete, steel, ..."] YAML --> SEC["section:
geometry + rebars"] YAML --> DEM["demands:
individual load cases"] YAML --> CMB["combinations:
factored sums / stages"] YAML --> ENV["envelopes:
max η among members"] YAML --> OUT["output:
flags and options"] MAT --> SEC DEM --> CMB DEM --> ENV CMB --> ENV style MAT fill:#fff3e0 style SEC fill:#e8f5e9 style DEM fill:#e3f2fd style CMB fill:#e3f2fd style ENV fill:#e3f2fd style OUT fill:#f3e5f5 The parser (``io_yaml.py``) reads each block and constructs the corresponding Python objects: +-------------------+--------------------------------------------------+ | YAML block | Python object produced | +===================+==================================================+ | ``materials`` | dict of ``Material`` instances | +-------------------+--------------------------------------------------+ | ``section`` | ``GenericSection`` or ``RectSection`` | +-------------------+--------------------------------------------------+ | ``demands`` | list of ``{"name", "N", "Mx", "My"}`` dicts | +-------------------+--------------------------------------------------+ | ``combinations`` | list of parsed combination specs | +-------------------+--------------------------------------------------+ | ``envelopes`` | list of parsed envelope specs | +-------------------+--------------------------------------------------+ | ``output`` | dict of flags with defaults applied | +-------------------+--------------------------------------------------+ Demand resolution ~~~~~~~~~~~~~~~~~~ Combinations and envelopes reference demands by name (``ref: G``). The resolution order is: 1. Look up ``ref`` in the ``demands`` block. 2. If not found, look up in previously computed ``combination_results`` (using the combination's final resultant). 3. If not found → error. This means combinations can reference demands, and envelopes can reference both demands and combinations. CLI subcommands ---------------- The CLI (``cli.py``) uses Python's ``argparse`` with two subcommands: .. mermaid:: flowchart TD CMD["gensec"] RUN["gensec run input.yaml
--n-points 400
--output-dir results/"] PLOT["gensec plot data.json
-o custom.png
--dpi 300"] COMPAT["gensec input.yaml
(auto-detected → run)"] CMD --> RUN CMD --> PLOT CMD -.-> COMPAT ``gensec run`` ~~~~~~~~~~~~~~~ The full analysis pipeline: 1. Load YAML → build section, materials, demands. 2. Generate N-Mx diagram (always). 3. Generate N-My diagram (biaxial sections). 4. Generate 3D surface (biaxial sections). 5. Create VerificationEngine → check demands, combinations, envelopes. 6. Export verification JSON/CSV. 7. Per-demand fiber analysis (solve inverse → stress/strain state). 8. Export fiber CSV + section state plots. 9. Generate N-M diagram plot. 10. Generate Mx-My contour plots (if ``generate_mx_my: true``). 11. Generate M-χ diagrams (JSON + CSV + plot). 12. Generate 3D surface plot (if ``generate_3d_surface: true``). 13. Generate bundle, polar ductility, and 3D M-χ-N surface plots. 14. Print summary table. ``gensec plot`` ~~~~~~~~~~~~~~~~ Regenerates a single plot from a previously exported JSON file: 1. Read JSON. 2. Detect data type from the ``"type"`` field (or infer from keys). 3. Reconstruct the data dict expected by the plotting function. 4. Call the appropriate plot function. 5. Save PNG. Supported types: ``moment_curvature``, ``mx_my_contour``, N-M domain, 3D surface. Data-first design ------------------ Every analysis step exports its numerical data (JSON + CSV) **before** generating the plot: .. mermaid:: flowchart LR CALC["Compute M-χ curve"] JSON["Export mx_chi_N0.json"] CSV["Export mx_chi_N0.csv"] PLOT["Generate mx_chi_N0.png"] REPLOT["gensec plot mx_chi_N0.json
(later, without recomputing)"] CALC --> JSON --> PLOT CALC --> CSV JSON -.-> REPLOT This design has three benefits: 1. **No recomputation**: change plot aesthetics without re-running the analysis. 2. **External tools**: import JSON/CSV into Excel, MATLAB, Python scripts, web dashboards, etc. 3. **GUI-ready**: a future GUI reads JSON data and renders its own interactive plots. Output files ------------- A typical run with all options enabled produces: +------------------------------------+------------------------------------------------+ | File | Content | +====================================+================================================+ | ``n_mx_domain.csv`` / ``.json`` | N-Mx interaction point cloud | +------------------------------------+------------------------------------------------+ | ``n_my_domain.csv`` | N-My interaction point cloud | +------------------------------------+------------------------------------------------+ | ``surface_3d.csv`` / ``.json`` | 3D surface (N, Mx, My) point cloud | +------------------------------------+------------------------------------------------+ | ``mx_chi_N{label}.json`` / ``.csv``| M-χ curve at fixed N (with key points) | +------------------------------------+------------------------------------------------+ | ``mx_my_N{label}.json`` / ``.csv`` | Mx-My contour at fixed N | +------------------------------------+------------------------------------------------+ | ``demand_summary.csv`` / ``.json`` | Per-demand η values | +------------------------------------+------------------------------------------------+ | ``combination_summary.json`` | Staged combination results | +------------------------------------+------------------------------------------------+ | ``envelope_summary.json`` | Envelope results with governing member | +------------------------------------+------------------------------------------------+ | ``verification_summary.json`` | Unified export (all three above) | +------------------------------------+------------------------------------------------+ | ``fibers_{name}.csv`` | Per-fiber strain/stress for each demand | +------------------------------------+------------------------------------------------+ PNG plots: ``n_mx_diagram.png``, ``n_my_diagram.png``, ``surface_3d.png``, ``mx_my_N{label}.png``, ``mx_chi_N{label}.png``, ``section_{name}.png``, ``state_{name}.png``, ``demand_utilization.png``, ``section_geometry.png``, ``mx_chi_bundle.png``, ``polar_ductility_N{label}.png``, etc. Verification JSON structure ---------------------------- The ``verification_summary.json`` file contains all three verification types in a single file: .. code-block:: json { "demands": [ { "name": "G", "N_kN": -2000.0, "Mx_kNm": 150.0, "My_kNm": 0.0, "eta_3D": 0.42, "eta_2D": 0.38, "inside": true, "verified": true } ], "combinations": [ { "name": "SLU_sismico", "type": "staged", "resultant": {"N_kN": -1850.0, "Mx_kNm": 350.0, "My_kNm": 100.0}, "stages": [ { "name": "gravitazionale", "cumulative": {"N_kN": -2150.0, "Mx_kNm": 174.0, "My_kNm": 9.0}, "eta_3D": 0.35 }, { "name": "sisma", "cumulative": {"N_kN": -1850.0, "Mx_kNm": 350.0, "My_kNm": 100.0}, "base": {"N_kN": -2150.0, "Mx_kNm": 174.0, "My_kNm": 9.0}, "eta_path": 0.72, "eta_3D": 0.81 } ], "eta_governing": 0.81, "verified": true } ], "envelopes": [ { "name": "Envelope_SLU", "eta_max": 0.81, "governing_member": "SLU_sismico", "verified": true } ] } The ``eta_governing`` of a combination is the maximum across all stages and all enabled η types. The ``eta_max`` of an envelope is the maximum across all members. 3D surface rendering --------------------- The 3D resistance surface plot uses a **lofted surface** technique instead of directly rendering the ConvexHull triangulation: .. mermaid:: flowchart TD H["3D ConvexHull
of (Mx, My, N) point cloud"] S["Slice hull at 20 regular N levels"] C["For each slice:
2D ConvexHull → clean boundary"] R["Resample each contour
to 72 equi-spaced arc-length points"] G["Build structured grid
(20 rows × 72 columns)"] P["plot_surface with
face colours from N"] M["Add contour rings (parallels)
and meridians (longitudes)"] H --> S --> C --> R --> G --> P --> M This produces a smooth surface free of the spurious triangles that plague raw ConvexHull rendering, especially in the tension zone where the point cloud is sparse.