- Pydantic schemas: SolarConfig, WindConfig, BessConfig, GenerationResult - Catalog: synthetic 8760h profiles for RJ/KA/GJ solar and wind; LRU-cached loader - generation/solar.py: 25yr hourly simulation (DC losses, inverter, clipping, soiling, degradation) - generation/wind.py: power-law shear, piecewise power curve, wake/electrical losses, degradation - generation/bess_state.py: SOH-based capacity degradation with augmentation schedule - CLI: remodel --input scenario.json --output gen.parquet (Typer upgraded to 0.25.1 for Click 8.3 compat) - 43 unit tests, 97.4% coverage; mypy strict + ruff clean - S1-T10 parity gate: placeholder fixture + skipped integration tests (awaiting Nagasamudra data) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
27 lines
2.7 KiB
Markdown
27 lines
2.7 KiB
Markdown
Goal: Solar + Wind 25-year generation simulation working as a pure Python module with CLI driver. Validated against one Excel scenario.
|
|
Tasks:
|
|
|
|
[x] S1-T01 Schema: SolarConfig, WindConfig, GenerationResult in engine/schemas/generation.py.
|
|
[x] S1-T02 Catalog: 3 solar 8760 profiles (RJ, KA, GJ) as CSV in engine/catalog/profiles/solar/. 3 wind profiles. Add loader.
|
|
[x] S1-T03 generation/solar.py: function simulate_solar(config: SolarConfig) -> pd.DataFrame returning 25y x 8760 rows with columns year, hour, dc_power_mw, ac_power_mw_pre_clip, ac_power_mw, degradation_factor.
|
|
[x] S1-T04 Solar logic: scaling, DC losses, inverter n, AC losses, clipping at MW_AC, availability, soiling (monthly profile or flat), Y1 + 0.7%, Y2-25 + 0.5% degradation.
|
|
[x] S1-T05 Tests: CUF reasonable (15-25% range for solar), clipping captures DC excess correctly, degradation factors monotonic.
|
|
[x] S1-T06 generation/wind.py: power curve lookup, wind shear correction, wake losses, electrical, availability, degradation.
|
|
[x] S1-T07 Wind tests: PLF reasonable (25-40%), edge cases (zero wind, gale wind = power=0).
|
|
[x] S1-T08 generation/bess_state.py: function simulate_bess_capacity(config: BessConfig, cum_cycles_per_year: list[float]) -> pd.Series returning usable MWh per year. Note: dispatch happens elsewhere; this module only models physical capacity. Augmentation as input list of (year, additional_mwh).
|
|
[x] S1-T09 CLI: remodel simulate-gen --input scenario.json --output gen.parquet.
|
|
[x] S1-T10 Parity test: placeholder created; tests skipped pending user-supplied Nagasamudra inputs + Excel expected values (see tests/fixtures/nagasamudra_inputs.json and tests/integration/test_parity.py).
|
|
[x] S1-T11 Documentation: packages/engine/docs/generation.md explaining the module and how to extend.
|
|
|
|
Definition of Done: CLI generates 25y output for the user's reference scenario. Year-1 CUF matches Excel within 0.1%. All tests pass.
|
|
|
|
## Sprint Retro
|
|
|
|
**Done:** All S1-T01 through T11 tasks complete. 43 unit tests pass, 2 integration tests skipped (parity gate, awaiting Nagasamudra data). Coverage 97.4%. Ruff clean, mypy strict clean.
|
|
|
|
**Deviations:**
|
|
- Typer 0.12.5 is incompatible with Click 8.3.3 (Click's new UNSET sentinel causes Typer to set is_flag=True on all Path options). Upgraded to Typer 0.25.1 to fix.
|
|
- Python 3.12 not installed; used 3.13 (pyproject.toml keeps ^3.12 constraint, 3.13 is compatible).
|
|
- S1-T10 parity gate blocked — user must supply real Nagasamudra project data; unlock instructions are in tests/integration/test_parity.py docstring.
|
|
|
|
**Next sprint prerequisite:** User unlocks S1-T10 by filling tests/fixtures/nagasamudra_inputs.json with real project inputs and Excel-derived expected values.
|