Spaces:
Sleeping
Sleeping
Upload 781 files
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +24 -0
- PyPSA/mcp_output/README_MCP.md +77 -0
- PyPSA/mcp_output/analysis.json +982 -0
- PyPSA/mcp_output/env_info.json +15 -0
- PyPSA/mcp_output/mcp_logs/llm_statistics.json +11 -0
- PyPSA/mcp_output/mcp_logs/run_log.json +66 -0
- PyPSA/mcp_output/mcp_plugin/__init__.py +0 -0
- PyPSA/mcp_output/mcp_plugin/__pycache__/adapter.cpython-310.pyc +0 -0
- PyPSA/mcp_output/mcp_plugin/__pycache__/mcp_service.cpython-310.pyc +0 -0
- PyPSA/mcp_output/mcp_plugin/adapter.py +129 -0
- PyPSA/mcp_output/mcp_plugin/main.py +13 -0
- PyPSA/mcp_output/mcp_plugin/mcp_service.py +524 -0
- PyPSA/mcp_output/requirements.txt +9 -0
- PyPSA/mcp_output/simple_revise_error_analysis.json +6 -0
- PyPSA/mcp_output/start_mcp.py +33 -0
- PyPSA/mcp_output/tests_mcp/test_mcp_basic.py +49 -0
- PyPSA/mcp_output/tests_smoke/test_smoke.py +29 -0
- PyPSA/source/.codespell.ignore +9 -0
- PyPSA/source/.git-blame-ignore-revs +6 -0
- PyPSA/source/.github/ISSUE_TEMPLATE/bug_report.yaml +73 -0
- PyPSA/source/.github/ISSUE_TEMPLATE/config.yml +9 -0
- PyPSA/source/.github/ISSUE_TEMPLATE/documentation_improvement.yaml +26 -0
- PyPSA/source/.github/ISSUE_TEMPLATE/feature_request.md +16 -0
- PyPSA/source/.github/dependabot.yml +18 -0
- PyPSA/source/.github/pull_request_template.md +11 -0
- PyPSA/source/.github/workflows/codeql.yml +96 -0
- PyPSA/source/.github/workflows/release.yml +174 -0
- PyPSA/source/.github/workflows/test-models.yml +206 -0
- PyPSA/source/.github/workflows/test.yml +223 -0
- PyPSA/source/.gitignore +54 -0
- PyPSA/source/.pre-commit-config.yaml +58 -0
- PyPSA/source/.readthedocs.yml +28 -0
- PyPSA/source/CITATION.cff +22 -0
- PyPSA/source/CONTRIBUTING.md +11 -0
- PyPSA/source/LICENSE +18 -0
- PyPSA/source/LICENSES/CC-BY-4.0.txt +156 -0
- PyPSA/source/LICENSES/MIT.txt +18 -0
- PyPSA/source/MANIFEST.in +10 -0
- PyPSA/source/README.md +210 -0
- PyPSA/source/REUSE.toml +51 -0
- PyPSA/source/__init__.py +4 -0
- PyPSA/source/codecov.yml +15 -0
- PyPSA/source/docs/CODE_OF_CONDUCT.md +143 -0
- PyPSA/source/docs/api/components/common.md +7 -0
- PyPSA/source/docs/api/components/components.md +24 -0
- PyPSA/source/docs/api/components/types/buses.md +7 -0
- PyPSA/source/docs/api/components/types/carriers.md +7 -0
- PyPSA/source/docs/api/components/types/generators.md +7 -0
- PyPSA/source/docs/api/components/types/global-constraints.md +7 -0
- PyPSA/source/docs/api/components/types/lines.md +13 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,27 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
PyPSA/source/docs/assets/images/ac_dc_meshed.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
PyPSA/source/docs/assets/images/carbon_management-energy_balance-area_plot-AC-bus_carrier.png filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
PyPSA/source/docs/assets/images/carbon_management-energy_balance-area_plot.png filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
PyPSA/source/docs/assets/images/elec_s_256_lv1.09_Co2L-3H.png filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
PyPSA/source/docs/assets/images/lmp_and_line-loading.png filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
PyPSA/source/docs/assets/images/load-distribution.png filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
PyPSA/source/docs/assets/images/pypsa-animation.png filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
PyPSA/source/docs/assets/images/reactive-power.png filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
PyPSA/source/docs/assets/images/scigrid-curtailment.png filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
PyPSA/source/docs/assets/images/stacked-gen_and_storage-scigrid.png filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
PyPSA/source/docs/assets/images/stacked-gen.png filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
PyPSA/source/docs/assets/images/storage-scigrid.png filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
PyPSA/source/docs/assets/logo/logo-primary-dark.png filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
PyPSA/source/docs/assets/logo/logo-primary-light-white-bg.png filter=lfs diff=lfs merge=lfs -text
|
| 50 |
+
PyPSA/source/docs/assets/logo/logo-primary-light.png filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
PyPSA/source/docs/assets/logo/logo-secondary-dark.png filter=lfs diff=lfs merge=lfs -text
|
| 52 |
+
PyPSA/source/docs/assets/logo/logo-secondary-light.png filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
PyPSA/source/docs/assets/logo/logo-white-bg.png filter=lfs diff=lfs merge=lfs -text
|
| 54 |
+
PyPSA/source/docs/assets/logo/logo.png filter=lfs diff=lfs merge=lfs -text
|
| 55 |
+
PyPSA/source/examples/networks/ac-dc-meshed/ac-dc-meshed.nc filter=lfs diff=lfs merge=lfs -text
|
| 56 |
+
PyPSA/source/examples/networks/model-energy/model-energy.nc filter=lfs diff=lfs merge=lfs -text
|
| 57 |
+
PyPSA/source/examples/networks/scigrid-de/scigrid-de.nc filter=lfs diff=lfs merge=lfs -text
|
| 58 |
+
PyPSA/source/examples/networks/stochastic-network/stochastic-network.nc filter=lfs diff=lfs merge=lfs -text
|
| 59 |
+
PyPSA/source/examples/networks/storage-hvdc/storage-hvdc.nc filter=lfs diff=lfs merge=lfs -text
|
PyPSA/mcp_output/README_MCP.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# MCP Plugin README
|
| 2 |
+
|
| 3 |
+
## Project Overview
|
| 4 |
+
|
| 5 |
+
The MCP Plugin is a component of the PyPSA (Python for Power System Analysis) ecosystem, designed to enhance the capabilities of power system modeling and analysis. PyPSA is an open-source toolbox for simulating and optimizing modern power systems over multiple periods. The MCP Plugin extends these functionalities by providing additional tools and features for more detailed and specific analyses.
|
| 6 |
+
|
| 7 |
+
### Key Features
|
| 8 |
+
|
| 9 |
+
- **Advanced Power System Modeling**: Leverage the robust PyPSA framework for detailed power system simulations.
|
| 10 |
+
- **Optimization Capabilities**: Perform complex optimization tasks to improve system efficiency and reliability.
|
| 11 |
+
- **Extensible and Customizable**: Easily integrate with existing PyPSA setups and customize according to specific project needs.
|
| 12 |
+
|
| 13 |
+
## Installation Instructions
|
| 14 |
+
|
| 15 |
+
To install the MCP Plugin, ensure you have Python installed on your system. The plugin requires Python 3.7 or later. Follow these steps to install:
|
| 16 |
+
|
| 17 |
+
1. **Clone the Repository**:
|
| 18 |
+
```bash
|
| 19 |
+
git clone https://github.com/PyPSA/PyPSA.git
|
| 20 |
+
cd PyPSA
|
| 21 |
+
```
|
| 22 |
+
|
| 23 |
+
2. **Install Dependencies**:
|
| 24 |
+
The MCP Plugin requires several Python packages. You can install them using `pip`:
|
| 25 |
+
```bash
|
| 26 |
+
pip install numpy pandas matplotlib
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
Optional dependencies for enhanced functionalities include:
|
| 30 |
+
```bash
|
| 31 |
+
pip install geopandas plotly
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
3. **Install the Plugin**:
|
| 35 |
+
Navigate to the plugin directory and install it:
|
| 36 |
+
```bash
|
| 37 |
+
pip install .
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
## Usage Methods
|
| 41 |
+
|
| 42 |
+
Once installed, the MCP Plugin can be used within the PyPSA framework to perform various analyses. Here’s a basic usage example:
|
| 43 |
+
|
| 44 |
+
1. **Import the Plugin**:
|
| 45 |
+
```python
|
| 46 |
+
import pypsa
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
2. **Create a Network**:
|
| 50 |
+
```python
|
| 51 |
+
network = pypsa.Network()
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
3. **Add Components and Perform Analysis**:
|
| 55 |
+
Use the plugin’s extended functionalities to add components and perform analyses on the network.
|
| 56 |
+
|
| 57 |
+
## Available Tool Endpoints
|
| 58 |
+
|
| 59 |
+
The MCP Plugin provides several endpoints for interacting with the power system models:
|
| 60 |
+
|
| 61 |
+
- **Network Optimization**: Optimize network configurations for efficiency.
|
| 62 |
+
- **Power Flow Analysis**: Conduct detailed power flow studies.
|
| 63 |
+
- **Statistical Analysis**: Perform statistical evaluations of network performance.
|
| 64 |
+
|
| 65 |
+
## Notes and Troubleshooting
|
| 66 |
+
|
| 67 |
+
- **Compatibility**: Ensure that your Python environment is compatible with the required dependencies.
|
| 68 |
+
- **Performance**: For large-scale simulations, consider optimizing your system resources.
|
| 69 |
+
- **Common Issues**:
|
| 70 |
+
- **Installation Errors**: Ensure all dependencies are correctly installed.
|
| 71 |
+
- **Runtime Errors**: Check for compatibility issues with other installed packages.
|
| 72 |
+
|
| 73 |
+
For further assistance, refer to the [PyPSA documentation](https://pypsa.org/doc/) or reach out to the community via the [PyPSA GitHub repository](https://github.com/PyPSA/PyPSA).
|
| 74 |
+
|
| 75 |
+
## Conclusion
|
| 76 |
+
|
| 77 |
+
The MCP Plugin is a powerful extension to the PyPSA framework, offering advanced tools for power system analysis and optimization. By following the installation and usage instructions, users can effectively integrate and utilize the plugin for their specific needs. For any issues or contributions, please refer to the official PyPSA repository.
|
PyPSA/mcp_output/analysis.json
ADDED
|
@@ -0,0 +1,982 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"summary": {
|
| 3 |
+
"repository_url": "https://github.com/PyPSA/PyPSA",
|
| 4 |
+
"summary": "Imported via zip fallback, file count: 280",
|
| 5 |
+
"file_tree": {
|
| 6 |
+
".github/ISSUE_TEMPLATE/bug_report.yaml": {
|
| 7 |
+
"size": 1876
|
| 8 |
+
},
|
| 9 |
+
".github/ISSUE_TEMPLATE/config.yml": {
|
| 10 |
+
"size": 248
|
| 11 |
+
},
|
| 12 |
+
".github/ISSUE_TEMPLATE/documentation_improvement.yaml": {
|
| 13 |
+
"size": 747
|
| 14 |
+
},
|
| 15 |
+
".github/ISSUE_TEMPLATE/feature_request.md": {
|
| 16 |
+
"size": 480
|
| 17 |
+
},
|
| 18 |
+
".github/dependabot.yml": {
|
| 19 |
+
"size": 536
|
| 20 |
+
},
|
| 21 |
+
".github/pull_request_template.md": {
|
| 22 |
+
"size": 449
|
| 23 |
+
},
|
| 24 |
+
".github/workflows/codeql.yml": {
|
| 25 |
+
"size": 4362
|
| 26 |
+
},
|
| 27 |
+
".github/workflows/release.yml": {
|
| 28 |
+
"size": 5532
|
| 29 |
+
},
|
| 30 |
+
".github/workflows/test-models.yml": {
|
| 31 |
+
"size": 5584
|
| 32 |
+
},
|
| 33 |
+
".github/workflows/test.yml": {
|
| 34 |
+
"size": 5866
|
| 35 |
+
},
|
| 36 |
+
".pre-commit-config.yaml": {
|
| 37 |
+
"size": 1494
|
| 38 |
+
},
|
| 39 |
+
".readthedocs.yml": {
|
| 40 |
+
"size": 699
|
| 41 |
+
},
|
| 42 |
+
"CONTRIBUTING.md": {
|
| 43 |
+
"size": 430
|
| 44 |
+
},
|
| 45 |
+
"LICENSES/CC-BY-4.0.txt": {
|
| 46 |
+
"size": 16983
|
| 47 |
+
},
|
| 48 |
+
"LICENSES/MIT.txt": {
|
| 49 |
+
"size": 1078
|
| 50 |
+
},
|
| 51 |
+
"README.md": {
|
| 52 |
+
"size": 9772
|
| 53 |
+
},
|
| 54 |
+
"REUSE.toml": {
|
| 55 |
+
"size": 1508
|
| 56 |
+
},
|
| 57 |
+
"codecov.yml": {
|
| 58 |
+
"size": 210
|
| 59 |
+
},
|
| 60 |
+
"docs/CODE_OF_CONDUCT.md": {
|
| 61 |
+
"size": 5811
|
| 62 |
+
},
|
| 63 |
+
"docs/api/components/common.md": {
|
| 64 |
+
"size": 117
|
| 65 |
+
},
|
| 66 |
+
"docs/api/components/components.md": {
|
| 67 |
+
"size": 507
|
| 68 |
+
},
|
| 69 |
+
"docs/api/components/types/buses.md": {
|
| 70 |
+
"size": 116
|
| 71 |
+
},
|
| 72 |
+
"docs/api/components/types/carriers.md": {
|
| 73 |
+
"size": 119
|
| 74 |
+
},
|
| 75 |
+
"docs/api/components/types/generators.md": {
|
| 76 |
+
"size": 121
|
| 77 |
+
},
|
| 78 |
+
"docs/api/components/types/global-constraints.md": {
|
| 79 |
+
"size": 128
|
| 80 |
+
},
|
| 81 |
+
"docs/api/components/types/lines.md": {
|
| 82 |
+
"size": 224
|
| 83 |
+
},
|
| 84 |
+
"docs/api/components/types/links.md": {
|
| 85 |
+
"size": 116
|
| 86 |
+
},
|
| 87 |
+
"docs/api/components/types/loads.md": {
|
| 88 |
+
"size": 116
|
| 89 |
+
},
|
| 90 |
+
"docs/api/components/types/shapes.md": {
|
| 91 |
+
"size": 117
|
| 92 |
+
},
|
| 93 |
+
"docs/api/components/types/shunt-impedances.md": {
|
| 94 |
+
"size": 126
|
| 95 |
+
},
|
| 96 |
+
"docs/api/components/types/storage-units.md": {
|
| 97 |
+
"size": 123
|
| 98 |
+
},
|
| 99 |
+
"docs/api/components/types/stores.md": {
|
| 100 |
+
"size": 117
|
| 101 |
+
},
|
| 102 |
+
"docs/api/components/types/sub-networks.md": {
|
| 103 |
+
"size": 122
|
| 104 |
+
},
|
| 105 |
+
"docs/api/components/types/transformers.md": {
|
| 106 |
+
"size": 238
|
| 107 |
+
},
|
| 108 |
+
"docs/api/networks/cluster.md": {
|
| 109 |
+
"size": 129
|
| 110 |
+
},
|
| 111 |
+
"docs/api/networks/collection.md": {
|
| 112 |
+
"size": 265
|
| 113 |
+
},
|
| 114 |
+
"docs/api/networks/components.md": {
|
| 115 |
+
"size": 210
|
| 116 |
+
},
|
| 117 |
+
"docs/api/networks/descriptors.md": {
|
| 118 |
+
"size": 212
|
| 119 |
+
},
|
| 120 |
+
"docs/api/networks/indexing.md": {
|
| 121 |
+
"size": 200
|
| 122 |
+
},
|
| 123 |
+
"docs/api/networks/io.md": {
|
| 124 |
+
"size": 164
|
| 125 |
+
},
|
| 126 |
+
"docs/api/networks/network.md": {
|
| 127 |
+
"size": 236
|
| 128 |
+
},
|
| 129 |
+
"docs/api/networks/optimize.md": {
|
| 130 |
+
"size": 424
|
| 131 |
+
},
|
| 132 |
+
"docs/api/networks/plot.md": {
|
| 133 |
+
"size": 445
|
| 134 |
+
},
|
| 135 |
+
"docs/api/networks/power-flow.md": {
|
| 136 |
+
"size": 179
|
| 137 |
+
},
|
| 138 |
+
"docs/api/networks/statistics.md": {
|
| 139 |
+
"size": 348
|
| 140 |
+
},
|
| 141 |
+
"docs/api/networks/subnetwork.md": {
|
| 142 |
+
"size": 164
|
| 143 |
+
},
|
| 144 |
+
"docs/api/networks/transform.md": {
|
| 145 |
+
"size": 178
|
| 146 |
+
},
|
| 147 |
+
"docs/api/other/api-examples.md": {
|
| 148 |
+
"size": 267
|
| 149 |
+
},
|
| 150 |
+
"docs/api/other/common.md": {
|
| 151 |
+
"size": 669
|
| 152 |
+
},
|
| 153 |
+
"docs/api/other/consistency.md": {
|
| 154 |
+
"size": 624
|
| 155 |
+
},
|
| 156 |
+
"docs/api/other/options.md": {
|
| 157 |
+
"size": 627
|
| 158 |
+
},
|
| 159 |
+
"docs/assets/javascripts/gurubase-widget.js": {
|
| 160 |
+
"size": 1197
|
| 161 |
+
},
|
| 162 |
+
"docs/assets/javascripts/matjax.js": {
|
| 163 |
+
"size": 502
|
| 164 |
+
},
|
| 165 |
+
"docs/assets/javascripts/readthedocs.js": {
|
| 166 |
+
"size": 809
|
| 167 |
+
},
|
| 168 |
+
"docs/contributing/contributing.md": {
|
| 169 |
+
"size": 6313
|
| 170 |
+
},
|
| 171 |
+
"docs/contributing/contributors.md": {
|
| 172 |
+
"size": 1441
|
| 173 |
+
},
|
| 174 |
+
"docs/examples/examples.md": {
|
| 175 |
+
"size": 8698
|
| 176 |
+
},
|
| 177 |
+
"docs/home/citing.md": {
|
| 178 |
+
"size": 9740
|
| 179 |
+
},
|
| 180 |
+
"docs/home/features.md": {
|
| 181 |
+
"size": 7780
|
| 182 |
+
},
|
| 183 |
+
"docs/home/installation.md": {
|
| 184 |
+
"size": 5455
|
| 185 |
+
},
|
| 186 |
+
"docs/home/license.md": {
|
| 187 |
+
"size": 1282
|
| 188 |
+
},
|
| 189 |
+
"docs/home/models.md": {
|
| 190 |
+
"size": 5138
|
| 191 |
+
},
|
| 192 |
+
"docs/home/users.md": {
|
| 193 |
+
"size": 23810
|
| 194 |
+
},
|
| 195 |
+
"docs/hooks/cleanup.py": {
|
| 196 |
+
"size": 968
|
| 197 |
+
},
|
| 198 |
+
"docs/hooks/dynamic_inspect.py": {
|
| 199 |
+
"size": 1082
|
| 200 |
+
},
|
| 201 |
+
"docs/hooks/path_aliases.py": {
|
| 202 |
+
"size": 4223
|
| 203 |
+
},
|
| 204 |
+
"docs/hooks/shortcodes.py": {
|
| 205 |
+
"size": 16035
|
| 206 |
+
},
|
| 207 |
+
"docs/index.md": {
|
| 208 |
+
"size": 4839
|
| 209 |
+
},
|
| 210 |
+
"docs/release-notes.md": {
|
| 211 |
+
"size": 128422
|
| 212 |
+
},
|
| 213 |
+
"docs/requirements.txt": {
|
| 214 |
+
"size": 17102
|
| 215 |
+
},
|
| 216 |
+
"docs/user-guide/collection.md": {
|
| 217 |
+
"size": 7632
|
| 218 |
+
},
|
| 219 |
+
"docs/user-guide/components.md": {
|
| 220 |
+
"size": 9304
|
| 221 |
+
},
|
| 222 |
+
"docs/user-guide/components/buses.md": {
|
| 223 |
+
"size": 654
|
| 224 |
+
},
|
| 225 |
+
"docs/user-guide/components/carriers.md": {
|
| 226 |
+
"size": 682
|
| 227 |
+
},
|
| 228 |
+
"docs/user-guide/components/generators.md": {
|
| 229 |
+
"size": 1012
|
| 230 |
+
},
|
| 231 |
+
"docs/user-guide/components/global-constraints.md": {
|
| 232 |
+
"size": 353
|
| 233 |
+
},
|
| 234 |
+
"docs/user-guide/components/line-types.md": {
|
| 235 |
+
"size": 936
|
| 236 |
+
},
|
| 237 |
+
"docs/user-guide/components/lines.md": {
|
| 238 |
+
"size": 951
|
| 239 |
+
},
|
| 240 |
+
"docs/user-guide/components/links.md": {
|
| 241 |
+
"size": 3686
|
| 242 |
+
},
|
| 243 |
+
"docs/user-guide/components/loads.md": {
|
| 244 |
+
"size": 867
|
| 245 |
+
},
|
| 246 |
+
"docs/user-guide/components/shapes.md": {
|
| 247 |
+
"size": 337
|
| 248 |
+
},
|
| 249 |
+
"docs/user-guide/components/shunt-impedances.md": {
|
| 250 |
+
"size": 943
|
| 251 |
+
},
|
| 252 |
+
"docs/user-guide/components/storage-units.md": {
|
| 253 |
+
"size": 1551
|
| 254 |
+
},
|
| 255 |
+
"docs/user-guide/components/stores.md": {
|
| 256 |
+
"size": 2536
|
| 257 |
+
},
|
| 258 |
+
"docs/user-guide/components/sub-networks.md": {
|
| 259 |
+
"size": 893
|
| 260 |
+
},
|
| 261 |
+
"docs/user-guide/components/transformer-types.md": {
|
| 262 |
+
"size": 855
|
| 263 |
+
},
|
| 264 |
+
"docs/user-guide/components/transformers.md": {
|
| 265 |
+
"size": 683
|
| 266 |
+
},
|
| 267 |
+
"docs/user-guide/design.md": {
|
| 268 |
+
"size": 17819
|
| 269 |
+
},
|
| 270 |
+
"docs/user-guide/faq.md": {
|
| 271 |
+
"size": 10223
|
| 272 |
+
},
|
| 273 |
+
"docs/user-guide/import-export.md": {
|
| 274 |
+
"size": 7634
|
| 275 |
+
},
|
| 276 |
+
"docs/user-guide/learning-materials.md": {
|
| 277 |
+
"size": 1010
|
| 278 |
+
},
|
| 279 |
+
"docs/user-guide/linear-power-flow.md": {
|
| 280 |
+
"size": 3856
|
| 281 |
+
},
|
| 282 |
+
"docs/user-guide/network-optimization.md": {
|
| 283 |
+
"size": 9547
|
| 284 |
+
},
|
| 285 |
+
"docs/user-guide/optimization/capacity-limits.md": {
|
| 286 |
+
"size": 7284
|
| 287 |
+
},
|
| 288 |
+
"docs/user-guide/optimization/contingencies.md": {
|
| 289 |
+
"size": 6579
|
| 290 |
+
},
|
| 291 |
+
"docs/user-guide/optimization/custom-constraints.md": {
|
| 292 |
+
"size": 7494
|
| 293 |
+
},
|
| 294 |
+
"docs/user-guide/optimization/dispatch-limits.md": {
|
| 295 |
+
"size": 7222
|
| 296 |
+
},
|
| 297 |
+
"docs/user-guide/optimization/energy-balance.md": {
|
| 298 |
+
"size": 3791
|
| 299 |
+
},
|
| 300 |
+
"docs/user-guide/optimization/global-constraints.md": {
|
| 301 |
+
"size": 12604
|
| 302 |
+
},
|
| 303 |
+
"docs/user-guide/optimization/modelling-to-generate-alternatives.md": {
|
| 304 |
+
"size": 5313
|
| 305 |
+
},
|
| 306 |
+
"docs/user-guide/optimization/objective.md": {
|
| 307 |
+
"size": 10001
|
| 308 |
+
},
|
| 309 |
+
"docs/user-guide/optimization/overview.md": {
|
| 310 |
+
"size": 3517
|
| 311 |
+
},
|
| 312 |
+
"docs/user-guide/optimization/pathway-planning.md": {
|
| 313 |
+
"size": 10983
|
| 314 |
+
},
|
| 315 |
+
"docs/user-guide/optimization/power-flow.md": {
|
| 316 |
+
"size": 7236
|
| 317 |
+
},
|
| 318 |
+
"docs/user-guide/optimization/stochastic.md": {
|
| 319 |
+
"size": 22635
|
| 320 |
+
},
|
| 321 |
+
"docs/user-guide/optimization/storage.md": {
|
| 322 |
+
"size": 11229
|
| 323 |
+
},
|
| 324 |
+
"docs/user-guide/optimization/unit-commitment.md": {
|
| 325 |
+
"size": 16807
|
| 326 |
+
},
|
| 327 |
+
"docs/user-guide/options.md": {
|
| 328 |
+
"size": 5386
|
| 329 |
+
},
|
| 330 |
+
"docs/user-guide/plotting/charts.md": {
|
| 331 |
+
"size": 15305
|
| 332 |
+
},
|
| 333 |
+
"docs/user-guide/power-flow.md": {
|
| 334 |
+
"size": 10049
|
| 335 |
+
},
|
| 336 |
+
"docs/user-guide/statistics.md": {
|
| 337 |
+
"size": 6948
|
| 338 |
+
},
|
| 339 |
+
"docs/user-guide/support.md": {
|
| 340 |
+
"size": 973
|
| 341 |
+
},
|
| 342 |
+
"docs/user-guide/troubleshooting.md": {
|
| 343 |
+
"size": 5941
|
| 344 |
+
},
|
| 345 |
+
"docs/user-guide/user-guide.md": {
|
| 346 |
+
"size": 1165
|
| 347 |
+
},
|
| 348 |
+
"docs/user-guide/v1-guide.md": {
|
| 349 |
+
"size": 9077
|
| 350 |
+
},
|
| 351 |
+
"examples/networks/ac-dc-meshed/ac-dc-meshed/crs.json": {
|
| 352 |
+
"size": 920
|
| 353 |
+
},
|
| 354 |
+
"examples/networks/ac-dc-meshed/ac-dc-meshed/meta.json": {
|
| 355 |
+
"size": 2
|
| 356 |
+
},
|
| 357 |
+
"examples/networks/model-energy/model-energy/crs.json": {
|
| 358 |
+
"size": 920
|
| 359 |
+
},
|
| 360 |
+
"examples/networks/model-energy/model-energy/meta.json": {
|
| 361 |
+
"size": 2
|
| 362 |
+
},
|
| 363 |
+
"examples/networks/scigrid-de/scigrid-de/crs.json": {
|
| 364 |
+
"size": 920
|
| 365 |
+
},
|
| 366 |
+
"examples/networks/scigrid-de/scigrid-de/meta.json": {
|
| 367 |
+
"size": 2
|
| 368 |
+
},
|
| 369 |
+
"examples/networks/storage-hvdc/storage-hvdc/crs.json": {
|
| 370 |
+
"size": 920
|
| 371 |
+
},
|
| 372 |
+
"examples/networks/storage-hvdc/storage-hvdc/meta.json": {
|
| 373 |
+
"size": 2
|
| 374 |
+
},
|
| 375 |
+
"mkdocs.yml": {
|
| 376 |
+
"size": 15022
|
| 377 |
+
},
|
| 378 |
+
"pyproject.toml": {
|
| 379 |
+
"size": 6831
|
| 380 |
+
},
|
| 381 |
+
"pypsa/__init__.py": {
|
| 382 |
+
"size": 2807
|
| 383 |
+
},
|
| 384 |
+
"pypsa/_options.py": {
|
| 385 |
+
"size": 13897
|
| 386 |
+
},
|
| 387 |
+
"pypsa/clustering/__init__.py": {
|
| 388 |
+
"size": 3376
|
| 389 |
+
},
|
| 390 |
+
"pypsa/clustering/spatial.py": {
|
| 391 |
+
"size": 35407
|
| 392 |
+
},
|
| 393 |
+
"pypsa/clustering/temporal.py": {
|
| 394 |
+
"size": 132
|
| 395 |
+
},
|
| 396 |
+
"pypsa/collection.py": {
|
| 397 |
+
"size": 28144
|
| 398 |
+
},
|
| 399 |
+
"pypsa/common.py": {
|
| 400 |
+
"size": 27902
|
| 401 |
+
},
|
| 402 |
+
"pypsa/components/__init__.py": {
|
| 403 |
+
"size": 1130
|
| 404 |
+
},
|
| 405 |
+
"pypsa/components/_types/__init__.py": {
|
| 406 |
+
"size": 1419
|
| 407 |
+
},
|
| 408 |
+
"pypsa/components/_types/_patch.py": {
|
| 409 |
+
"size": 3265
|
| 410 |
+
},
|
| 411 |
+
"pypsa/components/_types/buses.py": {
|
| 412 |
+
"size": 1352
|
| 413 |
+
},
|
| 414 |
+
"pypsa/components/_types/carriers.py": {
|
| 415 |
+
"size": 1379
|
| 416 |
+
},
|
| 417 |
+
"pypsa/components/_types/generators.py": {
|
| 418 |
+
"size": 2298
|
| 419 |
+
},
|
| 420 |
+
"pypsa/components/_types/global_constraints.py": {
|
| 421 |
+
"size": 1456
|
| 422 |
+
},
|
| 423 |
+
"pypsa/components/_types/line_types.py": {
|
| 424 |
+
"size": 1393
|
| 425 |
+
},
|
| 426 |
+
"pypsa/components/_types/lines.py": {
|
| 427 |
+
"size": 3882
|
| 428 |
+
},
|
| 429 |
+
"pypsa/components/_types/links.py": {
|
| 430 |
+
"size": 3090
|
| 431 |
+
},
|
| 432 |
+
"pypsa/components/_types/loads.py": {
|
| 433 |
+
"size": 1277
|
| 434 |
+
},
|
| 435 |
+
"pypsa/components/_types/shapes.py": {
|
| 436 |
+
"size": 1205
|
| 437 |
+
},
|
| 438 |
+
"pypsa/components/_types/shunt_impedances.py": {
|
| 439 |
+
"size": 1273
|
| 440 |
+
},
|
| 441 |
+
"pypsa/components/_types/storage_units.py": {
|
| 442 |
+
"size": 2518
|
| 443 |
+
},
|
| 444 |
+
"pypsa/components/_types/stores.py": {
|
| 445 |
+
"size": 2178
|
| 446 |
+
},
|
| 447 |
+
"pypsa/components/_types/sub_networks.py": {
|
| 448 |
+
"size": 1408
|
| 449 |
+
},
|
| 450 |
+
"pypsa/components/_types/transformer_types.py": {
|
| 451 |
+
"size": 1449
|
| 452 |
+
},
|
| 453 |
+
"pypsa/components/_types/transformers.py": {
|
| 454 |
+
"size": 2366
|
| 455 |
+
},
|
| 456 |
+
"pypsa/components/abstract.py": {
|
| 457 |
+
"size": 2676
|
| 458 |
+
},
|
| 459 |
+
"pypsa/components/array.py": {
|
| 460 |
+
"size": 12538
|
| 461 |
+
},
|
| 462 |
+
"pypsa/components/common.py": {
|
| 463 |
+
"size": 1848
|
| 464 |
+
},
|
| 465 |
+
"pypsa/components/components.py": {
|
| 466 |
+
"size": 26324
|
| 467 |
+
},
|
| 468 |
+
"pypsa/components/descriptors.py": {
|
| 469 |
+
"size": 9148
|
| 470 |
+
},
|
| 471 |
+
"pypsa/components/index.py": {
|
| 472 |
+
"size": 4049
|
| 473 |
+
},
|
| 474 |
+
"pypsa/components/legacy.py": {
|
| 475 |
+
"size": 2654
|
| 476 |
+
},
|
| 477 |
+
"pypsa/components/store.py": {
|
| 478 |
+
"size": 6550
|
| 479 |
+
},
|
| 480 |
+
"pypsa/components/transform.py": {
|
| 481 |
+
"size": 6882
|
| 482 |
+
},
|
| 483 |
+
"pypsa/components/types.py": {
|
| 484 |
+
"size": 7435
|
| 485 |
+
},
|
| 486 |
+
"pypsa/consistency.py": {
|
| 487 |
+
"size": 37582
|
| 488 |
+
},
|
| 489 |
+
"pypsa/constants.py": {
|
| 490 |
+
"size": 458
|
| 491 |
+
},
|
| 492 |
+
"pypsa/definitions/components.py": {
|
| 493 |
+
"size": 2020
|
| 494 |
+
},
|
| 495 |
+
"pypsa/definitions/structures.py": {
|
| 496 |
+
"size": 2240
|
| 497 |
+
},
|
| 498 |
+
"pypsa/deprecations.py": {
|
| 499 |
+
"size": 593
|
| 500 |
+
},
|
| 501 |
+
"pypsa/descriptors.py": {
|
| 502 |
+
"size": 8736
|
| 503 |
+
},
|
| 504 |
+
"pypsa/examples.py": {
|
| 505 |
+
"size": 6607
|
| 506 |
+
},
|
| 507 |
+
"pypsa/geo.py": {
|
| 508 |
+
"size": 6227
|
| 509 |
+
},
|
| 510 |
+
"pypsa/guards.py": {
|
| 511 |
+
"size": 7156
|
| 512 |
+
},
|
| 513 |
+
"pypsa/network/__init__.py": {
|
| 514 |
+
"size": 138
|
| 515 |
+
},
|
| 516 |
+
"pypsa/network/abstract.py": {
|
| 517 |
+
"size": 2775
|
| 518 |
+
},
|
| 519 |
+
"pypsa/network/components.py": {
|
| 520 |
+
"size": 30570
|
| 521 |
+
},
|
| 522 |
+
"pypsa/network/descriptors.py": {
|
| 523 |
+
"size": 8052
|
| 524 |
+
},
|
| 525 |
+
"pypsa/network/graph.py": {
|
| 526 |
+
"size": 10946
|
| 527 |
+
},
|
| 528 |
+
"pypsa/network/index.py": {
|
| 529 |
+
"size": 40162
|
| 530 |
+
},
|
| 531 |
+
"pypsa/network/io.py": {
|
| 532 |
+
"size": 86634
|
| 533 |
+
},
|
| 534 |
+
"pypsa/network/power_flow.py": {
|
| 535 |
+
"size": 67785
|
| 536 |
+
},
|
| 537 |
+
"pypsa/network/transform.py": {
|
| 538 |
+
"size": 21288
|
| 539 |
+
},
|
| 540 |
+
"pypsa/networks.py": {
|
| 541 |
+
"size": 62697
|
| 542 |
+
},
|
| 543 |
+
"pypsa/optimization/__init__.py": {
|
| 544 |
+
"size": 393
|
| 545 |
+
},
|
| 546 |
+
"pypsa/optimization/abstract.py": {
|
| 547 |
+
"size": 24469
|
| 548 |
+
},
|
| 549 |
+
"pypsa/optimization/common.py": {
|
| 550 |
+
"size": 2361
|
| 551 |
+
},
|
| 552 |
+
"pypsa/optimization/constraints.py": {
|
| 553 |
+
"size": 64639
|
| 554 |
+
},
|
| 555 |
+
"pypsa/optimization/expressions.py": {
|
| 556 |
+
"size": 26869
|
| 557 |
+
},
|
| 558 |
+
"pypsa/optimization/global_constraints.py": {
|
| 559 |
+
"size": 32963
|
| 560 |
+
},
|
| 561 |
+
"pypsa/optimization/mga.py": {
|
| 562 |
+
"size": 28507
|
| 563 |
+
},
|
| 564 |
+
"pypsa/optimization/optimize.py": {
|
| 565 |
+
"size": 40975
|
| 566 |
+
},
|
| 567 |
+
"pypsa/optimization/variables.py": {
|
| 568 |
+
"size": 7716
|
| 569 |
+
},
|
| 570 |
+
"pypsa/plot/__init__.py": {
|
| 571 |
+
"size": 641
|
| 572 |
+
},
|
| 573 |
+
"pypsa/plot/accessor.py": {
|
| 574 |
+
"size": 1401
|
| 575 |
+
},
|
| 576 |
+
"pypsa/plot/maps/__init__.py": {
|
| 577 |
+
"size": 460
|
| 578 |
+
},
|
| 579 |
+
"pypsa/plot/maps/common.py": {
|
| 580 |
+
"size": 28329
|
| 581 |
+
},
|
| 582 |
+
"pypsa/plot/maps/interactive.py": {
|
| 583 |
+
"size": 76737
|
| 584 |
+
},
|
| 585 |
+
"pypsa/plot/maps/static.py": {
|
| 586 |
+
"size": 66061
|
| 587 |
+
},
|
| 588 |
+
"pypsa/plot/statistics/__init__.py": {
|
| 589 |
+
"size": 420
|
| 590 |
+
},
|
| 591 |
+
"pypsa/plot/statistics/base.py": {
|
| 592 |
+
"size": 2845
|
| 593 |
+
},
|
| 594 |
+
"pypsa/plot/statistics/charts.py": {
|
| 595 |
+
"size": 22037
|
| 596 |
+
},
|
| 597 |
+
"pypsa/plot/statistics/maps.py": {
|
| 598 |
+
"size": 12641
|
| 599 |
+
},
|
| 600 |
+
"pypsa/plot/statistics/plotter.py": {
|
| 601 |
+
"size": 31725
|
| 602 |
+
},
|
| 603 |
+
"pypsa/plot/statistics/schema.py": {
|
| 604 |
+
"size": 9371
|
| 605 |
+
},
|
| 606 |
+
"pypsa/statistics/__init__.py": {
|
| 607 |
+
"size": 510
|
| 608 |
+
},
|
| 609 |
+
"pypsa/statistics/abstract.py": {
|
| 610 |
+
"size": 10351
|
| 611 |
+
},
|
| 612 |
+
"pypsa/statistics/expressions.py": {
|
| 613 |
+
"size": 113146
|
| 614 |
+
},
|
| 615 |
+
"pypsa/statistics/grouping.py": {
|
| 616 |
+
"size": 13732
|
| 617 |
+
},
|
| 618 |
+
"pypsa/type_utils.py": {
|
| 619 |
+
"size": 1135
|
| 620 |
+
},
|
| 621 |
+
"pypsa/version.py": {
|
| 622 |
+
"size": 1410
|
| 623 |
+
},
|
| 624 |
+
"test/conftest.py": {
|
| 625 |
+
"size": 8906
|
| 626 |
+
},
|
| 627 |
+
"test/data/ac-dc-meshed/results-lopf/crs.json": {
|
| 628 |
+
"size": 921
|
| 629 |
+
},
|
| 630 |
+
"test/data/ac-dc-meshed/results-lopf/meta.json": {
|
| 631 |
+
"size": 3
|
| 632 |
+
},
|
| 633 |
+
"test/data/benchmark-sp/crs.json": {
|
| 634 |
+
"size": 921
|
| 635 |
+
},
|
| 636 |
+
"test/data/benchmark-sp/meta.json": {
|
| 637 |
+
"size": 3
|
| 638 |
+
},
|
| 639 |
+
"test/test_bugs.py": {
|
| 640 |
+
"size": 7722
|
| 641 |
+
},
|
| 642 |
+
"test/test_collection.py": {
|
| 643 |
+
"size": 14965
|
| 644 |
+
},
|
| 645 |
+
"test/test_collection_statistics.py": {
|
| 646 |
+
"size": 18943
|
| 647 |
+
},
|
| 648 |
+
"test/test_common.py": {
|
| 649 |
+
"size": 14154
|
| 650 |
+
},
|
| 651 |
+
"test/test_common_deprecations.py": {
|
| 652 |
+
"size": 6725
|
| 653 |
+
},
|
| 654 |
+
"test/test_components.py": {
|
| 655 |
+
"size": 2717
|
| 656 |
+
},
|
| 657 |
+
"test/test_components_array.py": {
|
| 658 |
+
"size": 9287
|
| 659 |
+
},
|
| 660 |
+
"test/test_components_custom.py": {
|
| 661 |
+
"size": 1695
|
| 662 |
+
},
|
| 663 |
+
"test/test_components_store.py": {
|
| 664 |
+
"size": 398
|
| 665 |
+
},
|
| 666 |
+
"test/test_components_utils.py": {
|
| 667 |
+
"size": 460
|
| 668 |
+
},
|
| 669 |
+
"test/test_consistency_check.py": {
|
| 670 |
+
"size": 16082
|
| 671 |
+
},
|
| 672 |
+
"test/test_constants.py": {
|
| 673 |
+
"size": 5967
|
| 674 |
+
},
|
| 675 |
+
"test/test_deprecations.py": {
|
| 676 |
+
"size": 2726
|
| 677 |
+
},
|
| 678 |
+
"test/test_descriptors.py": {
|
| 679 |
+
"size": 5230
|
| 680 |
+
},
|
| 681 |
+
"test/test_docs.py": {
|
| 682 |
+
"size": 7727
|
| 683 |
+
},
|
| 684 |
+
"test/test_examples.py": {
|
| 685 |
+
"size": 1442
|
| 686 |
+
},
|
| 687 |
+
"test/test_graph.py": {
|
| 688 |
+
"size": 6678
|
| 689 |
+
},
|
| 690 |
+
"test/test_guards.py": {
|
| 691 |
+
"size": 835
|
| 692 |
+
},
|
| 693 |
+
"test/test_indices.py": {
|
| 694 |
+
"size": 2754
|
| 695 |
+
},
|
| 696 |
+
"test/test_io.py": {
|
| 697 |
+
"size": 24161
|
| 698 |
+
},
|
| 699 |
+
"test/test_io_cloudpathlib.py": {
|
| 700 |
+
"size": 3414
|
| 701 |
+
},
|
| 702 |
+
"test/test_link_post_discretization.py": {
|
| 703 |
+
"size": 4230
|
| 704 |
+
},
|
| 705 |
+
"test/test_lopf_ac_dc.py": {
|
| 706 |
+
"size": 820
|
| 707 |
+
},
|
| 708 |
+
"test/test_lopf_activity_mask.py": {
|
| 709 |
+
"size": 14953
|
| 710 |
+
},
|
| 711 |
+
"test/test_lopf_and_subsequent_power_flow.py": {
|
| 712 |
+
"size": 313
|
| 713 |
+
},
|
| 714 |
+
"test/test_lopf_basic_constraints.py": {
|
| 715 |
+
"size": 11940
|
| 716 |
+
},
|
| 717 |
+
"test/test_lopf_global_constraints.py": {
|
| 718 |
+
"size": 4076
|
| 719 |
+
},
|
| 720 |
+
"test/test_lopf_iteratively.py": {
|
| 721 |
+
"size": 1226
|
| 722 |
+
},
|
| 723 |
+
"test/test_lopf_losses.py": {
|
| 724 |
+
"size": 770
|
| 725 |
+
},
|
| 726 |
+
"test/test_lopf_mga.py": {
|
| 727 |
+
"size": 6265
|
| 728 |
+
},
|
| 729 |
+
"test/test_lopf_modularity.py": {
|
| 730 |
+
"size": 1157
|
| 731 |
+
},
|
| 732 |
+
"test/test_lopf_multiinvest.py": {
|
| 733 |
+
"size": 35983
|
| 734 |
+
},
|
| 735 |
+
"test/test_lopf_multilink.py": {
|
| 736 |
+
"size": 3960
|
| 737 |
+
},
|
| 738 |
+
"test/test_lopf_quadratic_costs.py": {
|
| 739 |
+
"size": 687
|
| 740 |
+
},
|
| 741 |
+
"test/test_lopf_rolling_horizon.py": {
|
| 742 |
+
"size": 2715
|
| 743 |
+
},
|
| 744 |
+
"test/test_lopf_storage.py": {
|
| 745 |
+
"size": 2821
|
| 746 |
+
},
|
| 747 |
+
"test/test_lopf_unit_commitment.py": {
|
| 748 |
+
"size": 16924
|
| 749 |
+
},
|
| 750 |
+
"test/test_lopf_varying_inputs.py": {
|
| 751 |
+
"size": 1628
|
| 752 |
+
},
|
| 753 |
+
"test/test_lpf_ac_dc.py": {
|
| 754 |
+
"size": 1556
|
| 755 |
+
},
|
| 756 |
+
"test/test_lpf_against_pypower.py": {
|
| 757 |
+
"size": 2670
|
| 758 |
+
},
|
| 759 |
+
"test/test_meshed_threshold.py": {
|
| 760 |
+
"size": 3880
|
| 761 |
+
},
|
| 762 |
+
"test/test_network.py": {
|
| 763 |
+
"size": 22314
|
| 764 |
+
},
|
| 765 |
+
"test/test_network_cycles.py": {
|
| 766 |
+
"size": 12678
|
| 767 |
+
},
|
| 768 |
+
"test/test_network_index.py": {
|
| 769 |
+
"size": 14289
|
| 770 |
+
},
|
| 771 |
+
"test/test_network_transform.py": {
|
| 772 |
+
"size": 8491
|
| 773 |
+
},
|
| 774 |
+
"test/test_optimization_expressions.py": {
|
| 775 |
+
"size": 5421
|
| 776 |
+
},
|
| 777 |
+
"test/test_optional_dependencies.py": {
|
| 778 |
+
"size": 2196
|
| 779 |
+
},
|
| 780 |
+
"test/test_options.py": {
|
| 781 |
+
"size": 9946
|
| 782 |
+
},
|
| 783 |
+
"test/test_pf_activity_mask.py": {
|
| 784 |
+
"size": 1039
|
| 785 |
+
},
|
| 786 |
+
"test/test_pf_against_pandapower.py": {
|
| 787 |
+
"size": 2358
|
| 788 |
+
},
|
| 789 |
+
"test/test_pf_against_pypower.py": {
|
| 790 |
+
"size": 3229
|
| 791 |
+
},
|
| 792 |
+
"test/test_pf_distributed_slack.py": {
|
| 793 |
+
"size": 2579
|
| 794 |
+
},
|
| 795 |
+
"test/test_plot_maps_common.py": {
|
| 796 |
+
"size": 20887
|
| 797 |
+
},
|
| 798 |
+
"test/test_plot_maps_interactive.py": {
|
| 799 |
+
"size": 5380
|
| 800 |
+
},
|
| 801 |
+
"test/test_plot_maps_static.py": {
|
| 802 |
+
"size": 9255
|
| 803 |
+
},
|
| 804 |
+
"test/test_riskaversion.py": {
|
| 805 |
+
"size": 11021
|
| 806 |
+
},
|
| 807 |
+
"test/test_sclopf_scigrid.py": {
|
| 808 |
+
"size": 3089
|
| 809 |
+
},
|
| 810 |
+
"test/test_snapshot_weightings.py": {
|
| 811 |
+
"size": 1375
|
| 812 |
+
},
|
| 813 |
+
"test/test_spatial_clustering.py": {
|
| 814 |
+
"size": 7552
|
| 815 |
+
},
|
| 816 |
+
"test/test_stand_by_cost.py": {
|
| 817 |
+
"size": 1397
|
| 818 |
+
},
|
| 819 |
+
"test/test_statistics.py": {
|
| 820 |
+
"size": 9835
|
| 821 |
+
},
|
| 822 |
+
"test/test_statistics_plot.py": {
|
| 823 |
+
"size": 8051
|
| 824 |
+
},
|
| 825 |
+
"test/test_statistics_plot_interactive.py": {
|
| 826 |
+
"size": 10662
|
| 827 |
+
},
|
| 828 |
+
"test/test_statistics_plot_schema.py": {
|
| 829 |
+
"size": 1152
|
| 830 |
+
},
|
| 831 |
+
"test/test_stochastic.py": {
|
| 832 |
+
"size": 56214
|
| 833 |
+
},
|
| 834 |
+
"test/test_stochastic_not_implemented.py": {
|
| 835 |
+
"size": 1835
|
| 836 |
+
},
|
| 837 |
+
"test/test_subnetwork.py": {
|
| 838 |
+
"size": 2908
|
| 839 |
+
},
|
| 840 |
+
"test/test_version.py": {
|
| 841 |
+
"size": 1433
|
| 842 |
+
},
|
| 843 |
+
"test/test_warnings_cyclic_storage.py": {
|
| 844 |
+
"size": 7694
|
| 845 |
+
}
|
| 846 |
+
},
|
| 847 |
+
"processed_by": "zip_fallback",
|
| 848 |
+
"success": true
|
| 849 |
+
},
|
| 850 |
+
"structure": {
|
| 851 |
+
"packages": [
|
| 852 |
+
"source.pypsa",
|
| 853 |
+
"source.pypsa.clustering",
|
| 854 |
+
"source.pypsa.components",
|
| 855 |
+
"source.pypsa.network",
|
| 856 |
+
"source.pypsa.optimization",
|
| 857 |
+
"source.pypsa.plot",
|
| 858 |
+
"source.pypsa.statistics"
|
| 859 |
+
]
|
| 860 |
+
},
|
| 861 |
+
"dependencies": {
|
| 862 |
+
"has_environment_yml": false,
|
| 863 |
+
"has_requirements_txt": false,
|
| 864 |
+
"pyproject": true,
|
| 865 |
+
"setup_cfg": false,
|
| 866 |
+
"setup_py": false
|
| 867 |
+
},
|
| 868 |
+
"entry_points": {
|
| 869 |
+
"imports": [],
|
| 870 |
+
"cli": [],
|
| 871 |
+
"modules": []
|
| 872 |
+
},
|
| 873 |
+
"llm_analysis": {
|
| 874 |
+
"core_modules": [
|
| 875 |
+
{
|
| 876 |
+
"package": "source.pypsa",
|
| 877 |
+
"module": "__init__",
|
| 878 |
+
"functions": [],
|
| 879 |
+
"classes": [],
|
| 880 |
+
"description": "Initialization module for the PyPSA package."
|
| 881 |
+
},
|
| 882 |
+
{
|
| 883 |
+
"package": "source.pypsa.clustering",
|
| 884 |
+
"module": "spatial",
|
| 885 |
+
"functions": [
|
| 886 |
+
"cluster_spatial"
|
| 887 |
+
],
|
| 888 |
+
"classes": [],
|
| 889 |
+
"description": "Functions for spatial clustering of network components."
|
| 890 |
+
},
|
| 891 |
+
{
|
| 892 |
+
"package": "source.pypsa.components",
|
| 893 |
+
"module": "components",
|
| 894 |
+
"functions": [
|
| 895 |
+
"add_component",
|
| 896 |
+
"remove_component"
|
| 897 |
+
],
|
| 898 |
+
"classes": [
|
| 899 |
+
"Component"
|
| 900 |
+
],
|
| 901 |
+
"description": "Handles the addition and removal of components in the network."
|
| 902 |
+
},
|
| 903 |
+
{
|
| 904 |
+
"package": "source.pypsa.network",
|
| 905 |
+
"module": "io",
|
| 906 |
+
"functions": [
|
| 907 |
+
"import_network",
|
| 908 |
+
"export_network"
|
| 909 |
+
],
|
| 910 |
+
"classes": [],
|
| 911 |
+
"description": "Functions for importing and exporting network data."
|
| 912 |
+
},
|
| 913 |
+
{
|
| 914 |
+
"package": "source.pypsa.optimization",
|
| 915 |
+
"module": "optimize",
|
| 916 |
+
"functions": [
|
| 917 |
+
"optimize_network"
|
| 918 |
+
],
|
| 919 |
+
"classes": [],
|
| 920 |
+
"description": "Optimization routines for network operation and planning."
|
| 921 |
+
},
|
| 922 |
+
{
|
| 923 |
+
"package": "source.pypsa.plot",
|
| 924 |
+
"module": "maps",
|
| 925 |
+
"functions": [
|
| 926 |
+
"plot_static_map",
|
| 927 |
+
"plot_interactive_map"
|
| 928 |
+
],
|
| 929 |
+
"classes": [],
|
| 930 |
+
"description": "Plotting functions for static and interactive maps."
|
| 931 |
+
},
|
| 932 |
+
{
|
| 933 |
+
"package": "source.pypsa.statistics",
|
| 934 |
+
"module": "expressions",
|
| 935 |
+
"functions": [
|
| 936 |
+
"calculate_statistics"
|
| 937 |
+
],
|
| 938 |
+
"classes": [],
|
| 939 |
+
"description": "Functions for calculating various network statistics."
|
| 940 |
+
}
|
| 941 |
+
],
|
| 942 |
+
"cli_commands": [],
|
| 943 |
+
"import_strategy": {
|
| 944 |
+
"primary": "import",
|
| 945 |
+
"fallback": "blackbox",
|
| 946 |
+
"confidence": 0.85
|
| 947 |
+
},
|
| 948 |
+
"dependencies": {
|
| 949 |
+
"required": [
|
| 950 |
+
"numpy",
|
| 951 |
+
"pandas",
|
| 952 |
+
"matplotlib"
|
| 953 |
+
],
|
| 954 |
+
"optional": [
|
| 955 |
+
"geopandas",
|
| 956 |
+
"plotly"
|
| 957 |
+
]
|
| 958 |
+
},
|
| 959 |
+
"risk_assessment": {
|
| 960 |
+
"import_feasibility": 0.8,
|
| 961 |
+
"intrusiveness_risk": "medium",
|
| 962 |
+
"complexity": "medium"
|
| 963 |
+
}
|
| 964 |
+
},
|
| 965 |
+
"deepwiki_analysis": {
|
| 966 |
+
"repo_url": "https://github.com/PyPSA/PyPSA",
|
| 967 |
+
"repo_name": "PyPSA",
|
| 968 |
+
"content": null,
|
| 969 |
+
"model": "gpt-4o",
|
| 970 |
+
"source": "selenium",
|
| 971 |
+
"success": true
|
| 972 |
+
},
|
| 973 |
+
"deepwiki_options": {
|
| 974 |
+
"enabled": true,
|
| 975 |
+
"model": "gpt-4o"
|
| 976 |
+
},
|
| 977 |
+
"risk": {
|
| 978 |
+
"import_feasibility": 0.8,
|
| 979 |
+
"intrusiveness_risk": "medium",
|
| 980 |
+
"complexity": "medium"
|
| 981 |
+
}
|
| 982 |
+
}
|
PyPSA/mcp_output/env_info.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"environment": {
|
| 3 |
+
"type": "conda",
|
| 4 |
+
"name": "PyPSA_558543_env",
|
| 5 |
+
"files": {},
|
| 6 |
+
"python": "3.10",
|
| 7 |
+
"exec_prefix": []
|
| 8 |
+
},
|
| 9 |
+
"original_tests": {
|
| 10 |
+
"passed": false,
|
| 11 |
+
"report_path": null
|
| 12 |
+
},
|
| 13 |
+
"timestamp": 1763558620.0246599,
|
| 14 |
+
"conda_available": true
|
| 15 |
+
}
|
PyPSA/mcp_output/mcp_logs/llm_statistics.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"total_calls": 5,
|
| 3 |
+
"failed_calls": 0,
|
| 4 |
+
"retry_count": 0,
|
| 5 |
+
"total_prompt_tokens": 27816,
|
| 6 |
+
"total_completion_tokens": 4358,
|
| 7 |
+
"total_tokens": 32174,
|
| 8 |
+
"average_prompt_tokens": 5563.2,
|
| 9 |
+
"average_completion_tokens": 871.6,
|
| 10 |
+
"average_tokens": 6434.8
|
| 11 |
+
}
|
PyPSA/mcp_output/mcp_logs/run_log.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"timestamp": 1763558886.5027742,
|
| 3 |
+
"node": "RunNode",
|
| 4 |
+
"test_result": {
|
| 5 |
+
"passed": false,
|
| 6 |
+
"report_path": null,
|
| 7 |
+
"stdout": "",
|
| 8 |
+
"stderr": "onda.cli.main_run:execute(41): `conda run python mcp_output/start_mcp.py` failed. (See above for error)\nTraceback (most recent call last):\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/start_mcp.py\", line 17, in <module>\n from mcp_service import create_app\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/mcp_plugin/mcp_service.py\", line 8, in <module>\n from pypsa import Network, SubNetwork, clustering, common, components, descriptors, examples, geo, optimization, plot, statistics\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/source/pypsa/__init__.py\", line 21, in <module>\n from pypsa import (\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/source/pypsa/clustering/__init__.py\", line 10, in <module>\n import pandas as pd\nModuleNotFoundError: No module named 'pandas'\n\n"
|
| 9 |
+
},
|
| 10 |
+
"run_result": {
|
| 11 |
+
"success": false,
|
| 12 |
+
"test_passed": false,
|
| 13 |
+
"exit_code": 1,
|
| 14 |
+
"stdout": "",
|
| 15 |
+
"stderr": "onda.cli.main_run:execute(41): `conda run python mcp_output/start_mcp.py` failed. (See above for error)\nTraceback (most recent call last):\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/start_mcp.py\", line 17, in <module>\n from mcp_service import create_app\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/mcp_plugin/mcp_service.py\", line 8, in <module>\n from pypsa import Network, SubNetwork, clustering, common, components, descriptors, examples, geo, optimization, plot, statistics\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/source/pypsa/__init__.py\", line 21, in <module>\n from pypsa import (\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/source/pypsa/clustering/__init__.py\", line 10, in <module>\n import pandas as pd\nModuleNotFoundError: No module named 'pandas'\n\n",
|
| 16 |
+
"timestamp": 1763558886.5027297,
|
| 17 |
+
"error_type": "ImportError",
|
| 18 |
+
"error": "Module import failed: ERROR conda.cli.main_run:execute(41): `conda run python mcp_output/start_mcp.py` failed. (See above for error)\nTraceback (most recent call last):\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/start_mcp.py\", line 17, in <module>\n from mcp_service import create_app\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/mcp_plugin/mcp_service.py\", line 8, in <module>\n from pypsa import Network, SubNetwork, clustering, common, components, descriptors, examples, geo, optimization, plot, statistics\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/source/pypsa/__init__.py\", line 21, in <module>\n from pypsa import (\n File \"/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/source/pypsa/clustering/__init__.py\", line 10, in <module>\n import pandas as pd\nModuleNotFoundError: No module named 'pandas'\n\n",
|
| 19 |
+
"details": {
|
| 20 |
+
"command": "/home/wshiah/code/miniconda3/bin/conda run -n PyPSA_558543_env --cwd /export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA python mcp_output/start_mcp.py",
|
| 21 |
+
"working_directory": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA",
|
| 22 |
+
"environment_type": "conda"
|
| 23 |
+
}
|
| 24 |
+
},
|
| 25 |
+
"environment": {
|
| 26 |
+
"type": "conda",
|
| 27 |
+
"name": "PyPSA_558543_env",
|
| 28 |
+
"files": {},
|
| 29 |
+
"python": "3.10",
|
| 30 |
+
"exec_prefix": []
|
| 31 |
+
},
|
| 32 |
+
"plugin_info": {
|
| 33 |
+
"files": {
|
| 34 |
+
"mcp_output/start_mcp.py": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/start_mcp.py",
|
| 35 |
+
"mcp_output/mcp_plugin/__init__.py": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/mcp_plugin/__init__.py",
|
| 36 |
+
"mcp_output/mcp_plugin/mcp_service.py": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/mcp_plugin/mcp_service.py",
|
| 37 |
+
"mcp_output/mcp_plugin/adapter.py": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/mcp_plugin/adapter.py",
|
| 38 |
+
"mcp_output/mcp_plugin/main.py": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/mcp_plugin/main.py",
|
| 39 |
+
"mcp_output/requirements.txt": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/requirements.txt",
|
| 40 |
+
"mcp_output/README_MCP.md": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/README_MCP.md",
|
| 41 |
+
"mcp_output/tests_mcp/test_mcp_basic.py": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/tests_mcp/test_mcp_basic.py"
|
| 42 |
+
},
|
| 43 |
+
"adapter_mode": "import",
|
| 44 |
+
"endpoints": [
|
| 45 |
+
"cluster_spatial",
|
| 46 |
+
"add_component",
|
| 47 |
+
"remove_component",
|
| 48 |
+
"component",
|
| 49 |
+
"import_network",
|
| 50 |
+
"export_network",
|
| 51 |
+
"optimize_network",
|
| 52 |
+
"plot_static_map",
|
| 53 |
+
"plot_interactive_map",
|
| 54 |
+
"calculate_statistics"
|
| 55 |
+
],
|
| 56 |
+
"mcp_dir": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/mcp_plugin",
|
| 57 |
+
"tests_dir": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/tests_mcp",
|
| 58 |
+
"main_entry": "start_mcp.py",
|
| 59 |
+
"readme_path": "/export/project/shiweijie/ghh/LLM_MCP_RAG/MCP-agent-github-repo-output/workspace/PyPSA/mcp_output/README_MCP.md",
|
| 60 |
+
"requirements": [
|
| 61 |
+
"fastmcp>=0.1.0",
|
| 62 |
+
"pydantic>=2.0.0"
|
| 63 |
+
]
|
| 64 |
+
},
|
| 65 |
+
"fastmcp_installed": false
|
| 66 |
+
}
|
PyPSA/mcp_output/mcp_plugin/__init__.py
ADDED
|
File without changes
|
PyPSA/mcp_output/mcp_plugin/__pycache__/adapter.cpython-310.pyc
ADDED
|
Binary file (4.16 kB). View file
|
|
|
PyPSA/mcp_output/mcp_plugin/__pycache__/mcp_service.cpython-310.pyc
ADDED
|
Binary file (5.98 kB). View file
|
|
|
PyPSA/mcp_output/mcp_plugin/adapter.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
|
| 4 |
+
# Path settings
|
| 5 |
+
source_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "source")
|
| 6 |
+
sys.path.insert(0, source_path)
|
| 7 |
+
|
| 8 |
+
# Import statements
|
| 9 |
+
try:
|
| 10 |
+
from pypsa import Network
|
| 11 |
+
from pypsa.clustering import spatial
|
| 12 |
+
from pypsa.optimization import optimize
|
| 13 |
+
from pypsa.plot import maps
|
| 14 |
+
from pypsa.statistics import expressions
|
| 15 |
+
except ImportError as e:
|
| 16 |
+
print(f"ImportError: {e}. Ensure the PyPSA package is correctly installed and accessible.")
|
| 17 |
+
# Fallback mode can be implemented here if necessary
|
| 18 |
+
|
| 19 |
+
# Adapter class definition
|
| 20 |
+
class Adapter:
|
| 21 |
+
"""
|
| 22 |
+
Adapter class for the MCP plugin, utilizing the PyPSA library.
|
| 23 |
+
Provides methods to interact with various components and functionalities of PyPSA.
|
| 24 |
+
"""
|
| 25 |
+
|
| 26 |
+
def __init__(self):
|
| 27 |
+
self.mode = "import"
|
| 28 |
+
|
| 29 |
+
# Network Module
|
| 30 |
+
# -------------------------------------------------------------------------
|
| 31 |
+
def create_network(self, *args, **kwargs):
|
| 32 |
+
"""
|
| 33 |
+
Create a new network instance.
|
| 34 |
+
|
| 35 |
+
Parameters:
|
| 36 |
+
- args: Positional arguments for Network initialization.
|
| 37 |
+
- kwargs: Keyword arguments for Network initialization.
|
| 38 |
+
|
| 39 |
+
Returns:
|
| 40 |
+
- dict: Status and network instance or error message.
|
| 41 |
+
"""
|
| 42 |
+
try:
|
| 43 |
+
network = Network(*args, **kwargs)
|
| 44 |
+
return {"status": "success", "network": network}
|
| 45 |
+
except Exception as e:
|
| 46 |
+
return {"status": "error", "message": f"Failed to create network: {e}"}
|
| 47 |
+
|
| 48 |
+
# Clustering Module
|
| 49 |
+
# -------------------------------------------------------------------------
|
| 50 |
+
def perform_spatial_clustering(self, network, *args, **kwargs):
|
| 51 |
+
"""
|
| 52 |
+
Perform spatial clustering on the given network.
|
| 53 |
+
|
| 54 |
+
Parameters:
|
| 55 |
+
- network: The network instance to cluster.
|
| 56 |
+
- args: Additional positional arguments for clustering.
|
| 57 |
+
- kwargs: Additional keyword arguments for clustering.
|
| 58 |
+
|
| 59 |
+
Returns:
|
| 60 |
+
- dict: Status and clustering result or error message.
|
| 61 |
+
"""
|
| 62 |
+
try:
|
| 63 |
+
result = spatial(network, *args, **kwargs)
|
| 64 |
+
return {"status": "success", "result": result}
|
| 65 |
+
except Exception as e:
|
| 66 |
+
return {"status": "error", "message": f"Failed to perform spatial clustering: {e}"}
|
| 67 |
+
|
| 68 |
+
# Optimization Module
|
| 69 |
+
# -------------------------------------------------------------------------
|
| 70 |
+
def optimize_network(self, network, *args, **kwargs):
|
| 71 |
+
"""
|
| 72 |
+
Optimize the given network.
|
| 73 |
+
|
| 74 |
+
Parameters:
|
| 75 |
+
- network: The network instance to optimize.
|
| 76 |
+
- args: Additional positional arguments for optimization.
|
| 77 |
+
- kwargs: Additional keyword arguments for optimization.
|
| 78 |
+
|
| 79 |
+
Returns:
|
| 80 |
+
- dict: Status and optimization result or error message.
|
| 81 |
+
"""
|
| 82 |
+
try:
|
| 83 |
+
result = optimize(network, *args, **kwargs)
|
| 84 |
+
return {"status": "success", "result": result}
|
| 85 |
+
except Exception as e:
|
| 86 |
+
return {"status": "error", "message": f"Failed to optimize network: {e}"}
|
| 87 |
+
|
| 88 |
+
# Plotting Module
|
| 89 |
+
# -------------------------------------------------------------------------
|
| 90 |
+
def plot_network_map(self, network, *args, **kwargs):
|
| 91 |
+
"""
|
| 92 |
+
Plot a map of the given network.
|
| 93 |
+
|
| 94 |
+
Parameters:
|
| 95 |
+
- network: The network instance to plot.
|
| 96 |
+
- args: Additional positional arguments for plotting.
|
| 97 |
+
- kwargs: Additional keyword arguments for plotting.
|
| 98 |
+
|
| 99 |
+
Returns:
|
| 100 |
+
- dict: Status and plot result or error message.
|
| 101 |
+
"""
|
| 102 |
+
try:
|
| 103 |
+
result = maps(network, *args, **kwargs)
|
| 104 |
+
return {"status": "success", "result": result}
|
| 105 |
+
except Exception as e:
|
| 106 |
+
return {"status": "error", "message": f"Failed to plot network map: {e}"}
|
| 107 |
+
|
| 108 |
+
# Statistics Module
|
| 109 |
+
# -------------------------------------------------------------------------
|
| 110 |
+
def calculate_expressions(self, network, *args, **kwargs):
|
| 111 |
+
"""
|
| 112 |
+
Calculate expressions for the given network.
|
| 113 |
+
|
| 114 |
+
Parameters:
|
| 115 |
+
- network: The network instance for which to calculate expressions.
|
| 116 |
+
- args: Additional positional arguments for calculation.
|
| 117 |
+
- kwargs: Additional keyword arguments for calculation.
|
| 118 |
+
|
| 119 |
+
Returns:
|
| 120 |
+
- dict: Status and calculation result or error message.
|
| 121 |
+
"""
|
| 122 |
+
try:
|
| 123 |
+
result = expressions(network, *args, **kwargs)
|
| 124 |
+
return {"status": "success", "result": result}
|
| 125 |
+
except Exception as e:
|
| 126 |
+
return {"status": "error", "message": f"Failed to calculate expressions: {e}"}
|
| 127 |
+
|
| 128 |
+
# End of Adapter class definition
|
| 129 |
+
# -------------------------------------------------------------------------
|
PyPSA/mcp_output/mcp_plugin/main.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
MCP Service Auto-Wrapper - Auto-generated
|
| 3 |
+
"""
|
| 4 |
+
from mcp_service import create_app
|
| 5 |
+
|
| 6 |
+
def main():
|
| 7 |
+
"""Main entry point"""
|
| 8 |
+
app = create_app()
|
| 9 |
+
return app
|
| 10 |
+
|
| 11 |
+
if __name__ == "__main__":
|
| 12 |
+
app = main()
|
| 13 |
+
app.run()
|
PyPSA/mcp_output/mcp_plugin/mcp_service.py
ADDED
|
@@ -0,0 +1,524 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
import json
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
|
| 6 |
+
source_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "source")
|
| 7 |
+
sys.path.insert(0, source_path)
|
| 8 |
+
|
| 9 |
+
from fastmcp import FastMCP
|
| 10 |
+
from pypsa import Network
|
| 11 |
+
from pypsa.statistics import StatisticsAccessor, get_operation, get_transmission_branches
|
| 12 |
+
import logging
|
| 13 |
+
|
| 14 |
+
# Set up logging
|
| 15 |
+
logging.basicConfig(level=logging.WARNING)
|
| 16 |
+
logger = logging.getLogger(__name__)
|
| 17 |
+
|
| 18 |
+
mcp = FastMCP("pypsa_service")
|
| 19 |
+
|
| 20 |
+
# ============================================================================
|
| 21 |
+
# NETWORK I/O TOOLS
|
| 22 |
+
# ============================================================================
|
| 23 |
+
|
| 24 |
+
@mcp.tool(
|
| 25 |
+
name="load_network",
|
| 26 |
+
description="Load a PyPSA network from a file (netCDF, HDF5, CSV folder, or URL)"
|
| 27 |
+
)
|
| 28 |
+
def tool_load_network(file_path: str) -> dict:
|
| 29 |
+
"""
|
| 30 |
+
Load a PyPSA network from a specified file path.
|
| 31 |
+
|
| 32 |
+
Supported formats:
|
| 33 |
+
- .nc (NetCDF)
|
| 34 |
+
- .h5 (HDF5)
|
| 35 |
+
- folder containing CSV files
|
| 36 |
+
- URL to remote network file
|
| 37 |
+
|
| 38 |
+
Parameters:
|
| 39 |
+
- file_path (str): Path to the network file or folder
|
| 40 |
+
|
| 41 |
+
Returns:
|
| 42 |
+
- dict: Network metadata and basic info
|
| 43 |
+
"""
|
| 44 |
+
try:
|
| 45 |
+
network = Network(file_path)
|
| 46 |
+
|
| 47 |
+
# Extract network metadata
|
| 48 |
+
result = {
|
| 49 |
+
"success": True,
|
| 50 |
+
"result": {
|
| 51 |
+
"network_name": network.name,
|
| 52 |
+
"pypsa_version": network._pypsa_version,
|
| 53 |
+
"snapshots_count": len(network.snapshots),
|
| 54 |
+
"buses_count": len(network.buses),
|
| 55 |
+
"generators_count": len(network.generators),
|
| 56 |
+
"loads_count": len(network.loads),
|
| 57 |
+
"storage_units_count": len(network.storage_units),
|
| 58 |
+
"stores_count": len(network.stores),
|
| 59 |
+
"lines_count": len(network.lines),
|
| 60 |
+
"links_count": len(network.links),
|
| 61 |
+
"transformers_count": len(network.transformers),
|
| 62 |
+
"sub_networks_count": len(network.sub_networks),
|
| 63 |
+
"objective_value": float(network.objective) if hasattr(network, 'objective') else None,
|
| 64 |
+
"carriers": list(network.carriers.index) if len(network.carriers) > 0 else [],
|
| 65 |
+
"crs": str(network.crs),
|
| 66 |
+
"file_path": str(file_path),
|
| 67 |
+
"description": f"Network with {len(network.buses)} buses, {len(network.generators)} generators, {len(network.loads)} loads"
|
| 68 |
+
},
|
| 69 |
+
"error": None
|
| 70 |
+
}
|
| 71 |
+
return result
|
| 72 |
+
except Exception as e:
|
| 73 |
+
return {"success": False, "result": None, "error": f"Failed to load network: {str(e)}"}
|
| 74 |
+
|
| 75 |
+
@mcp.tool(
|
| 76 |
+
name="save_network",
|
| 77 |
+
description="Save a PyPSA network to a file"
|
| 78 |
+
)
|
| 79 |
+
def tool_save_network(network_path: str, output_path: str, format: str = "netcdf") -> dict:
|
| 80 |
+
"""
|
| 81 |
+
Save a PyPSA network to a file in specified format.
|
| 82 |
+
|
| 83 |
+
Supported formats:
|
| 84 |
+
- netcdf (.nc)
|
| 85 |
+
- hdf5 (.h5)
|
| 86 |
+
- csv (folder)
|
| 87 |
+
|
| 88 |
+
Parameters:
|
| 89 |
+
- network_path (str): Path to load the network from
|
| 90 |
+
- output_path (str): Path to save the network to
|
| 91 |
+
- format (str): Output format (netcdf, hdf5, or csv)
|
| 92 |
+
|
| 93 |
+
Returns:
|
| 94 |
+
- dict: Save status and result information
|
| 95 |
+
"""
|
| 96 |
+
try:
|
| 97 |
+
network = Network(network_path)
|
| 98 |
+
|
| 99 |
+
if format.lower() in ["netcdf", "nc"]:
|
| 100 |
+
network.export_to_netcdf(output_path)
|
| 101 |
+
format_used = "NetCDF (.nc)"
|
| 102 |
+
elif format.lower() in ["hdf5", "h5"]:
|
| 103 |
+
network.export_to_hdf5(output_path)
|
| 104 |
+
format_used = "HDF5 (.h5)"
|
| 105 |
+
elif format.lower() == "csv":
|
| 106 |
+
network.export_to_csv_folder(output_path)
|
| 107 |
+
format_used = "CSV (folder)"
|
| 108 |
+
else:
|
| 109 |
+
raise ValueError(f"Unsupported format: {format}")
|
| 110 |
+
|
| 111 |
+
return {
|
| 112 |
+
"success": True,
|
| 113 |
+
"result": {
|
| 114 |
+
"output_path": str(output_path),
|
| 115 |
+
"format": format_used,
|
| 116 |
+
"description": f"Network saved successfully as {format_used}"
|
| 117 |
+
},
|
| 118 |
+
"error": None
|
| 119 |
+
}
|
| 120 |
+
except Exception as e:
|
| 121 |
+
return {"success": False, "result": None, "error": f"Failed to save network: {str(e)}"}
|
| 122 |
+
|
| 123 |
+
# ============================================================================
|
| 124 |
+
# NETWORK ANALYSIS TOOLS
|
| 125 |
+
# ============================================================================
|
| 126 |
+
|
| 127 |
+
@mcp.tool(
|
| 128 |
+
name="get_network_statistics",
|
| 129 |
+
description="Calculate detailed statistics for the network"
|
| 130 |
+
)
|
| 131 |
+
def tool_get_network_statistics(file_path: str) -> dict:
|
| 132 |
+
"""
|
| 133 |
+
Calculate comprehensive statistics for the network.
|
| 134 |
+
|
| 135 |
+
Includes:
|
| 136 |
+
- Component counts and attributes
|
| 137 |
+
- Capacity information
|
| 138 |
+
- Operating data
|
| 139 |
+
- Energy flows
|
| 140 |
+
- Network topology stats
|
| 141 |
+
|
| 142 |
+
Parameters:
|
| 143 |
+
- file_path (str): Path to the network file
|
| 144 |
+
|
| 145 |
+
Returns:
|
| 146 |
+
- dict: Detailed network statistics
|
| 147 |
+
"""
|
| 148 |
+
try:
|
| 149 |
+
network = Network(file_path)
|
| 150 |
+
|
| 151 |
+
# Calculate basic statistics
|
| 152 |
+
stats = {
|
| 153 |
+
"success": True,
|
| 154 |
+
"result": {
|
| 155 |
+
"network_overview": {
|
| 156 |
+
"name": network.name,
|
| 157 |
+
"snapshots_count": len(network.snapshots),
|
| 158 |
+
"time_period": f"{network.snapshots[0]} to {network.snapshots[-1]}" if len(network.snapshots) > 0 else "N/A"
|
| 159 |
+
},
|
| 160 |
+
"components": {
|
| 161 |
+
"buses": len(network.buses),
|
| 162 |
+
"generators": len(network.generators),
|
| 163 |
+
"storage_units": len(network.storage_units),
|
| 164 |
+
"stores": len(network.stores),
|
| 165 |
+
"loads": len(network.loads),
|
| 166 |
+
"lines": len(network.lines),
|
| 167 |
+
"links": len(network.links),
|
| 168 |
+
"transformers": len(network.transformers),
|
| 169 |
+
"sub_networks": len(network.sub_networks)
|
| 170 |
+
},
|
| 171 |
+
"capacity_stats": {
|
| 172 |
+
"total_generator_capacity_mw": round(network.generators.p_nom.sum(), 2) if len(network.generators) > 0 else 0,
|
| 173 |
+
"total_storage_capacity_mwh": round(network.storage_units.e_nom.sum(), 2) if len(network.storage_units) > 0 else 0,
|
| 174 |
+
"total_store_capacity_mwh": round(network.stores.e_nom.sum(), 2) if len(network.stores) > 0 else 0,
|
| 175 |
+
"total_load_mw": round(network.loads.p_set.sum(), 2) if len(network.loads) > 0 else 0
|
| 176 |
+
},
|
| 177 |
+
"carrier_info": {
|
| 178 |
+
"unique_carriers": list(network.carriers.index) if len(network.carriers) > 0 else [],
|
| 179 |
+
"carrier_count": len(network.carriers)
|
| 180 |
+
},
|
| 181 |
+
"transmission_info": {
|
| 182 |
+
"total_line_capacity_mva": round(network.lines.s_nom.sum(), 2) if len(network.lines) > 0 else 0,
|
| 183 |
+
"total_link_count": len(network.links),
|
| 184 |
+
"total_line_count": len(network.lines)
|
| 185 |
+
},
|
| 186 |
+
"objective_value": float(network.objective) if hasattr(network, 'objective') else None
|
| 187 |
+
},
|
| 188 |
+
"error": None
|
| 189 |
+
}
|
| 190 |
+
return stats
|
| 191 |
+
except Exception as e:
|
| 192 |
+
return {"success": False, "result": None, "error": f"Failed to get statistics: {str(e)}"}
|
| 193 |
+
|
| 194 |
+
@mcp.tool(
|
| 195 |
+
name="optimize_network",
|
| 196 |
+
description="Run network optimization with linear optimal power flow (LOPF)"
|
| 197 |
+
)
|
| 198 |
+
def tool_optimize_network(
|
| 199 |
+
file_path: str,
|
| 200 |
+
snapshots: str = "all",
|
| 201 |
+
linearized_unit_commitment: bool = False,
|
| 202 |
+
multi_invest: bool = False,
|
| 203 |
+
solver: str = "glpk"
|
| 204 |
+
) -> dict:
|
| 205 |
+
"""
|
| 206 |
+
Run linear optimal power flow (LOPF) optimization on the network.
|
| 207 |
+
|
| 208 |
+
Parameters:
|
| 209 |
+
- file_path (str): Path to the network file
|
| 210 |
+
- snapshots (str): "all" or comma-separated snapshot indices
|
| 211 |
+
- linearized_unit_commitment (bool): Enable linearized unit commitment
|
| 212 |
+
- multi_invest (bool): Enable multi-period investment optimization
|
| 213 |
+
- solver (str): Solver to use (glpk, cbc, cplex, gurobi, scip, etc.)
|
| 214 |
+
|
| 215 |
+
Returns:
|
| 216 |
+
- dict: Optimization results with objective value and status
|
| 217 |
+
"""
|
| 218 |
+
try:
|
| 219 |
+
network = Network(file_path)
|
| 220 |
+
|
| 221 |
+
# Set optimization options
|
| 222 |
+
if linearized_unit_commitment:
|
| 223 |
+
network._linearized_uc = 1
|
| 224 |
+
if multi_invest:
|
| 225 |
+
network._multi_invest = 1
|
| 226 |
+
|
| 227 |
+
# Run optimization
|
| 228 |
+
status, termination_condition = network.optimize(
|
| 229 |
+
solver_name=solver,
|
| 230 |
+
multi_investment_periods=multi_invest
|
| 231 |
+
)
|
| 232 |
+
|
| 233 |
+
result = {
|
| 234 |
+
"success": True,
|
| 235 |
+
"result": {
|
| 236 |
+
"status": status,
|
| 237 |
+
"termination_condition": termination_condition,
|
| 238 |
+
"objective_value": round(float(network.objective), 2),
|
| 239 |
+
"optimization_info": {
|
| 240 |
+
"snapshots_optimized": len(network.snapshots),
|
| 241 |
+
"linearzed_unit_commitment": linearized_unit_commitment,
|
| 242 |
+
"multi_period_investment": multi_invest,
|
| 243 |
+
"solver_used": solver
|
| 244 |
+
},
|
| 245 |
+
"description": f"Optimization completed with status: {status}, objective value: {network.objective:.2f}"
|
| 246 |
+
},
|
| 247 |
+
"error": None
|
| 248 |
+
}
|
| 249 |
+
return result
|
| 250 |
+
except Exception as e:
|
| 251 |
+
return {"success": False, "result": None, "error": f"Optimization failed: {str(e)}"}
|
| 252 |
+
|
| 253 |
+
# ============================================================================
|
| 254 |
+
# NETWORK COMPONENTS ANALYSIS TOOLS
|
| 255 |
+
# ============================================================================
|
| 256 |
+
|
| 257 |
+
@mcp.tool(
|
| 258 |
+
name="get_buses_info",
|
| 259 |
+
description="Get information about all buses in the network"
|
| 260 |
+
)
|
| 261 |
+
def tool_get_buses_info(file_path: str) -> dict:
|
| 262 |
+
"""
|
| 263 |
+
Get detailed information about buses in the network.
|
| 264 |
+
|
| 265 |
+
Returns:
|
| 266 |
+
- Bus counts by carrier
|
| 267 |
+
- Bus locations (if available)
|
| 268 |
+
- Control types
|
| 269 |
+
- Voltage levels
|
| 270 |
+
|
| 271 |
+
Parameters:
|
| 272 |
+
- file_path (str): Path to the network file
|
| 273 |
+
|
| 274 |
+
Returns:
|
| 275 |
+
- dict: Detailed bus information
|
| 276 |
+
"""
|
| 277 |
+
try:
|
| 278 |
+
network = Network(file_path)
|
| 279 |
+
|
| 280 |
+
buses_info = {
|
| 281 |
+
"success": True,
|
| 282 |
+
"result": {
|
| 283 |
+
"total_buses": len(network.buses),
|
| 284 |
+
"buses_by_carrier": dict(network.buses.carrier.value_counts()) if len(network.buses) > 0 else {},
|
| 285 |
+
"buses_with_generation": len(network.buses[network.buses.index.isin(network.generators.bus)]) if len(network.generators) > 0 else 0,
|
| 286 |
+
"buses_with_load": len(network.buses[network.buses.index.isin(network.loads.bus)]) if len(network.loads) > 0 else 0,
|
| 287 |
+
"buses_with_storage": len(network.buses[network.buses.index.isin(network.storage_units.bus)]) if len(network.storage_units) > 0 else 0,
|
| 288 |
+
"buses_list": list(network.buses.index[:20]), # First 20 buses
|
| 289 |
+
"description": f"Network contains {len(network.buses)} buses"
|
| 290 |
+
},
|
| 291 |
+
"error": None
|
| 292 |
+
}
|
| 293 |
+
return buses_info
|
| 294 |
+
except Exception as e:
|
| 295 |
+
return {"success": False, "result": None, "error": f"Failed to get buses info: {str(e)}"}
|
| 296 |
+
|
| 297 |
+
@mcp.tool(
|
| 298 |
+
name="get_generators_info",
|
| 299 |
+
description="Get information about all generators in the network"
|
| 300 |
+
)
|
| 301 |
+
def tool_get_generators_info(file_path: str) -> dict:
|
| 302 |
+
"""
|
| 303 |
+
Get detailed information about generators.
|
| 304 |
+
|
| 305 |
+
Returns:
|
| 306 |
+
- Generator counts by carrier
|
| 307 |
+
- Total installed capacity
|
| 308 |
+
- Generator efficiency
|
| 309 |
+
- Marginal costs
|
| 310 |
+
|
| 311 |
+
Parameters:
|
| 312 |
+
- file_path (str): Path to the network file
|
| 313 |
+
|
| 314 |
+
Returns:
|
| 315 |
+
- dict: Detailed generator information
|
| 316 |
+
"""
|
| 317 |
+
try:
|
| 318 |
+
network = Network(file_path)
|
| 319 |
+
|
| 320 |
+
if len(network.generators) == 0:
|
| 321 |
+
return {
|
| 322 |
+
"success": True,
|
| 323 |
+
"result": {
|
| 324 |
+
"total_generators": 0,
|
| 325 |
+
"description": "No generators in network"
|
| 326 |
+
},
|
| 327 |
+
"error": None
|
| 328 |
+
}
|
| 329 |
+
|
| 330 |
+
generators_info = {
|
| 331 |
+
"success": True,
|
| 332 |
+
"result": {
|
| 333 |
+
"total_generators": len(network.generators),
|
| 334 |
+
"generators_by_carrier": dict(network.generators.carrier.value_counts()),
|
| 335 |
+
"total_capacity_mw": round(network.generators.p_nom.sum(), 2),
|
| 336 |
+
"average_efficiency": round(network.generators.efficiency.mean(), 4),
|
| 337 |
+
"marginal_cost_range": {
|
| 338 |
+
"min": round(network.generators.marginal_cost.min(), 2),
|
| 339 |
+
"max": round(network.generators.marginal_cost.max(), 2),
|
| 340 |
+
"mean": round(network.generators.marginal_cost.mean(), 2)
|
| 341 |
+
},
|
| 342 |
+
"generators_by_bus": dict(network.generators.bus.value_counts().head(10)),
|
| 343 |
+
"description": f"Network contains {len(network.generators)} generators with total capacity {network.generators.p_nom.sum():.2f} MW"
|
| 344 |
+
},
|
| 345 |
+
"error": None
|
| 346 |
+
}
|
| 347 |
+
return generators_info
|
| 348 |
+
except Exception as e:
|
| 349 |
+
return {"success": False, "result": None, "error": f"Failed to get generators info: {str(e)}"}
|
| 350 |
+
|
| 351 |
+
@mcp.tool(
|
| 352 |
+
name="get_transmission_info",
|
| 353 |
+
description="Get information about transmission branches (lines and links)"
|
| 354 |
+
)
|
| 355 |
+
def tool_get_transmission_info(file_path: str) -> dict:
|
| 356 |
+
"""
|
| 357 |
+
Get detailed information about transmission branches.
|
| 358 |
+
|
| 359 |
+
Returns:
|
| 360 |
+
- Line and link counts
|
| 361 |
+
- Total transmission capacity
|
| 362 |
+
- Voltage levels
|
| 363 |
+
- Transmission losses
|
| 364 |
+
|
| 365 |
+
Parameters:
|
| 366 |
+
- file_path (str): Path to the network file
|
| 367 |
+
|
| 368 |
+
Returns:
|
| 369 |
+
- dict: Detailed transmission information
|
| 370 |
+
"""
|
| 371 |
+
try:
|
| 372 |
+
network = Network(file_path)
|
| 373 |
+
|
| 374 |
+
transmission_info = {
|
| 375 |
+
"success": True,
|
| 376 |
+
"result": {
|
| 377 |
+
"transmission_components": {
|
| 378 |
+
"total_lines": len(network.lines),
|
| 379 |
+
"total_links": len(network.links),
|
| 380 |
+
"total_transformers": len(network.transformers)
|
| 381 |
+
},
|
| 382 |
+
"transmission_capacity": {
|
| 383 |
+
"total_line_capacity_mva": round(network.lines.s_nom.sum(), 2) if len(network.lines) > 0 else 0,
|
| 384 |
+
"total_link_capacity_mw": round(network.links.p_nom.sum(), 2) if len(network.links) > 0 else 0,
|
| 385 |
+
"average_line_capacity_mva": round(network.lines.s_nom.mean(), 2) if len(network.lines) > 0 else 0
|
| 386 |
+
},
|
| 387 |
+
"transmission_losses": {
|
| 388 |
+
"ac_line_losses": round(network.lines.x.sum(), 4) if len(network.lines) > 0 else 0,
|
| 389 |
+
"transformer_losses": round(network.transformers.x.sum(), 4) if len(network.transformers) > 0 else 0
|
| 390 |
+
},
|
| 391 |
+
"description": f"Network has {len(network.lines)} transmission lines and {len(network.links)} links"
|
| 392 |
+
},
|
| 393 |
+
"error": None
|
| 394 |
+
}
|
| 395 |
+
return transmission_info
|
| 396 |
+
except Exception as e:
|
| 397 |
+
return {"success": False, "result": None, "error": f"Failed to get transmission info: {str(e)}"}
|
| 398 |
+
|
| 399 |
+
# ============================================================================
|
| 400 |
+
# NETWORK CLUSTERING/AGGREGATION TOOLS
|
| 401 |
+
# ============================================================================
|
| 402 |
+
|
| 403 |
+
@mcp.tool(
|
| 404 |
+
name="cluster_network_by_kmeans",
|
| 405 |
+
description="Cluster network buses using k-means algorithm"
|
| 406 |
+
)
|
| 407 |
+
def tool_cluster_network_by_kmeans(file_path: str, clusters_count: int = 5) -> dict:
|
| 408 |
+
"""
|
| 409 |
+
Cluster network buses using k-means algorithm for network reduction.
|
| 410 |
+
|
| 411 |
+
Parameters:
|
| 412 |
+
- file_path (str): Path to the network file
|
| 413 |
+
- clusters_count (int): Number of clusters to create
|
| 414 |
+
|
| 415 |
+
Returns:
|
| 416 |
+
- dict: Clustering results and mapping
|
| 417 |
+
"""
|
| 418 |
+
try:
|
| 419 |
+
network = Network(file_path)
|
| 420 |
+
|
| 421 |
+
# Use PyPSA's clustering accessor
|
| 422 |
+
busmap = network.clustering.busmap_by_kmeans(clusters_count)
|
| 423 |
+
|
| 424 |
+
return {
|
| 425 |
+
"success": True,
|
| 426 |
+
"result": {
|
| 427 |
+
"original_buses_count": len(network.buses),
|
| 428 |
+
"target_clusters": clusters_count,
|
| 429 |
+
"created_clusters": len(busmap.unique()),
|
| 430 |
+
"clustering_method": "k-means",
|
| 431 |
+
"buses_per_cluster_avg": round(len(network.buses) / clusters_count, 2),
|
| 432 |
+
"description": f"Network reduced from {len(network.buses)} buses to {len(busmap.unique())} clusters using k-means"
|
| 433 |
+
},
|
| 434 |
+
"error": None
|
| 435 |
+
}
|
| 436 |
+
except Exception as e:
|
| 437 |
+
return {"success": False, "result": None, "error": f"Clustering failed: {str(e)}"}
|
| 438 |
+
|
| 439 |
+
# ============================================================================
|
| 440 |
+
# NETWORK EXPORT TOOLS
|
| 441 |
+
# ============================================================================
|
| 442 |
+
|
| 443 |
+
@mcp.tool(
|
| 444 |
+
name="export_network_summary",
|
| 445 |
+
description="Export a detailed summary of the network to JSON"
|
| 446 |
+
)
|
| 447 |
+
def tool_export_network_summary(file_path: str, output_file: str = None) -> dict:
|
| 448 |
+
"""
|
| 449 |
+
Export a comprehensive network summary to JSON format.
|
| 450 |
+
|
| 451 |
+
Parameters:
|
| 452 |
+
- file_path (str): Path to the network file
|
| 453 |
+
- output_file (str): Optional path to save JSON summary (if None, returns inline)
|
| 454 |
+
|
| 455 |
+
Returns:
|
| 456 |
+
- dict: Network summary data
|
| 457 |
+
"""
|
| 458 |
+
try:
|
| 459 |
+
network = Network(file_path)
|
| 460 |
+
|
| 461 |
+
summary = {
|
| 462 |
+
"network_name": network.name,
|
| 463 |
+
"pypsa_version": network._pypsa_version,
|
| 464 |
+
"statistics": {
|
| 465 |
+
"snapshots": len(network.snapshots),
|
| 466 |
+
"buses": len(network.buses),
|
| 467 |
+
"generators": len(network.generators),
|
| 468 |
+
"loads": len(network.loads),
|
| 469 |
+
"storage_units": len(network.storage_units),
|
| 470 |
+
"stores": len(network.stores),
|
| 471 |
+
"lines": len(network.lines),
|
| 472 |
+
"links": len(network.links),
|
| 473 |
+
"transformers": len(network.transformers)
|
| 474 |
+
},
|
| 475 |
+
"capacity": {
|
| 476 |
+
"generator_capacity_mw": round(network.generators.p_nom.sum(), 2) if len(network.generators) > 0 else 0,
|
| 477 |
+
"storage_capacity_mwh": round(network.storage_units.e_nom.sum(), 2) if len(network.storage_units) > 0 else 0,
|
| 478 |
+
"transmission_capacity_mva": round(network.lines.s_nom.sum(), 2) if len(network.lines) > 0 else 0
|
| 479 |
+
},
|
| 480 |
+
"carriers": list(network.carriers.index) if len(network.carriers) > 0 else [],
|
| 481 |
+
"objective": float(network.objective) if hasattr(network, 'objective') else None
|
| 482 |
+
}
|
| 483 |
+
|
| 484 |
+
if output_file:
|
| 485 |
+
with open(output_file, 'w') as f:
|
| 486 |
+
json.dump(summary, f, indent=2)
|
| 487 |
+
return {
|
| 488 |
+
"success": True,
|
| 489 |
+
"result": {
|
| 490 |
+
"summary_saved": True,
|
| 491 |
+
"output_file": str(output_file),
|
| 492 |
+
"description": f"Network summary exported to {output_file}"
|
| 493 |
+
},
|
| 494 |
+
"error": None
|
| 495 |
+
}
|
| 496 |
+
else:
|
| 497 |
+
return {
|
| 498 |
+
"success": True,
|
| 499 |
+
"result": summary,
|
| 500 |
+
"error": None
|
| 501 |
+
}
|
| 502 |
+
except Exception as e:
|
| 503 |
+
return {"success": False, "result": None, "error": f"Export failed: {str(e)}"}
|
| 504 |
+
|
| 505 |
+
# ============================================================================
|
| 506 |
+
# APP CREATION
|
| 507 |
+
# ============================================================================
|
| 508 |
+
|
| 509 |
+
def create_app() -> FastMCP:
|
| 510 |
+
"""
|
| 511 |
+
Create and return the FastMCP application instance.
|
| 512 |
+
|
| 513 |
+
Features:
|
| 514 |
+
- Network loading and saving (NetCDF, HDF5, CSV)
|
| 515 |
+
- Optimization with LOPF
|
| 516 |
+
- Network statistics and analysis
|
| 517 |
+
- Component information extraction
|
| 518 |
+
- Network clustering and reduction
|
| 519 |
+
- Comprehensive export capabilities
|
| 520 |
+
|
| 521 |
+
Returns:
|
| 522 |
+
- FastMCP: The configured FastMCP instance with 10+ PyPSA tools.
|
| 523 |
+
"""
|
| 524 |
+
return mcp
|
PyPSA/mcp_output/requirements.txt
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastmcp>=0.1.0
|
| 2 |
+
pydantic>=2.0.0
|
| 3 |
+
numpy
|
| 4 |
+
pandas
|
| 5 |
+
matplotlib
|
| 6 |
+
|
| 7 |
+
# Optional Dependencies
|
| 8 |
+
# geopandas
|
| 9 |
+
# plotly
|
PyPSA/mcp_output/simple_revise_error_analysis.json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"status": "FAIL",
|
| 3 |
+
"next_action": "fix_directly",
|
| 4 |
+
"confidence": 0.9,
|
| 5 |
+
"summary": "The error is due to a missing Python module 'pandas', which is required by the 'pypsa.clustering' module. This can be fixed directly by installing the 'pandas' package in the conda environment being used. Run 'conda install pandas' to resolve the issue. Additionally, ensure that the conda environment is activated correctly before running the script."
|
| 6 |
+
}
|
PyPSA/mcp_output/start_mcp.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
MCP Service Startup Entry
|
| 3 |
+
"""
|
| 4 |
+
import sys
|
| 5 |
+
import os
|
| 6 |
+
|
| 7 |
+
project_root = os.path.dirname(os.path.abspath(__file__))
|
| 8 |
+
mcp_plugin_dir = os.path.join(project_root, "mcp_plugin")
|
| 9 |
+
if mcp_plugin_dir not in sys.path:
|
| 10 |
+
sys.path.insert(0, mcp_plugin_dir)
|
| 11 |
+
|
| 12 |
+
# Set path to source directory
|
| 13 |
+
source_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "source")
|
| 14 |
+
sys.path.insert(0, source_path)
|
| 15 |
+
|
| 16 |
+
from mcp_plugin.mcp_service import create_app
|
| 17 |
+
|
| 18 |
+
def main():
|
| 19 |
+
"""Start FastMCP service"""
|
| 20 |
+
app = create_app()
|
| 21 |
+
# Use environment variable to configure port, default 8000
|
| 22 |
+
port = int(os.environ.get("MCP_PORT", "8000"))
|
| 23 |
+
|
| 24 |
+
# Choose transport mode based on environment variable
|
| 25 |
+
transport = os.environ.get("MCP_TRANSPORT", "stdio")
|
| 26 |
+
if transport == "http":
|
| 27 |
+
app.run(transport="http", host="0.0.0.0", port=port)
|
| 28 |
+
else:
|
| 29 |
+
# Default to STDIO mode
|
| 30 |
+
app.run()
|
| 31 |
+
|
| 32 |
+
if __name__ == "__main__":
|
| 33 |
+
main()
|
PyPSA/mcp_output/tests_mcp/test_mcp_basic.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
MCP Service Basic Test
|
| 3 |
+
"""
|
| 4 |
+
import sys
|
| 5 |
+
import os
|
| 6 |
+
|
| 7 |
+
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 8 |
+
mcp_plugin_dir = os.path.join(project_root, "mcp_plugin")
|
| 9 |
+
if mcp_plugin_dir not in sys.path:
|
| 10 |
+
sys.path.insert(0, mcp_plugin_dir)
|
| 11 |
+
|
| 12 |
+
source_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "source")
|
| 13 |
+
sys.path.insert(0, source_path)
|
| 14 |
+
|
| 15 |
+
def test_import_mcp_service():
|
| 16 |
+
"""Test if MCP service can be imported normally"""
|
| 17 |
+
try:
|
| 18 |
+
from mcp_service import create_app
|
| 19 |
+
app = create_app()
|
| 20 |
+
assert app is not None
|
| 21 |
+
print("MCP service imported successfully")
|
| 22 |
+
return True
|
| 23 |
+
except Exception as e:
|
| 24 |
+
print("MCP service import failed: " + str(e))
|
| 25 |
+
return False
|
| 26 |
+
|
| 27 |
+
def test_adapter_init():
|
| 28 |
+
"""Test if adapter can be initialized normally"""
|
| 29 |
+
try:
|
| 30 |
+
from adapter import Adapter
|
| 31 |
+
adapter = Adapter()
|
| 32 |
+
assert adapter is not None
|
| 33 |
+
print("Adapter initialized successfully")
|
| 34 |
+
return True
|
| 35 |
+
except Exception as e:
|
| 36 |
+
print("Adapter initialization failed: " + str(e))
|
| 37 |
+
return False
|
| 38 |
+
|
| 39 |
+
if __name__ == "__main__":
|
| 40 |
+
print("Running MCP service basic test...")
|
| 41 |
+
test1 = test_import_mcp_service()
|
| 42 |
+
test2 = test_adapter_init()
|
| 43 |
+
|
| 44 |
+
if test1 and test2:
|
| 45 |
+
print("All basic tests passed")
|
| 46 |
+
sys.exit(0)
|
| 47 |
+
else:
|
| 48 |
+
print("Some tests failed")
|
| 49 |
+
sys.exit(1)
|
PyPSA/mcp_output/tests_smoke/test_smoke.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import importlib, sys
|
| 2 |
+
import os
|
| 3 |
+
|
| 4 |
+
# Add current directory to Python path
|
| 5 |
+
sys.path.insert(0, os.getcwd())
|
| 6 |
+
|
| 7 |
+
source_dir = os.path.join(os.getcwd(), "source")
|
| 8 |
+
if os.path.exists(source_dir):
|
| 9 |
+
sys.path.insert(0, source_dir)
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
try:
|
| 13 |
+
importlib.import_module("pypsa")
|
| 14 |
+
print("OK - Successfully imported pypsa")
|
| 15 |
+
except ImportError as e:
|
| 16 |
+
print(f"Failed to import pypsa: {e}")
|
| 17 |
+
fallback_packages = []
|
| 18 |
+
|
| 19 |
+
fallback_packages = ['pypsa']
|
| 20 |
+
|
| 21 |
+
for pkg in fallback_packages:
|
| 22 |
+
try:
|
| 23 |
+
importlib.import_module(pkg)
|
| 24 |
+
print(f"OK - Successfully imported {pkg}")
|
| 25 |
+
break
|
| 26 |
+
except ImportError:
|
| 27 |
+
continue
|
| 28 |
+
else:
|
| 29 |
+
print("All import attempts failed")
|
PyPSA/source/.codespell.ignore
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
ines
|
| 6 |
+
psace
|
| 7 |
+
datas
|
| 8 |
+
fom
|
| 9 |
+
esy
|
PyPSA/source/.git-blame-ignore-revs
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
# apply pre-commit setup to all files (including black)
|
| 6 |
+
57099450d1df78f9d3571f4515721aa04613d456
|
PyPSA/source/.github/ISSUE_TEMPLATE/bug_report.yaml
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
name: Bug Report
|
| 6 |
+
description: Create a report if something doesn't work quite right.
|
| 7 |
+
labels: ["needs triage"]
|
| 8 |
+
type: "Bug"
|
| 9 |
+
|
| 10 |
+
body:
|
| 11 |
+
- type: markdown
|
| 12 |
+
attributes:
|
| 13 |
+
value: |
|
| 14 |
+
Thanks for taking the time to fill out this bug report!
|
| 15 |
+
Please do not post usage questions here. Ask them on the [PyPSA Discord server](https://discord.gg/AnuJBk23FU).
|
| 16 |
+
|
| 17 |
+
- type: checkboxes
|
| 18 |
+
id: checks
|
| 19 |
+
attributes:
|
| 20 |
+
label: Version Checks (indicate both or one)
|
| 21 |
+
options:
|
| 22 |
+
- label: >
|
| 23 |
+
I have confirmed this bug exists on the lastest
|
| 24 |
+
[release](https://github.com/pypsa/pypsa/releases) of PyPSA.
|
| 25 |
+
- label: >
|
| 26 |
+
I have confirmed this bug exists on the current
|
| 27 |
+
[`master`](https://github.com/pypsa/pypsa/tree/master) branch of PyPSA.
|
| 28 |
+
|
| 29 |
+
- type: textarea
|
| 30 |
+
id: problem
|
| 31 |
+
attributes:
|
| 32 |
+
label: Issue Description
|
| 33 |
+
description: >
|
| 34 |
+
Please provide a description of the issue.
|
| 35 |
+
validations:
|
| 36 |
+
required: true
|
| 37 |
+
|
| 38 |
+
- type: textarea
|
| 39 |
+
id: example
|
| 40 |
+
validations:
|
| 41 |
+
required: true
|
| 42 |
+
attributes:
|
| 43 |
+
label: Reproducible Example
|
| 44 |
+
description: >
|
| 45 |
+
Please provide a minimal reproduciable example. See how to [craft minimal bug reports](https://matthewrocklin.com/minimal-bug-reports).
|
| 46 |
+
placeholder: >
|
| 47 |
+
import pypsa
|
| 48 |
+
|
| 49 |
+
n = pypsa.Network()
|
| 50 |
+
|
| 51 |
+
render: python
|
| 52 |
+
|
| 53 |
+
- type: textarea
|
| 54 |
+
id: expected-behavior
|
| 55 |
+
validations:
|
| 56 |
+
required: true
|
| 57 |
+
attributes:
|
| 58 |
+
label: Expected Behavior
|
| 59 |
+
description: >
|
| 60 |
+
Please describe or show a code example of the expected behavior.
|
| 61 |
+
|
| 62 |
+
- type: textarea
|
| 63 |
+
id: version
|
| 64 |
+
attributes:
|
| 65 |
+
label: Installed Versions
|
| 66 |
+
description: >
|
| 67 |
+
Please share information on your environment. Paste the output below. For conda `conda env export` and for pip `pip freeze`.
|
| 68 |
+
value: >
|
| 69 |
+
<details>
|
| 70 |
+
|
| 71 |
+
Replace this line.
|
| 72 |
+
|
| 73 |
+
</details>
|
PyPSA/source/.github/ISSUE_TEMPLATE/config.yml
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
blank_issues_enabled: true
|
| 6 |
+
contact_links:
|
| 7 |
+
- name: PyPSA Discord server
|
| 8 |
+
url: https://discord.gg/AnuJBk23FU
|
| 9 |
+
about: Please ask and answer general usage questions here.
|
PyPSA/source/.github/ISSUE_TEMPLATE/documentation_improvement.yaml
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
name: Documentation Improvement
|
| 6 |
+
description: Report wrong or missing documentation
|
| 7 |
+
labels: ["needs triage"]
|
| 8 |
+
type: 'Docs'
|
| 9 |
+
|
| 10 |
+
body:
|
| 11 |
+
- type: textarea
|
| 12 |
+
id: location
|
| 13 |
+
attributes:
|
| 14 |
+
label: Location
|
| 15 |
+
description: >
|
| 16 |
+
Please provide the location of the documentation or docstring, e.g. `pypsa.Network.import_from_netcdf` or the link to the docs.
|
| 17 |
+
placeholder: https://docs.pypsa.org/latest/user-guide/linear-power-flow
|
| 18 |
+
required: true
|
| 19 |
+
- type: textarea
|
| 20 |
+
id: problem
|
| 21 |
+
attributes:
|
| 22 |
+
label: Documentation problem
|
| 23 |
+
description: >
|
| 24 |
+
Please provide a description of what you believe needs to be fixed/ improved/ explained.
|
| 25 |
+
validations:
|
| 26 |
+
required: true
|
PyPSA/source/.github/ISSUE_TEMPLATE/feature_request.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: Feature Request
|
| 3 |
+
about: Suggest an idea for this project
|
| 4 |
+
title: ''
|
| 5 |
+
labels: ["needs triage"]
|
| 6 |
+
type: 'Feature'
|
| 7 |
+
assignees: ''
|
| 8 |
+
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
<!-- Please do not post usage questions here. Ask them on the PyPSA Discord server: https://discord.gg/AnuJBk23FU -->
|
| 12 |
+
|
| 13 |
+
## Describe the feature you'd like to see
|
| 14 |
+
|
| 15 |
+
*Please give a clear and concise description and provide context why the feature would be useful.*
|
| 16 |
+
*Also, we'd appreciate any implementation ideas and references you already have.*
|
PyPSA/source/.github/dependabot.yml
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
# dependabot
|
| 6 |
+
# Ref: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
| 7 |
+
# ------------------------------------------------------------------------------
|
| 8 |
+
version: 2
|
| 9 |
+
updates:
|
| 10 |
+
- package-ecosystem: github-actions
|
| 11 |
+
directory: /
|
| 12 |
+
schedule:
|
| 13 |
+
interval: monthly
|
| 14 |
+
groups:
|
| 15 |
+
# open a single pull-request for all GitHub actions updates
|
| 16 |
+
github-actions:
|
| 17 |
+
patterns:
|
| 18 |
+
- '*'
|
PyPSA/source/.github/pull_request_template.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Closes # (if applicable).
|
| 2 |
+
|
| 3 |
+
## Changes proposed in this Pull Request
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
## Checklist
|
| 7 |
+
|
| 8 |
+
- [ ] Code changes are sufficiently documented; i.e. new functions contain docstrings and further explanations may be given in `docs`.
|
| 9 |
+
- [ ] Unit tests for new features were added (if applicable).
|
| 10 |
+
- [ ] A note for the release notes `docs/release-notes.md` of the upcoming release is included.
|
| 11 |
+
- [ ] I consent to the release of this PR's code under the MIT license.
|
PyPSA/source/.github/workflows/codeql.yml
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
# For most projects, this workflow file will not need changing; you simply need
|
| 6 |
+
# to commit it to your repository.
|
| 7 |
+
#
|
| 8 |
+
# You may wish to alter this file to override the set of languages analyzed,
|
| 9 |
+
# or to provide custom queries or build logic.
|
| 10 |
+
#
|
| 11 |
+
# ******** NOTE ********
|
| 12 |
+
# We have attempted to detect the languages in your repository. Please check
|
| 13 |
+
# the `language` matrix defined below to confirm you have the correct set of
|
| 14 |
+
# supported CodeQL languages.
|
| 15 |
+
#
|
| 16 |
+
name: "CodeQL"
|
| 17 |
+
|
| 18 |
+
on:
|
| 19 |
+
push:
|
| 20 |
+
branches: ["master"]
|
| 21 |
+
pull_request:
|
| 22 |
+
branches: ["master"]
|
| 23 |
+
schedule:
|
| 24 |
+
- cron: '36 6 * * 4'
|
| 25 |
+
|
| 26 |
+
jobs:
|
| 27 |
+
analyze:
|
| 28 |
+
name: Analyze (${{ matrix.language }})
|
| 29 |
+
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
| 30 |
+
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
| 31 |
+
# - https://gh.io/supported-runners-and-hardware-resources
|
| 32 |
+
# - https://gh.io/using-larger-runners (GitHub.com only)
|
| 33 |
+
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
| 34 |
+
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
| 35 |
+
permissions:
|
| 36 |
+
# required for all workflows
|
| 37 |
+
security-events: write
|
| 38 |
+
|
| 39 |
+
# required to fetch internal or private CodeQL packs
|
| 40 |
+
packages: read
|
| 41 |
+
|
| 42 |
+
# only required for workflows in private repositories
|
| 43 |
+
actions: read
|
| 44 |
+
contents: read
|
| 45 |
+
|
| 46 |
+
strategy:
|
| 47 |
+
fail-fast: false
|
| 48 |
+
matrix:
|
| 49 |
+
include:
|
| 50 |
+
- language: python
|
| 51 |
+
build-mode: none
|
| 52 |
+
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
|
| 53 |
+
# Use `c-cpp` to analyze code written in C, C++ or both
|
| 54 |
+
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
| 55 |
+
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
| 56 |
+
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
| 57 |
+
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
| 58 |
+
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
| 59 |
+
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
| 60 |
+
steps:
|
| 61 |
+
- name: Checkout repository
|
| 62 |
+
uses: actions/checkout@v5
|
| 63 |
+
|
| 64 |
+
# Initializes the CodeQL tools for scanning.
|
| 65 |
+
- name: Initialize CodeQL
|
| 66 |
+
uses: github/codeql-action/init@v4
|
| 67 |
+
with:
|
| 68 |
+
languages: ${{ matrix.language }}
|
| 69 |
+
build-mode: ${{ matrix.build-mode }}
|
| 70 |
+
# If you wish to specify custom queries, you can do so here or in a config file.
|
| 71 |
+
# By default, queries listed here will override any specified in a config file.
|
| 72 |
+
# Prefix the list here with "+" to use these queries and those in the config file.
|
| 73 |
+
|
| 74 |
+
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
| 75 |
+
# queries: security-extended,security-and-quality
|
| 76 |
+
|
| 77 |
+
# If the analyze step fails for one of the languages you are analyzing with
|
| 78 |
+
# "We were unable to automatically build your code", modify the matrix above
|
| 79 |
+
# to set the build mode to "manual" for that language. Then modify this step
|
| 80 |
+
# to build your code.
|
| 81 |
+
# ℹ️ Command-line programs to run using the OS shell.
|
| 82 |
+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
| 83 |
+
- if: matrix.build-mode == 'manual'
|
| 84 |
+
shell: bash
|
| 85 |
+
run: |
|
| 86 |
+
echo 'If you are using a "manual" build mode for one or more of the' \
|
| 87 |
+
'languages you are analyzing, replace this with the commands to build' \
|
| 88 |
+
'your code, for example:'
|
| 89 |
+
echo ' make bootstrap'
|
| 90 |
+
echo ' make release'
|
| 91 |
+
exit 1
|
| 92 |
+
|
| 93 |
+
- name: Perform CodeQL Analysis
|
| 94 |
+
uses: github/codeql-action/analyze@v4
|
| 95 |
+
with:
|
| 96 |
+
category: "/language:${{matrix.language}}"
|
PyPSA/source/.github/workflows/release.yml
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
name: Release
|
| 6 |
+
|
| 7 |
+
on:
|
| 8 |
+
push:
|
| 9 |
+
tags:
|
| 10 |
+
- v*.*.*
|
| 11 |
+
|
| 12 |
+
env:
|
| 13 |
+
PREPARATION_COMMIT: '[github-actions.ci] prepare release ${{ github.ref_name }}'
|
| 14 |
+
|
| 15 |
+
jobs:
|
| 16 |
+
check-preparation:
|
| 17 |
+
name: Check if release is prepared
|
| 18 |
+
runs-on: ubuntu-latest
|
| 19 |
+
outputs:
|
| 20 |
+
prepared: ${{ steps.validate.outputs.prepared }}
|
| 21 |
+
steps:
|
| 22 |
+
- uses: actions/checkout@v5
|
| 23 |
+
|
| 24 |
+
- name: Validate commit message
|
| 25 |
+
id: validate
|
| 26 |
+
run: |
|
| 27 |
+
# Check if last commit is the expected commit message
|
| 28 |
+
COMMIT_MESSAGE=$(git log -1 --pretty=%B)
|
| 29 |
+
echo "Expected: '${{ env.PREPARATION_COMMIT }}'"
|
| 30 |
+
echo "Received: '$COMMIT_MESSAGE'"
|
| 31 |
+
|
| 32 |
+
prepared="false"
|
| 33 |
+
if [[ "$COMMIT_MESSAGE" == "${{ env.PREPARATION_COMMIT }}" ]]; then
|
| 34 |
+
prepared="true"
|
| 35 |
+
fi
|
| 36 |
+
|
| 37 |
+
echo "prepared=$prepared" >> $GITHUB_OUTPUT
|
| 38 |
+
|
| 39 |
+
prepare-release:
|
| 40 |
+
name: Prepare release
|
| 41 |
+
needs: [check-preparation]
|
| 42 |
+
if: ${{ needs.check-preparation.outputs.prepared == 'false' }}
|
| 43 |
+
runs-on: ubuntu-latest
|
| 44 |
+
steps:
|
| 45 |
+
- name: Generate token for PyPSA Bot
|
| 46 |
+
id: generate-token
|
| 47 |
+
uses: actions/create-github-app-token@v2
|
| 48 |
+
with:
|
| 49 |
+
app-id: ${{ vars.PYPSA_BOT_ID }}
|
| 50 |
+
private-key: ${{ secrets.PYPSA_BOT_PRIVATE_KEY }}
|
| 51 |
+
|
| 52 |
+
- uses: actions/checkout@v5
|
| 53 |
+
with:
|
| 54 |
+
fetch-depth: 0
|
| 55 |
+
|
| 56 |
+
- name: Find the branch for commit/ tag
|
| 57 |
+
run: |
|
| 58 |
+
branch=$(git branch -r --contains ${{ github.sha }} | grep -v 'HEAD' | head -n 1 | sed 's|origin/||' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
| 59 |
+
echo "Branch found: $branch"
|
| 60 |
+
echo "BRANCH_NAME=$branch" >> $GITHUB_ENV
|
| 61 |
+
|
| 62 |
+
- uses: actions/checkout@v5
|
| 63 |
+
with:
|
| 64 |
+
fetch-depth: 0
|
| 65 |
+
ref: ${{ env.BRANCH_NAME }}
|
| 66 |
+
token: ${{ steps.generate-token.outputs.token }}
|
| 67 |
+
|
| 68 |
+
# Start of preparation script
|
| 69 |
+
|
| 70 |
+
- uses: actions/setup-python@v6
|
| 71 |
+
with:
|
| 72 |
+
python-version: 3.12
|
| 73 |
+
|
| 74 |
+
- name: Install packages
|
| 75 |
+
run: |
|
| 76 |
+
python -m pip install uv
|
| 77 |
+
uv pip install --system toml
|
| 78 |
+
uv pip install --system setuptools_scm
|
| 79 |
+
uv pip install --system .
|
| 80 |
+
|
| 81 |
+
- name: Update CITATION.cff
|
| 82 |
+
run: |
|
| 83 |
+
import re
|
| 84 |
+
from setuptools_scm import get_version
|
| 85 |
+
|
| 86 |
+
version = get_version()
|
| 87 |
+
|
| 88 |
+
with open('CITATION.cff', 'r') as file:
|
| 89 |
+
cff_content = file.read()
|
| 90 |
+
cff_content = open('CITATION.cff', 'r').read()
|
| 91 |
+
|
| 92 |
+
updated_cff_content = re.sub(r"(?<=version: ).+(?= #)",version,cff_content,flags=re.MULTILINE)
|
| 93 |
+
|
| 94 |
+
with open('CITATION.cff', 'w') as file:
|
| 95 |
+
file.write(updated_cff_content)
|
| 96 |
+
shell: python
|
| 97 |
+
|
| 98 |
+
- name: Update example notebooks
|
| 99 |
+
run: |
|
| 100 |
+
import pypsa
|
| 101 |
+
# ac-dc-meshed
|
| 102 |
+
n = pypsa.Network("examples/networks/ac-dc-meshed/ac-dc-meshed")
|
| 103 |
+
n.export_to_csv_folder("examples/networks/ac-dc-meshed/ac-dc-meshed")
|
| 104 |
+
n.export_to_netcdf("examples/networks/ac-dc-meshed/ac-dc-meshed.nc")
|
| 105 |
+
# storage-hvdc
|
| 106 |
+
n = pypsa.Network("examples/networks/storage-hvdc/storage-hvdc")
|
| 107 |
+
n.export_to_csv_folder("examples/networks/storage-hvdc/storage-hvdc")
|
| 108 |
+
n.export_to_netcdf("examples/networks/storage-hvdc/storage-hvdc.nc")
|
| 109 |
+
# scigrid-de
|
| 110 |
+
n = pypsa.Network("examples/networks/scigrid-de/scigrid-de")
|
| 111 |
+
n.export_to_csv_folder("examples/networks/scigrid-de/scigrid-de")
|
| 112 |
+
n.export_to_netcdf("examples/networks/scigrid-de/scigrid-de.nc")
|
| 113 |
+
# model-energy
|
| 114 |
+
n = pypsa.Network("examples/networks/model-energy/model-energy")
|
| 115 |
+
n.export_to_csv_folder("examples/networks/model-energy/model-energy")
|
| 116 |
+
n.export_to_netcdf("examples/networks/model-energy/model-energy.nc")
|
| 117 |
+
# stochastic-network
|
| 118 |
+
n = pypsa.Network("examples/networks/stochastic-network/stochastic-network.nc")
|
| 119 |
+
n.export_to_netcdf("examples/networks/stochastic-network/stochastic-network.nc")
|
| 120 |
+
shell: python
|
| 121 |
+
|
| 122 |
+
# End of preparation script
|
| 123 |
+
|
| 124 |
+
- name: Remove previous tag
|
| 125 |
+
run: |
|
| 126 |
+
git tag -d ${{ github.ref_name }}
|
| 127 |
+
git push origin --delete ${{ github.ref_name }}
|
| 128 |
+
|
| 129 |
+
- name: Commit changes
|
| 130 |
+
uses: stefanzweifel/git-auto-commit-action@v7
|
| 131 |
+
with:
|
| 132 |
+
branch: ${{ env.BRANCH_NAME }}
|
| 133 |
+
commit_message: '${{ env.PREPARATION_COMMIT }}'
|
| 134 |
+
tagging_message: '${{ github.ref_name }}' # add tag again
|
| 135 |
+
push_options: '${{ github.ref_name }}'
|
| 136 |
+
add_options: '-u' # Never add untracked files
|
| 137 |
+
|
| 138 |
+
build:
|
| 139 |
+
name: Build and verify package
|
| 140 |
+
needs: [check-preparation]
|
| 141 |
+
if: ${{ needs.check-preparation.outputs.prepared == 'true' }}
|
| 142 |
+
runs-on: ubuntu-latest
|
| 143 |
+
steps:
|
| 144 |
+
- uses: actions/checkout@v5
|
| 145 |
+
- uses: hynek/build-and-inspect-python-package@v2
|
| 146 |
+
|
| 147 |
+
release:
|
| 148 |
+
name: Create GitHub release
|
| 149 |
+
needs: [build]
|
| 150 |
+
runs-on: ubuntu-latest
|
| 151 |
+
steps:
|
| 152 |
+
- uses: actions/checkout@v5
|
| 153 |
+
- uses: softprops/action-gh-release@v2
|
| 154 |
+
with:
|
| 155 |
+
body: |
|
| 156 |
+
Revised release notes are available in the [documentation](https://${{ github.event.repository.name }}.readthedocs.io/en/latest/release-notes.html).
|
| 157 |
+
append_body: true
|
| 158 |
+
generate_release_notes: true
|
| 159 |
+
|
| 160 |
+
publish:
|
| 161 |
+
name: Publish to PyPI
|
| 162 |
+
needs: [build]
|
| 163 |
+
runs-on: ubuntu-latest
|
| 164 |
+
environment:
|
| 165 |
+
name: pypi
|
| 166 |
+
url: https://pypi.org/project/${{ github.event.repository.name }}
|
| 167 |
+
permissions:
|
| 168 |
+
id-token: write
|
| 169 |
+
steps:
|
| 170 |
+
- uses: actions/download-artifact@v6
|
| 171 |
+
with:
|
| 172 |
+
name: Packages
|
| 173 |
+
path: dist
|
| 174 |
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
PyPSA/source/.github/workflows/test-models.yml
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
name: Test models
|
| 6 |
+
|
| 7 |
+
on:
|
| 8 |
+
push:
|
| 9 |
+
branches:
|
| 10 |
+
- master
|
| 11 |
+
- release-branch-v*
|
| 12 |
+
pull_request:
|
| 13 |
+
branches: ['*']
|
| 14 |
+
schedule:
|
| 15 |
+
- cron: "0 5 * * *"
|
| 16 |
+
|
| 17 |
+
env:
|
| 18 |
+
PACKAGE_NAME: 'pypsa'
|
| 19 |
+
|
| 20 |
+
# Cancel any in-progress runs when a new run is triggered
|
| 21 |
+
concurrency:
|
| 22 |
+
group: ${{ github.workflow }}-${{ github.ref }}
|
| 23 |
+
cancel-in-progress: true
|
| 24 |
+
|
| 25 |
+
jobs:
|
| 26 |
+
test-pypsa-eur:
|
| 27 |
+
name: PyPSA-Eur
|
| 28 |
+
runs-on: ubuntu-latest
|
| 29 |
+
strategy:
|
| 30 |
+
fail-fast: false
|
| 31 |
+
matrix:
|
| 32 |
+
version:
|
| 33 |
+
- master
|
| 34 |
+
# - latest
|
| 35 |
+
|
| 36 |
+
defaults:
|
| 37 |
+
run:
|
| 38 |
+
shell: bash -l {0}
|
| 39 |
+
|
| 40 |
+
steps:
|
| 41 |
+
- uses: actions/checkout@v5
|
| 42 |
+
with:
|
| 43 |
+
repository: PyPSA/pypsa-eur
|
| 44 |
+
ref: master
|
| 45 |
+
|
| 46 |
+
- name: Check out latest release
|
| 47 |
+
if: matrix.version == 'latest'
|
| 48 |
+
run: |
|
| 49 |
+
git fetch --tags
|
| 50 |
+
latest_tag=$(git describe --tags `git rev-list --tags --max-count=1`)
|
| 51 |
+
git checkout $latest_tag
|
| 52 |
+
|
| 53 |
+
- name: Setup Pixi
|
| 54 |
+
uses: prefix-dev/setup-pixi@v0.9.3
|
| 55 |
+
with:
|
| 56 |
+
pixi-version: v0.59.0
|
| 57 |
+
cache: true
|
| 58 |
+
# Do not cache in branches
|
| 59 |
+
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'main' }}
|
| 60 |
+
|
| 61 |
+
- name: Setup cache keys
|
| 62 |
+
run: |
|
| 63 |
+
echo "WEEK=$(date +'%Y%U')" >> $GITHUB_ENV # data and cutouts
|
| 64 |
+
|
| 65 |
+
# Only run check if package is not pinned
|
| 66 |
+
- name: Check if inhouse package is pinned
|
| 67 |
+
run: |
|
| 68 |
+
grep_line=$(grep -- '- pypsa' envs/environment.yaml)
|
| 69 |
+
if [[ $grep_line == *"<"* || $grep_line == *"=="* ]]; then
|
| 70 |
+
echo "pinned=true" >> $GITHUB_ENV
|
| 71 |
+
else
|
| 72 |
+
echo "pinned=false" >> $GITHUB_ENV
|
| 73 |
+
fi
|
| 74 |
+
|
| 75 |
+
- uses: actions/cache@v4
|
| 76 |
+
if: env.pinned == 'false'
|
| 77 |
+
with:
|
| 78 |
+
path: |
|
| 79 |
+
data
|
| 80 |
+
cutouts
|
| 81 |
+
key: data-cutouts-pypsa-eur-${{ env.WEEK }}
|
| 82 |
+
|
| 83 |
+
- name: Install package from ref
|
| 84 |
+
if: env.pinned == 'false'
|
| 85 |
+
run: |
|
| 86 |
+
pixi remove ${{ env.PACKAGE_NAME }}
|
| 87 |
+
pixi add --pypi --git https://github.com/${{ github.repository }}.git ${{ github.event.repository.name }} --rev ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
| 88 |
+
|
| 89 |
+
- name: Run snakemake test workflows
|
| 90 |
+
if: env.pinned == 'false'
|
| 91 |
+
run: |
|
| 92 |
+
pixi run integration-tests
|
| 93 |
+
|
| 94 |
+
- name: Run unit tests
|
| 95 |
+
if: env.pinned == 'false'
|
| 96 |
+
run: |
|
| 97 |
+
pixi run unit-tests
|
| 98 |
+
|
| 99 |
+
- name: Upload artifacts
|
| 100 |
+
if: env.pinned == 'false'
|
| 101 |
+
uses: actions/upload-artifact@v5
|
| 102 |
+
with:
|
| 103 |
+
name: results-pypsa-eur-${{ matrix.version }}
|
| 104 |
+
path: |
|
| 105 |
+
logs
|
| 106 |
+
.snakemake/log
|
| 107 |
+
results
|
| 108 |
+
retention-days: 3
|
| 109 |
+
|
| 110 |
+
# Temporarily disabled until PyPSA-DE issues are resolved. This is not a problem of PyPSA.
|
| 111 |
+
# test-pypsa-de:
|
| 112 |
+
# name: PyPSA-DE
|
| 113 |
+
# runs-on: ubuntu-latest
|
| 114 |
+
# strategy:
|
| 115 |
+
# fail-fast: false
|
| 116 |
+
# matrix:
|
| 117 |
+
# version:
|
| 118 |
+
# - master
|
| 119 |
+
# # - latest
|
| 120 |
+
|
| 121 |
+
# defaults:
|
| 122 |
+
# run:
|
| 123 |
+
# shell: bash -l {0}
|
| 124 |
+
|
| 125 |
+
# steps:
|
| 126 |
+
# - uses: actions/checkout@v5
|
| 127 |
+
# with:
|
| 128 |
+
# repository: PyPSA/pypsa-de
|
| 129 |
+
# ref: main
|
| 130 |
+
|
| 131 |
+
# - name: Check out latest release
|
| 132 |
+
# if: matrix.version == 'latest'
|
| 133 |
+
# run: |
|
| 134 |
+
# git fetch --tags
|
| 135 |
+
# latest_tag=$(git describe --tags `git rev-list --tags --max-count=1`)
|
| 136 |
+
# git checkout $latest_tag
|
| 137 |
+
|
| 138 |
+
# - name: Setup cache keys
|
| 139 |
+
# run: |
|
| 140 |
+
# echo "WEEK=$(date +'%Y%U')" >> $GITHUB_ENV # data and cutouts
|
| 141 |
+
|
| 142 |
+
# # Only run check if package is not pinned
|
| 143 |
+
# - name: Check if inhouse package is pinned
|
| 144 |
+
# run: |
|
| 145 |
+
# grep_line=$(grep -- '- pypsa' envs/environment.yaml)
|
| 146 |
+
# if [[ $grep_line == *"<"* || $grep_line == *"=="* ]]; then
|
| 147 |
+
# echo "pinned=true" >> $GITHUB_ENV
|
| 148 |
+
# else
|
| 149 |
+
# echo "pinned=false" >> $GITHUB_ENV
|
| 150 |
+
# fi
|
| 151 |
+
|
| 152 |
+
# - uses: actions/cache@v4
|
| 153 |
+
# if: env.pinned == 'false'
|
| 154 |
+
# with:
|
| 155 |
+
# path: |
|
| 156 |
+
# data
|
| 157 |
+
# cutouts
|
| 158 |
+
# resources/ariadne_database.csv
|
| 159 |
+
# key: data-cutouts-pypsa-de-${{ env.WEEK }}
|
| 160 |
+
|
| 161 |
+
# - uses: conda-incubator/setup-miniconda@v3
|
| 162 |
+
# if: env.pinned == 'false'
|
| 163 |
+
# with:
|
| 164 |
+
# miniforge-version: latest
|
| 165 |
+
# activate-environment: pypsa-de
|
| 166 |
+
# channel-priority: strict
|
| 167 |
+
|
| 168 |
+
# - name: Cache Conda env
|
| 169 |
+
# if: env.pinned == 'false'
|
| 170 |
+
# uses: actions/cache@v4
|
| 171 |
+
# with:
|
| 172 |
+
# path: ${{ env.CONDA }}/envs
|
| 173 |
+
# key: conda-pypsa-de-${{ env.WEEK }}-${{ hashFiles('envs/linux-64.lock.yaml') }}
|
| 174 |
+
# id: cache-env
|
| 175 |
+
|
| 176 |
+
# - name: Update environment
|
| 177 |
+
# if: env.pinned == 'false' && steps.cache-env.outputs.cache-hit != 'true'
|
| 178 |
+
# run: |
|
| 179 |
+
# conda env update -n pypsa-de -f envs/linux-64.lock.yaml
|
| 180 |
+
# echo "Run conda list" && conda list
|
| 181 |
+
|
| 182 |
+
# - name: Install package from ref
|
| 183 |
+
# if: env.pinned == 'false'
|
| 184 |
+
# run: |
|
| 185 |
+
# python -m pip install git+https://github.com/${{ github.repository }}@${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
| 186 |
+
|
| 187 |
+
# - name: Run snakemake test workflows
|
| 188 |
+
# if: env.pinned == 'false'
|
| 189 |
+
# run: |
|
| 190 |
+
# make test
|
| 191 |
+
|
| 192 |
+
# - name: Run unit tests
|
| 193 |
+
# if: env.pinned == 'false'
|
| 194 |
+
# run: |
|
| 195 |
+
# make unit-test
|
| 196 |
+
|
| 197 |
+
# - name: Upload artifacts
|
| 198 |
+
# if: env.pinned == 'false'
|
| 199 |
+
# uses: actions/upload-artifact@v5
|
| 200 |
+
# with:
|
| 201 |
+
# name: results-pypsa-de-${{ matrix.version }}
|
| 202 |
+
# path: |
|
| 203 |
+
# logs
|
| 204 |
+
# .snakemake/log
|
| 205 |
+
# results
|
| 206 |
+
# retention-days: 3
|
PyPSA/source/.github/workflows/test.yml
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
name: Tests
|
| 6 |
+
|
| 7 |
+
on:
|
| 8 |
+
push:
|
| 9 |
+
branches:
|
| 10 |
+
- master
|
| 11 |
+
- release-branch-v*
|
| 12 |
+
pull_request:
|
| 13 |
+
branches: ["*"]
|
| 14 |
+
schedule:
|
| 15 |
+
- cron: "0 5 * * *"
|
| 16 |
+
|
| 17 |
+
# Cancel any in-progress runs when a new run is triggered
|
| 18 |
+
concurrency:
|
| 19 |
+
group: ${{ github.workflow }}-${{ github.ref }}
|
| 20 |
+
cancel-in-progress: true
|
| 21 |
+
|
| 22 |
+
jobs:
|
| 23 |
+
build:
|
| 24 |
+
# Build the Python SDist and wheel, performs metadata and readme linting
|
| 25 |
+
name: Build and verify package
|
| 26 |
+
runs-on: ubuntu-latest
|
| 27 |
+
steps:
|
| 28 |
+
- uses: actions/checkout@v5
|
| 29 |
+
with:
|
| 30 |
+
fetch-depth: 0 # Needed for setuptools_scm
|
| 31 |
+
- uses: hynek/build-and-inspect-python-package@v2
|
| 32 |
+
id: baipp
|
| 33 |
+
|
| 34 |
+
outputs:
|
| 35 |
+
python-versions: ${{ steps.baipp.outputs.supported_python_classifiers_json_array }}
|
| 36 |
+
|
| 37 |
+
test:
|
| 38 |
+
# Test package build in matrix of OS and Python versions
|
| 39 |
+
name: Test package
|
| 40 |
+
needs: [build]
|
| 41 |
+
runs-on: ${{ matrix.os }}
|
| 42 |
+
strategy:
|
| 43 |
+
fail-fast: false
|
| 44 |
+
matrix:
|
| 45 |
+
python-version: ${{ fromJSON(needs.build.outputs.python-versions) }}
|
| 46 |
+
os:
|
| 47 |
+
- ubuntu-latest
|
| 48 |
+
- macos-latest
|
| 49 |
+
- windows-latest
|
| 50 |
+
api: [default, new_api]
|
| 51 |
+
exclude:
|
| 52 |
+
- os: macos-latest
|
| 53 |
+
api: new_api
|
| 54 |
+
- os: windows-latest
|
| 55 |
+
api: new_api
|
| 56 |
+
|
| 57 |
+
env:
|
| 58 |
+
MPLBACKEND: Agg # https://github.com/orgs/community/discussions/26434
|
| 59 |
+
steps:
|
| 60 |
+
- uses: actions/checkout@v5
|
| 61 |
+
with:
|
| 62 |
+
fetch-depth: 0 # Needed for setuptools_scm
|
| 63 |
+
|
| 64 |
+
- name: Set up Python ${{ matrix.python-version }} on ${{ matrix.os }}
|
| 65 |
+
uses: actions/setup-python@v6
|
| 66 |
+
with:
|
| 67 |
+
python-version: ${{ matrix.python-version }}
|
| 68 |
+
|
| 69 |
+
- name: Install macos dependencies
|
| 70 |
+
if: matrix.os == 'macos-latest'
|
| 71 |
+
run: |
|
| 72 |
+
brew update
|
| 73 |
+
# pkg-config is deprecated but still installed in runner
|
| 74 |
+
# Can be removed once it is removed from the runner
|
| 75 |
+
brew unlink pkg-config@0.29.2 || true
|
| 76 |
+
brew install hdf5
|
| 77 |
+
|
| 78 |
+
- name: Download package
|
| 79 |
+
uses: actions/download-artifact@v6
|
| 80 |
+
with:
|
| 81 |
+
name: Packages
|
| 82 |
+
path: dist
|
| 83 |
+
|
| 84 |
+
- name: Install package and dependencies
|
| 85 |
+
run: |
|
| 86 |
+
python -m pip install uv
|
| 87 |
+
uv sync --all-extras --no-install-project
|
| 88 |
+
uv pip install "$(ls dist/*.whl)"
|
| 89 |
+
|
| 90 |
+
- name: Run unit tests (old API)
|
| 91 |
+
if: matrix.api == 'default'
|
| 92 |
+
run: >
|
| 93 |
+
uv run pytest --mpl --mpl-generate-summary=html --mpl-results-path=mpl-results
|
| 94 |
+
--cov=pypsa --junitxml=junit.xml -o junit_family=legacy
|
| 95 |
+
&& uv run coverage xml
|
| 96 |
+
|
| 97 |
+
- name: Run unit tests (new API)
|
| 98 |
+
if: matrix.api == 'new_api'
|
| 99 |
+
run: >
|
| 100 |
+
uv run pytest
|
| 101 |
+
--new-components-api
|
| 102 |
+
--mpl --mpl-generate-summary=html --mpl-results-path=mpl-results
|
| 103 |
+
--cov=pypsa --junitxml=junit.xml -o junit_family=legacy
|
| 104 |
+
&& uv run coverage xml
|
| 105 |
+
|
| 106 |
+
- name: Upload artifacts
|
| 107 |
+
if: matrix.api == 'default' && matrix.os == 'macos-latest' && matrix.python-version == '3.13'
|
| 108 |
+
uses: actions/upload-artifact@v5
|
| 109 |
+
with:
|
| 110 |
+
name: results-plotting
|
| 111 |
+
path: |
|
| 112 |
+
mpl-results
|
| 113 |
+
retention-days: 14
|
| 114 |
+
if-no-files-found: ignore
|
| 115 |
+
|
| 116 |
+
- name: Upload code coverage report
|
| 117 |
+
if: ${{ !cancelled() }}
|
| 118 |
+
uses: codecov/codecov-action@v5
|
| 119 |
+
with:
|
| 120 |
+
token: ${{ secrets.CODECOV_TOKEN }}
|
| 121 |
+
flags: >
|
| 122 |
+
unit-tests,
|
| 123 |
+
os-${{ matrix.os }},
|
| 124 |
+
python${{ matrix.python-version }},
|
| 125 |
+
api-${{ matrix.api }}
|
| 126 |
+
|
| 127 |
+
- name: Upload test results to Codecov
|
| 128 |
+
if: ${{ !cancelled() }}
|
| 129 |
+
uses: codecov/test-results-action@v1
|
| 130 |
+
with:
|
| 131 |
+
token: ${{ secrets.CODECOV_TOKEN }}
|
| 132 |
+
flags: >
|
| 133 |
+
unit-tests,
|
| 134 |
+
os-${{ matrix.os }},
|
| 135 |
+
python${{ matrix.python-version }},
|
| 136 |
+
api-${{ matrix.api }}
|
| 137 |
+
|
| 138 |
+
check-docs:
|
| 139 |
+
name: Check docs
|
| 140 |
+
needs: [build]
|
| 141 |
+
runs-on: ubuntu-latest
|
| 142 |
+
|
| 143 |
+
steps:
|
| 144 |
+
- uses: actions/checkout@v5
|
| 145 |
+
with:
|
| 146 |
+
fetch-depth: 0 # Needed for setuptools_scm
|
| 147 |
+
|
| 148 |
+
- name: Set up Python 3.13
|
| 149 |
+
uses: actions/setup-python@v6
|
| 150 |
+
with:
|
| 151 |
+
python-version: 3.13
|
| 152 |
+
|
| 153 |
+
- name: Download package
|
| 154 |
+
uses: actions/download-artifact@v6
|
| 155 |
+
with:
|
| 156 |
+
name: Packages
|
| 157 |
+
path: dist
|
| 158 |
+
|
| 159 |
+
- name: Install package and dependencies
|
| 160 |
+
run: |
|
| 161 |
+
python -m pip install uv
|
| 162 |
+
uv sync --all-extras --no-install-project
|
| 163 |
+
uv pip install "$(ls dist/*.whl)"
|
| 164 |
+
|
| 165 |
+
- name: Run doc tests
|
| 166 |
+
run: >
|
| 167 |
+
uv run pytest
|
| 168 |
+
test/test_docs.py --test-docs
|
| 169 |
+
--cov=pypsa --junitxml=junit.xml -o junit_family=legacy
|
| 170 |
+
&& uv run coverage xml
|
| 171 |
+
|
| 172 |
+
- name: Upload code coverage report
|
| 173 |
+
if: ${{ !cancelled() }}
|
| 174 |
+
uses: codecov/codecov-action@v5
|
| 175 |
+
with:
|
| 176 |
+
token: ${{ secrets.CODECOV_TOKEN }}
|
| 177 |
+
flags: >
|
| 178 |
+
doc-tests,
|
| 179 |
+
os-ubuntu-latest,
|
| 180 |
+
python3.13,
|
| 181 |
+
api-old-api
|
| 182 |
+
|
| 183 |
+
- name: Upload test results to Codecov
|
| 184 |
+
if: ${{ !cancelled() }}
|
| 185 |
+
uses: codecov/test-results-action@v1
|
| 186 |
+
with:
|
| 187 |
+
token: ${{ secrets.CODECOV_TOKEN }}
|
| 188 |
+
flags: >
|
| 189 |
+
doc-tests,
|
| 190 |
+
os-ubuntu-latest,
|
| 191 |
+
python3.13,
|
| 192 |
+
api-old-api
|
| 193 |
+
|
| 194 |
+
check-types:
|
| 195 |
+
name: Check types
|
| 196 |
+
needs: [build]
|
| 197 |
+
runs-on: ubuntu-latest
|
| 198 |
+
|
| 199 |
+
steps:
|
| 200 |
+
- uses: actions/checkout@v5
|
| 201 |
+
with:
|
| 202 |
+
fetch-depth: 0 # Needed for setuptools_scm
|
| 203 |
+
|
| 204 |
+
- name: Set up Python 3.13
|
| 205 |
+
uses: actions/setup-python@v6
|
| 206 |
+
with:
|
| 207 |
+
python-version: 3.13
|
| 208 |
+
|
| 209 |
+
- name: Download package
|
| 210 |
+
uses: actions/download-artifact@v6
|
| 211 |
+
with:
|
| 212 |
+
name: Packages
|
| 213 |
+
path: dist
|
| 214 |
+
|
| 215 |
+
- name: Install package and dependencies
|
| 216 |
+
run: |
|
| 217 |
+
python -m pip install uv
|
| 218 |
+
uv sync --all-extras --no-install-project
|
| 219 |
+
uv pip install "$(ls dist/*.whl)"
|
| 220 |
+
|
| 221 |
+
- name: Run type checker (mypy)
|
| 222 |
+
run: |
|
| 223 |
+
uv run mypy .
|
PyPSA/source/.gitignore
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
*~
|
| 6 |
+
.~*
|
| 7 |
+
*.py[cod]
|
| 8 |
+
.ipynb_checkpoints/
|
| 9 |
+
*.log
|
| 10 |
+
old/
|
| 11 |
+
|
| 12 |
+
# Ignore all jupyter notebooks, except those for the docs
|
| 13 |
+
*.ipynb
|
| 14 |
+
!/docs/**/*.ipynb
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
test/.cache/
|
| 18 |
+
.cache/
|
| 19 |
+
|
| 20 |
+
test/results/*
|
| 21 |
+
|
| 22 |
+
pypsa.egg-info/
|
| 23 |
+
|
| 24 |
+
files.txt
|
| 25 |
+
|
| 26 |
+
tom_notes.org
|
| 27 |
+
|
| 28 |
+
*.pdf
|
| 29 |
+
|
| 30 |
+
*.aux
|
| 31 |
+
|
| 32 |
+
website/examples/*.py
|
| 33 |
+
|
| 34 |
+
*.zip
|
| 35 |
+
|
| 36 |
+
.vscode
|
| 37 |
+
.devcontainer
|
| 38 |
+
.github/copilot-instructions.md
|
| 39 |
+
|
| 40 |
+
.idea
|
| 41 |
+
|
| 42 |
+
.coverage
|
| 43 |
+
|
| 44 |
+
dev-scripts
|
| 45 |
+
dev
|
| 46 |
+
|
| 47 |
+
.venv
|
| 48 |
+
uv.lock
|
| 49 |
+
.aider*
|
| 50 |
+
CLAUDE.md
|
| 51 |
+
.claude
|
| 52 |
+
.github/copilot-instructions.md
|
| 53 |
+
site/
|
| 54 |
+
doc/_build/
|
PyPSA/source/.pre-commit-config.yaml
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
exclude: ^(docs/hooks|examples)
|
| 6 |
+
|
| 7 |
+
ci:
|
| 8 |
+
autoupdate_schedule: quarterly
|
| 9 |
+
|
| 10 |
+
repos:
|
| 11 |
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
| 12 |
+
rev: v6.0.0
|
| 13 |
+
hooks:
|
| 14 |
+
- id: check-added-large-files
|
| 15 |
+
args: ['--maxkb=2000']
|
| 16 |
+
- id: trailing-whitespace
|
| 17 |
+
- id: end-of-file-fixer
|
| 18 |
+
|
| 19 |
+
# Run ruff to lint and format
|
| 20 |
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
| 21 |
+
# Ruff version.
|
| 22 |
+
rev: v0.13.3
|
| 23 |
+
hooks:
|
| 24 |
+
# Run the linter.
|
| 25 |
+
- id: ruff
|
| 26 |
+
args: [--fix]
|
| 27 |
+
# Run the formatter.
|
| 28 |
+
- id: ruff-format
|
| 29 |
+
|
| 30 |
+
# Find common spelling mistakes in comments and docstrings
|
| 31 |
+
- repo: https://github.com/codespell-project/codespell
|
| 32 |
+
rev: v2.4.1
|
| 33 |
+
hooks:
|
| 34 |
+
- id: codespell
|
| 35 |
+
# Ignore capital case words, e.g. country codes
|
| 36 |
+
args: ['--ignore-regex="(\b[A-Z]+\b)"', '--ignore-words=.codespell.ignore']
|
| 37 |
+
types_or: [python, rst, markdown]
|
| 38 |
+
files: ^(scripts|doc)/
|
| 39 |
+
|
| 40 |
+
# Remove output from Jupyter notebooks
|
| 41 |
+
- repo: https://github.com/aflc/pre-commit-jupyter
|
| 42 |
+
rev: v1.2.1
|
| 43 |
+
hooks:
|
| 44 |
+
- id: jupyter-notebook-cleanup
|
| 45 |
+
args: ['--remove-kernel-metadata']
|
| 46 |
+
|
| 47 |
+
# Do YAML formatting (before the linter checks it for misses)
|
| 48 |
+
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
|
| 49 |
+
rev: v2.15.0
|
| 50 |
+
hooks:
|
| 51 |
+
- id: pretty-format-yaml
|
| 52 |
+
args: [--autofix, --indent, '2', --preserve-quotes]
|
| 53 |
+
|
| 54 |
+
# Check for FSFE REUSE compliance (licensing)
|
| 55 |
+
- repo: https://github.com/fsfe/reuse-tool
|
| 56 |
+
rev: v6.0.0
|
| 57 |
+
hooks:
|
| 58 |
+
- id: reuse-lint-file
|
PyPSA/source/.readthedocs.yml
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
version: 2
|
| 6 |
+
|
| 7 |
+
build:
|
| 8 |
+
os: ubuntu-24.04
|
| 9 |
+
tools:
|
| 10 |
+
python: "3.13"
|
| 11 |
+
jobs:
|
| 12 |
+
pre_system_dependencies:
|
| 13 |
+
- git fetch --unshallow # Needed to get version tags
|
| 14 |
+
pre_create_environment:
|
| 15 |
+
- asdf plugin add uv
|
| 16 |
+
- asdf install uv latest
|
| 17 |
+
- asdf global uv latest
|
| 18 |
+
create_environment:
|
| 19 |
+
- uv venv "${READTHEDOCS_VIRTUALENV_PATH}"
|
| 20 |
+
install:
|
| 21 |
+
- UV_PROJECT_ENVIRONMENT="${READTHEDOCS_VIRTUALENV_PATH}" uv pip install -r docs/requirements.txt
|
| 22 |
+
pre_build:
|
| 23 |
+
# To create all doctest files
|
| 24 |
+
- uv run pytest test/test_docs.py --test-docs
|
| 25 |
+
|
| 26 |
+
mkdocs:
|
| 27 |
+
configuration: mkdocs.yml
|
| 28 |
+
fail_on_warning: true
|
PyPSA/source/CITATION.cff
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
cff-version: 1.2.0
|
| 6 |
+
message: "If you use this package, please cite the corresponding manuscript in Journal of Open Research Software."
|
| 7 |
+
title: "PyPSA: Python for Power System Analysis"
|
| 8 |
+
repository: https://github.com/pypsa/pypsa
|
| 9 |
+
version: 1.0.3 # Don't touch, will be updated by the release script
|
| 10 |
+
license: MIT
|
| 11 |
+
journal: Journal of Open Research Software
|
| 12 |
+
doi: 10.5334/jors.188
|
| 13 |
+
authors:
|
| 14 |
+
- family-names: Brown
|
| 15 |
+
given-names: Tom
|
| 16 |
+
orcid: https://orcid.org/0000-0001-5898-1911
|
| 17 |
+
- family-names: Hörsch
|
| 18 |
+
given-names: Jonas
|
| 19 |
+
orcid: https://orcid.org/0000-0001-9438-767X
|
| 20 |
+
- family-names: Schlachtberger
|
| 21 |
+
given-names: David
|
| 22 |
+
orcid: https://orcid.org/0000-0002-8167-8213
|
PyPSA/source/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!--
|
| 2 |
+
SPDX-FileCopyrightText: PyPSA Contributors
|
| 3 |
+
|
| 4 |
+
SPDX-License-Identifier: MIT
|
| 5 |
+
-->
|
| 6 |
+
|
| 7 |
+
🎉 Thank you for your interest in contributing to PyPSA! 🎉
|
| 8 |
+
|
| 9 |
+
We strongly welcome anyone interested in contributing to PyPSA and it's related projects. All types of contributions are encouraged and valued!
|
| 10 |
+
|
| 11 |
+
Detailed guidelines can be found in the [Contributing](https://docs.pypsa.org/latest/contributing/contributing/) section of our documentation.
|
PyPSA/source/LICENSE
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) <year> <copyright holders>
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
| 6 |
+
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
| 7 |
+
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 8 |
+
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
| 9 |
+
following conditions:
|
| 10 |
+
|
| 11 |
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
| 12 |
+
portions of the Software.
|
| 13 |
+
|
| 14 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
| 15 |
+
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
| 16 |
+
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
| 17 |
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
| 18 |
+
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
PyPSA/source/LICENSES/CC-BY-4.0.txt
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Creative Commons Attribution 4.0 International
|
| 2 |
+
|
| 3 |
+
Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.
|
| 4 |
+
|
| 5 |
+
Using Creative Commons Public Licenses
|
| 6 |
+
|
| 7 |
+
Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.
|
| 8 |
+
|
| 9 |
+
Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors.
|
| 10 |
+
|
| 11 |
+
Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public.
|
| 12 |
+
|
| 13 |
+
Creative Commons Attribution 4.0 International Public License
|
| 14 |
+
|
| 15 |
+
By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
|
| 16 |
+
|
| 17 |
+
Section 1 – Definitions.
|
| 18 |
+
|
| 19 |
+
a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
|
| 20 |
+
|
| 21 |
+
b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License.
|
| 22 |
+
|
| 23 |
+
c. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
|
| 24 |
+
|
| 25 |
+
d. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
|
| 26 |
+
|
| 27 |
+
e. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
|
| 28 |
+
|
| 29 |
+
f. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
|
| 30 |
+
|
| 31 |
+
g. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
|
| 32 |
+
|
| 33 |
+
h. Licensor means the individual(s) or entity(ies) granting rights under this Public License.
|
| 34 |
+
|
| 35 |
+
i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
|
| 36 |
+
|
| 37 |
+
j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
|
| 38 |
+
|
| 39 |
+
k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
|
| 40 |
+
|
| 41 |
+
Section 2 – Scope.
|
| 42 |
+
|
| 43 |
+
a. License grant.
|
| 44 |
+
|
| 45 |
+
1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
|
| 46 |
+
|
| 47 |
+
A. reproduce and Share the Licensed Material, in whole or in part; and
|
| 48 |
+
|
| 49 |
+
B. produce, reproduce, and Share Adapted Material.
|
| 50 |
+
|
| 51 |
+
2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
|
| 52 |
+
|
| 53 |
+
3. Term. The term of this Public License is specified in Section 6(a).
|
| 54 |
+
|
| 55 |
+
4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
|
| 56 |
+
|
| 57 |
+
5. Downstream recipients.
|
| 58 |
+
|
| 59 |
+
A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
|
| 60 |
+
|
| 61 |
+
B. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
|
| 62 |
+
|
| 63 |
+
6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
|
| 64 |
+
|
| 65 |
+
b. Other rights.
|
| 66 |
+
|
| 67 |
+
1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
|
| 68 |
+
|
| 69 |
+
2. Patent and trademark rights are not licensed under this Public License.
|
| 70 |
+
|
| 71 |
+
3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties.
|
| 72 |
+
|
| 73 |
+
Section 3 – License Conditions.
|
| 74 |
+
|
| 75 |
+
Your exercise of the Licensed Rights is expressly made subject to the following conditions.
|
| 76 |
+
|
| 77 |
+
a. Attribution.
|
| 78 |
+
|
| 79 |
+
1. If You Share the Licensed Material (including in modified form), You must:
|
| 80 |
+
|
| 81 |
+
A. retain the following if it is supplied by the Licensor with the Licensed Material:
|
| 82 |
+
|
| 83 |
+
i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
|
| 84 |
+
|
| 85 |
+
ii. a copyright notice;
|
| 86 |
+
|
| 87 |
+
iii. a notice that refers to this Public License;
|
| 88 |
+
|
| 89 |
+
iv. a notice that refers to the disclaimer of warranties;
|
| 90 |
+
|
| 91 |
+
v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
|
| 92 |
+
|
| 93 |
+
B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
|
| 94 |
+
|
| 95 |
+
C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
|
| 96 |
+
|
| 97 |
+
2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
|
| 98 |
+
|
| 99 |
+
3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
|
| 100 |
+
|
| 101 |
+
4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License.
|
| 102 |
+
|
| 103 |
+
Section 4 – Sui Generis Database Rights.
|
| 104 |
+
|
| 105 |
+
Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
|
| 106 |
+
|
| 107 |
+
a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database;
|
| 108 |
+
|
| 109 |
+
b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and
|
| 110 |
+
|
| 111 |
+
c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
|
| 112 |
+
For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
|
| 113 |
+
|
| 114 |
+
Section 5 – Disclaimer of Warranties and Limitation of Liability.
|
| 115 |
+
|
| 116 |
+
a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.
|
| 117 |
+
|
| 118 |
+
b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.
|
| 119 |
+
|
| 120 |
+
c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
|
| 121 |
+
|
| 122 |
+
Section 6 – Term and Termination.
|
| 123 |
+
|
| 124 |
+
a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
|
| 125 |
+
|
| 126 |
+
b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
|
| 127 |
+
|
| 128 |
+
1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
|
| 129 |
+
|
| 130 |
+
2. upon express reinstatement by the Licensor.
|
| 131 |
+
|
| 132 |
+
c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
|
| 133 |
+
|
| 134 |
+
d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
|
| 135 |
+
|
| 136 |
+
e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
|
| 137 |
+
|
| 138 |
+
Section 7 – Other Terms and Conditions.
|
| 139 |
+
|
| 140 |
+
a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
|
| 141 |
+
|
| 142 |
+
b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
|
| 143 |
+
|
| 144 |
+
Section 8 – Interpretation.
|
| 145 |
+
|
| 146 |
+
a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
|
| 147 |
+
|
| 148 |
+
b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
|
| 149 |
+
|
| 150 |
+
c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
|
| 151 |
+
|
| 152 |
+
d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
|
| 153 |
+
|
| 154 |
+
Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.
|
| 155 |
+
|
| 156 |
+
Creative Commons may be contacted at creativecommons.org.
|
PyPSA/source/LICENSES/MIT.txt
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) <year> <copyright holders>
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
| 6 |
+
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
| 7 |
+
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 8 |
+
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
| 9 |
+
following conditions:
|
| 10 |
+
|
| 11 |
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
| 12 |
+
portions of the Software.
|
| 13 |
+
|
| 14 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
| 15 |
+
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
| 16 |
+
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
| 17 |
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
| 18 |
+
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
PyPSA/source/MANIFEST.in
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
include pypsa/data/component_attrs/*.csv
|
| 6 |
+
include pypsa/data/standard_types/*.csv
|
| 7 |
+
include pypsa/data/components.csv
|
| 8 |
+
include pypsa/data/variables.csv
|
| 9 |
+
include README.rst LICENSE.txt
|
| 10 |
+
include requirements.yml
|
PyPSA/source/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!--
|
| 2 |
+
SPDX-FileCopyrightText: PyPSA Contributors
|
| 3 |
+
|
| 4 |
+
SPDX-License-Identifier: MIT
|
| 5 |
+
-->
|
| 6 |
+
|
| 7 |
+
<picture align="center">
|
| 8 |
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/PyPSA/PyPSA/refs/heads/master/docs/assets/logo/logo-primary-dark.svg">
|
| 9 |
+
<img alt="PyPSA Banner" src="https://raw.githubusercontent.com/PyPSA/PyPSA/refs/heads/master/docs/assets/logo/logo-primary-light.svg">
|
| 10 |
+
</picture>
|
| 11 |
+
|
| 12 |
+
# PyPSA - Python for Power System Analysis
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
[](https://pypi.python.org/pypi/pypsa)
|
| 16 |
+
[](https://anaconda.org/conda-forge/pypsa)
|
| 17 |
+

|
| 18 |
+
[](https://github.com/PyPSA/PyPSA/actions/workflows/test.yml)
|
| 19 |
+
[](https://docs.pypsa.org/latest/?badge=latest)
|
| 20 |
+
[](https://results.pre-commit.ci/latest/github/PyPSA/PyPSA/master)
|
| 21 |
+
[](https://codecov.io/gh/PyPSA/PyPSA)
|
| 22 |
+
[](https://api.reuse.software/info/github.com/pypsa/pypsa)
|
| 23 |
+
[](https://github.com/astral-sh/ruff)
|
| 24 |
+
[](LICENSE)
|
| 25 |
+
[](https://doi.org/10.5281/zenodo.3946412)
|
| 26 |
+
[](https://discord.gg/AnuJBk23FU)
|
| 27 |
+
[](CODE_OF_CONDUCT.md)
|
| 28 |
+
|
| 29 |
+
PyPSA stands for **Python for Power System Analysis**. It is pronounced
|
| 30 |
+
**pipes-ah**.
|
| 31 |
+
|
| 32 |
+
PyPSA is an open-source Python framework for optimising and simulating modern
|
| 33 |
+
power and energy systems that include features such as conventional generators
|
| 34 |
+
with unit commitment, variable wind and solar generation, hydro-electricity,
|
| 35 |
+
inter-temporal storage, coupling to other energy sectors, elastic demands, and
|
| 36 |
+
linearised power flow with loss approximations in DC and AC networks. PyPSA is
|
| 37 |
+
designed to scale well with large networks and long time series. It is made for
|
| 38 |
+
researchers, planners and utilities with basic coding aptitude who need a fast,
|
| 39 |
+
easy-to-use and transparent tool for power and energy system analysis.
|
| 40 |
+
|
| 41 |
+
PyPSA is maintained by the [Department of Digital Transformation in Energy
|
| 42 |
+
Systems](https://tu.berlin/en/ensys) at the [Technical University of
|
| 43 |
+
Berlin](https://www.tu.berlin). Previous versions were developed at the
|
| 44 |
+
[Karlsruhe Institute of Technology](http://www.kit.edu/english/index.php) funded
|
| 45 |
+
by the [Helmholtz Association](https://www.helmholtz.de/en/), and at
|
| 46 |
+
[FIAS](https://fias.uni-frankfurt.de/) funded by the [German Federal Ministry
|
| 47 |
+
for Education and Research (BMBF)](https://www.bmbf.de/bmbf/en/).
|
| 48 |
+
|
| 49 |
+
## Features
|
| 50 |
+
|
| 51 |
+
- **Economic Dispatch (ED):** Models short-term market-based dispatch including
|
| 52 |
+
unit commitment, renewable availability, short-duration and seasonal storage
|
| 53 |
+
including hydro reservoirs with inflow and spillage dynamics, elastic demands,
|
| 54 |
+
load shedding and conversion between energy carriers, using either perfect
|
| 55 |
+
operational foresight or rolling horizon time resolution.
|
| 56 |
+
|
| 57 |
+
- **Linear Optimal Power Flow (LOPF):** Extends economic dispatch to determine
|
| 58 |
+
the least-cost dispatch while respecting network constraints in meshed AC-DC
|
| 59 |
+
networks, using a linearised representation of power flow (KVL, KCL) with
|
| 60 |
+
optional loss approximations.
|
| 61 |
+
|
| 62 |
+
- **Security-Constrained LOPF (SCLOPF):** Extends LOPF by accounting for line
|
| 63 |
+
outage contingencies to ensure system reliability under $N-1$ conditions.
|
| 64 |
+
|
| 65 |
+
- **Capacity Expansion Planning (CEP):** Supports least-cost
|
| 66 |
+
long-term system planning with investment decisions for generation, storage,
|
| 67 |
+
conversion, and transmission infrastructure. Handles both single and multiple
|
| 68 |
+
investment periods. Continuous and discrete investments are supported.
|
| 69 |
+
|
| 70 |
+
- **Pathway Planning:** Supports co-optimisation of multiple investment periods to
|
| 71 |
+
plan energy system transitions over time with perfect planning foresight.
|
| 72 |
+
|
| 73 |
+
- **Stochastic Optimisation:** Implements two-stage stochastic programming
|
| 74 |
+
framework with scenario-weighted uncertain inputs, with investments as
|
| 75 |
+
first-stage decisions and dispatch as recourse decisions.
|
| 76 |
+
|
| 77 |
+
- **Modelling-to-Generate-Alternatives (MGA):** Explores near-optimal decision
|
| 78 |
+
spaces to provide insight into the range of feasible system configurations with
|
| 79 |
+
similar costs.
|
| 80 |
+
|
| 81 |
+
- **Sector-Coupling:** Modelling integrated energy systems with multiple energy
|
| 82 |
+
carriers (electricity, heat, hydrogen, etc.) and conversion between them.
|
| 83 |
+
Flexible representation of technologies such as heat pumps, electrolysers,
|
| 84 |
+
battery electric vehicles (BEVs), direct air capture (DAC), and synthetic
|
| 85 |
+
fuels production.
|
| 86 |
+
|
| 87 |
+
- **Static Power Flow Analysis:** Computes both full non-linear and linearised
|
| 88 |
+
load flows for meshed AC and DC grids using Newton-Raphson method.
|
| 89 |
+
|
| 90 |
+
## Documentation
|
| 91 |
+
|
| 92 |
+
PyPSA has extensive [documentation](https://docs.pypsa.org) with tutorials, user guides, examples and an API reference.
|
| 93 |
+
|
| 94 |
+
## Installation
|
| 95 |
+
|
| 96 |
+
pip:
|
| 97 |
+
|
| 98 |
+
``` bash
|
| 99 |
+
pip install pypsa
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
conda/mamba:
|
| 103 |
+
|
| 104 |
+
``` bash
|
| 105 |
+
conda install -c conda-forge pypsa
|
| 106 |
+
```
|
| 107 |
+
|
| 108 |
+
uv:
|
| 109 |
+
|
| 110 |
+
``` bash
|
| 111 |
+
uv add pypsa
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
## Usage
|
| 115 |
+
|
| 116 |
+
``` py
|
| 117 |
+
import pypsa
|
| 118 |
+
|
| 119 |
+
# create a new network
|
| 120 |
+
n = pypsa.Network()
|
| 121 |
+
n.add("Bus", "mybus")
|
| 122 |
+
n.add("Load", "myload", bus="mybus", p_set=100)
|
| 123 |
+
n.add("Generator", "mygen", bus="mybus", p_nom=100, marginal_cost=20)
|
| 124 |
+
|
| 125 |
+
# load an example network
|
| 126 |
+
n = pypsa.examples.ac_dc_meshed()
|
| 127 |
+
|
| 128 |
+
# run the optimisation
|
| 129 |
+
n.optimize()
|
| 130 |
+
|
| 131 |
+
# plot results
|
| 132 |
+
n.generators_t.p.plot()
|
| 133 |
+
n.plot()
|
| 134 |
+
|
| 135 |
+
# get statistics
|
| 136 |
+
n.statistics()
|
| 137 |
+
n.statistics.energy_balance()
|
| 138 |
+
```
|
| 139 |
+
|
| 140 |
+
## Dependencies
|
| 141 |
+
|
| 142 |
+
PyPSA relies heavily on other open-source Python packages. Some of them are:
|
| 143 |
+
|
| 144 |
+
* [pandas](http://pandas.pydata.org/) for storing data about components and time series
|
| 145 |
+
* [numpy](http://www.numpy.org/) and [scipy](http://scipy.org/) for linear algebra and matrix calculations
|
| 146 |
+
* [linopy](https://github.com/PyPSA/linopy) for preparing optimisation problems
|
| 147 |
+
* [matplotlib](https://matplotlib.org/), [seaborn](https://seaborn.pydata.org/) and [plotly](https://plotly.com/python/) for static and interactive plotting
|
| 148 |
+
* [networkx](https://networkx.github.io/) for network calculations
|
| 149 |
+
* [pytest](http://pytest.org/) for unit testing
|
| 150 |
+
|
| 151 |
+
Find the full list of dependencies in the [`pyproject.toml`](https://github.com/PyPSA/PyPSA/blob/master/pyproject.toml) file.
|
| 152 |
+
|
| 153 |
+
PyPSA can be used with different solvers. For instance, the free solvers
|
| 154 |
+
[HiGHS](https://highs.dev/) (installed by default), [GLPK](https://www.gnu.org/software/glpk/) and
|
| 155 |
+
[CBC](https://github.com/coin-or/Cbc/) or commercial solvers like
|
| 156 |
+
[Gurobi](http://www.gurobi.com/) or [FICO Xpress](https://www.fico.com/en/products/fico-xpress-optimization) for which free academic licenses are available.
|
| 157 |
+
|
| 158 |
+
## Contributing and Support
|
| 159 |
+
|
| 160 |
+
We strongly welcome anyone interested in contributing to this project. If you have any ideas, suggestions or encounter problems, feel invited to file issues or make pull requests on GitHub.
|
| 161 |
+
|
| 162 |
+
- To **discuss** with other PyPSA users, organise projects, share news, and get in touch with the community you can use the [Discord server](https://discord.gg/AnuJBk23FU).
|
| 163 |
+
- For **bugs and feature requests**, please [open an issue](https://github.com/PyPSA/PyPSA/issues).
|
| 164 |
+
- For **troubleshooting and support**, please check the [troubleshooting](https://docs.pypsa.org/latest/user-guide/support/) and [support](https://docs.pypsa.org/latest/user-guide/support/) sectionsin the documentation.
|
| 165 |
+
|
| 166 |
+
Detailed guidelines can be found in the [Contributing](https://docs.pypsa.org/latest/contributing/contributing/) guidelines of our documentation.
|
| 167 |
+
|
| 168 |
+
## Code of Conduct
|
| 169 |
+
|
| 170 |
+
Please respect our [Code of Conduct](https://docs.pypsa.org/latest/contributing/code-of-conduct/).
|
| 171 |
+
|
| 172 |
+
## Citing PyPSA
|
| 173 |
+
|
| 174 |
+
If you use PyPSA for your research, we would appreciate it if you would
|
| 175 |
+
cite the following paper:
|
| 176 |
+
|
| 177 |
+
- T. Brown, J. Hörsch, D. Schlachtberger, [PyPSA: Python for Power
|
| 178 |
+
System Analysis](https://arxiv.org/abs/1707.09913), 2018, [Journal
|
| 179 |
+
of Open Research
|
| 180 |
+
Software](https://openresearchsoftware.metajnl.com/), 6(1),
|
| 181 |
+
[arXiv:1707.09913](https://arxiv.org/abs/1707.09913),
|
| 182 |
+
[DOI:10.5334/jors.188](https://doi.org/10.5334/jors.188)
|
| 183 |
+
|
| 184 |
+
Please use the following BibTeX:
|
| 185 |
+
|
| 186 |
+
@article{PyPSA,
|
| 187 |
+
author = {T. Brown and J. H\"orsch and D. Schlachtberger},
|
| 188 |
+
title = {{PyPSA: Python for Power System Analysis}},
|
| 189 |
+
journal = {Journal of Open Research Software},
|
| 190 |
+
volume = {6},
|
| 191 |
+
issue = {1},
|
| 192 |
+
number = {4},
|
| 193 |
+
year = {2018},
|
| 194 |
+
eprint = {1707.09913},
|
| 195 |
+
url = {https://doi.org/10.5334/jors.188},
|
| 196 |
+
doi = {10.5334/jors.188}
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
If you want to cite a specific PyPSA version, each release of PyPSA is archived
|
| 200 |
+
on [Zenodo](https://zenodo.org/) with a release-specific DOI:
|
| 201 |
+
[](https://doi.org/10.5281/zenodo.3946412)
|
| 202 |
+
|
| 203 |
+
## Licence
|
| 204 |
+
|
| 205 |
+
Copyright [PyPSA Contributors](https://docs.pypsa.org/latest/developers.html)
|
| 206 |
+
|
| 207 |
+
PyPSA is licensed under the open source [MIT License](LICENSES/MIT.txt).
|
| 208 |
+
The documentation is licensed under [CC-BY-4.0](LICENSES/CC-BY-4.0.txt).
|
| 209 |
+
|
| 210 |
+
The repository uses [REUSE](https://reuse.software/) to expose the licenses of its files.
|
PyPSA/source/REUSE.toml
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version = 1
|
| 2 |
+
SPDX-PackageName = "PyPSA"
|
| 3 |
+
SPDX-PackageSupplier = "Tom Brown <t.brown@tu-berlin.de>"
|
| 4 |
+
SPDX-PackageDownloadLocation = "https://github.com/pypsa/pypsa"
|
| 5 |
+
|
| 6 |
+
[[annotations]]
|
| 7 |
+
# As an essential part of PyPSA package, these parts are licensed under the same MIT license as the code itself
|
| 8 |
+
path = [
|
| 9 |
+
".github/**/*.md",
|
| 10 |
+
"pypsa/data/component_attrs/*.csv",
|
| 11 |
+
"pypsa/data/standard_types/*.csv",
|
| 12 |
+
"pypsa/data/*.csv",
|
| 13 |
+
"test/baseline/*.png",
|
| 14 |
+
"test/data/**/*.csv",
|
| 15 |
+
"test/data/**/*.json",
|
| 16 |
+
"docs/requirements.txt",
|
| 17 |
+
]
|
| 18 |
+
SPDX-FileCopyrightText = "PyPSA Contributors"
|
| 19 |
+
SPDX-License-Identifier = "MIT"
|
| 20 |
+
|
| 21 |
+
[[annotations]]
|
| 22 |
+
# Data for examples, CC-BY-4.0 license for reuse by others
|
| 23 |
+
path = [
|
| 24 |
+
"examples/**.csv",
|
| 25 |
+
"examples/**.json",
|
| 26 |
+
"examples/**.nc",
|
| 27 |
+
]
|
| 28 |
+
SPDX-FileCopyrightText = "PyPSA Contributors"
|
| 29 |
+
SPDX-License-Identifier = "CC-BY-4.0"
|
| 30 |
+
|
| 31 |
+
[[annotations]]
|
| 32 |
+
# All documentation figures and notebooks (including their code) are for simplicity licensed under CC-BY-4.0
|
| 33 |
+
path = [
|
| 34 |
+
"docs/**/*.ipynb",
|
| 35 |
+
"docs/**/*.png",
|
| 36 |
+
"docs/**/*.html",
|
| 37 |
+
"docs/**/*.svg",
|
| 38 |
+
"docs/**/*.jpg",
|
| 39 |
+
]
|
| 40 |
+
SPDX-FileCopyrightText = "PyPSA Contributors"
|
| 41 |
+
SPDX-License-Identifier = "CC-BY-4.0"
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
[[annotations]]
|
| 45 |
+
# TODO find correct information for this external image
|
| 46 |
+
path = [
|
| 47 |
+
"docs/assets/images/reserve-power-funding.gif",
|
| 48 |
+
]
|
| 49 |
+
# We think this is the correct attribution (copyright holder and license)
|
| 50 |
+
SPDX-FileCopyrightText = "Ministry for Economic Affairs and Climate Action"
|
| 51 |
+
SPDX-License-Identifier = "CC-BY-4.0"
|
PyPSA/source/__init__.py
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""
|
| 3 |
+
PyPSA Project Package Initialization File
|
| 4 |
+
"""
|
PyPSA/source/codecov.yml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-FileCopyrightText: PyPSA Contributors
|
| 2 |
+
#
|
| 3 |
+
# SPDX-License-Identifier: MIT
|
| 4 |
+
|
| 5 |
+
comment: false
|
| 6 |
+
|
| 7 |
+
coverage:
|
| 8 |
+
status:
|
| 9 |
+
project:
|
| 10 |
+
default:
|
| 11 |
+
threshold: 0.1%
|
| 12 |
+
|
| 13 |
+
codecov:
|
| 14 |
+
notify:
|
| 15 |
+
after_n_builds: 13
|
PyPSA/source/docs/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!--
|
| 2 |
+
SPDX-FileCopyrightText: Organization for Ethical Source
|
| 3 |
+
SPDX-FileCopyrightText: PyPSA Contributors
|
| 4 |
+
|
| 5 |
+
SPDX-License-Identifier: CC-BY-4.0
|
| 6 |
+
-->
|
| 7 |
+
|
| 8 |
+
# Code of Conduct
|
| 9 |
+
|
| 10 |
+
!!! info
|
| 11 |
+
|
| 12 |
+
This Code of Conduct follows the [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
|
| 13 |
+
|
| 14 |
+
## Our Pledge
|
| 15 |
+
|
| 16 |
+
We as members, contributors, and leaders pledge to make participation in our
|
| 17 |
+
community a harassment-free experience for everyone, regardless of age, body
|
| 18 |
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
| 19 |
+
identity and expression, level of experience, education, socio-economic status,
|
| 20 |
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
| 21 |
+
identity and orientation.
|
| 22 |
+
|
| 23 |
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
| 24 |
+
diverse, inclusive, and healthy community.
|
| 25 |
+
|
| 26 |
+
## Our Standards
|
| 27 |
+
|
| 28 |
+
Examples of behavior that contributes to a positive environment for our
|
| 29 |
+
community include:
|
| 30 |
+
|
| 31 |
+
* Demonstrating empathy and kindness toward other people
|
| 32 |
+
* Being respectful of differing opinions, viewpoints, and experiences
|
| 33 |
+
* Giving and gracefully accepting constructive feedback
|
| 34 |
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
| 35 |
+
and learning from the experience
|
| 36 |
+
* Focusing on what is best not just for us as individuals, but for the overall
|
| 37 |
+
community
|
| 38 |
+
|
| 39 |
+
Examples of unacceptable behavior include:
|
| 40 |
+
|
| 41 |
+
* The use of sexualized language or imagery, and sexual attention or advances of
|
| 42 |
+
any kind
|
| 43 |
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
| 44 |
+
* Public or private harassment
|
| 45 |
+
* Publishing others' private information, such as a physical or email address,
|
| 46 |
+
without their explicit permission
|
| 47 |
+
* Other conduct which could reasonably be considered inappropriate in a
|
| 48 |
+
professional setting
|
| 49 |
+
|
| 50 |
+
## Enforcement Responsibilities
|
| 51 |
+
|
| 52 |
+
Community leaders are responsible for clarifying and enforcing our standards of
|
| 53 |
+
acceptable behavior and will take appropriate and fair corrective action in
|
| 54 |
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
| 55 |
+
or harmful.
|
| 56 |
+
|
| 57 |
+
Community leaders have the right and responsibility to remove, edit, or reject
|
| 58 |
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
| 59 |
+
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
| 60 |
+
decisions when appropriate.
|
| 61 |
+
|
| 62 |
+
## Scope
|
| 63 |
+
|
| 64 |
+
This Code of Conduct applies within all community spaces, and also applies when
|
| 65 |
+
an individual is officially representing the community in public spaces.
|
| 66 |
+
Examples of representing our community include using an official e-mail address,
|
| 67 |
+
posting via an official social media account, or acting as an appointed
|
| 68 |
+
representative at an online or offline event.
|
| 69 |
+
|
| 70 |
+
## Enforcement
|
| 71 |
+
|
| 72 |
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
| 73 |
+
reported to the community leaders responsible for enforcement at
|
| 74 |
+
f.neumann@tu-berlin.de / m.hofmann@tu-berlin.de / t.brown@tu-berlin.de.
|
| 75 |
+
All complaints will be reviewed and investigated promptly and fairly.
|
| 76 |
+
|
| 77 |
+
All community leaders are obligated to respect the privacy and security of the
|
| 78 |
+
reporter of any incident.
|
| 79 |
+
|
| 80 |
+
## Enforcement Guidelines
|
| 81 |
+
|
| 82 |
+
Community leaders will follow these Community Impact Guidelines in determining
|
| 83 |
+
the consequences for any action they deem in violation of this Code of Conduct:
|
| 84 |
+
|
| 85 |
+
### 1. Correction
|
| 86 |
+
|
| 87 |
+
**Community Impact**: Use of inappropriate language or other behavior deemed
|
| 88 |
+
unprofessional or unwelcome in the community.
|
| 89 |
+
|
| 90 |
+
**Consequence**: A private, written warning from community leaders, providing
|
| 91 |
+
clarity around the nature of the violation and an explanation of why the
|
| 92 |
+
behavior was inappropriate. A public apology may be requested.
|
| 93 |
+
|
| 94 |
+
### 2. Warning
|
| 95 |
+
|
| 96 |
+
**Community Impact**: A violation through a single incident or series of
|
| 97 |
+
actions.
|
| 98 |
+
|
| 99 |
+
**Consequence**: A warning with consequences for continued behavior. No
|
| 100 |
+
interaction with the people involved, including unsolicited interaction with
|
| 101 |
+
those enforcing the Code of Conduct, for a specified period of time. This
|
| 102 |
+
includes avoiding interactions in community spaces as well as external channels
|
| 103 |
+
like social media. Violating these terms may lead to a temporary or permanent
|
| 104 |
+
ban.
|
| 105 |
+
|
| 106 |
+
### 3. Temporary Ban
|
| 107 |
+
|
| 108 |
+
**Community Impact**: A serious violation of community standards, including
|
| 109 |
+
sustained inappropriate behavior.
|
| 110 |
+
|
| 111 |
+
**Consequence**: A temporary ban from any sort of interaction or public
|
| 112 |
+
communication with the community for a specified period of time. No public or
|
| 113 |
+
private interaction with the people involved, including unsolicited interaction
|
| 114 |
+
with those enforcing the Code of Conduct, is allowed during this period.
|
| 115 |
+
Violating these terms may lead to a permanent ban.
|
| 116 |
+
|
| 117 |
+
### 4. Permanent Ban
|
| 118 |
+
|
| 119 |
+
**Community Impact**: Demonstrating a pattern of violation of community
|
| 120 |
+
standards, including sustained inappropriate behavior, harassment of an
|
| 121 |
+
individual, or aggression toward or disparagement of classes of individuals.
|
| 122 |
+
|
| 123 |
+
**Consequence**: A permanent ban from any sort of public interaction within the
|
| 124 |
+
community.
|
| 125 |
+
|
| 126 |
+
## Attribution
|
| 127 |
+
|
| 128 |
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
| 129 |
+
version 2.1, available at
|
| 130 |
+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
| 131 |
+
|
| 132 |
+
Community Impact Guidelines were inspired by
|
| 133 |
+
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
| 134 |
+
|
| 135 |
+
For answers to common questions about this code of conduct, see the FAQ at
|
| 136 |
+
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
| 137 |
+
[https://www.contributor-covenant.org/translations][translations].
|
| 138 |
+
|
| 139 |
+
[homepage]: https://www.contributor-covenant.org
|
| 140 |
+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
| 141 |
+
[Mozilla CoC]: https://github.com/mozilla/diversity
|
| 142 |
+
[FAQ]: https://www.contributor-covenant.org/faq
|
| 143 |
+
[translations]: https://www.contributor-covenant.org/translations
|
PyPSA/source/docs/api/components/common.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!--
|
| 2 |
+
SPDX-FileCopyrightText: PyPSA Contributors
|
| 3 |
+
|
| 4 |
+
SPDX-License-Identifier: CC-BY-4.0
|
| 5 |
+
-->
|
| 6 |
+
|
| 7 |
+
::: pypsa.components.common
|
PyPSA/source/docs/api/components/components.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!--
|
| 2 |
+
SPDX-FileCopyrightText: PyPSA Contributors
|
| 3 |
+
|
| 4 |
+
SPDX-License-Identifier: CC-BY-4.0
|
| 5 |
+
-->
|
| 6 |
+
|
| 7 |
+
::: pypsa.components.Components
|
| 8 |
+
options:
|
| 9 |
+
heading_level: 2
|
| 10 |
+
members_order: source
|
| 11 |
+
inherited_members: true
|
| 12 |
+
filters:
|
| 13 |
+
- "!^_[^_]"
|
| 14 |
+
- "!logger"
|
| 15 |
+
- "!iteration"
|
| 16 |
+
- "!__deepcopy__"
|
| 17 |
+
- "!__getitem__"
|
| 18 |
+
- "!__setitem__"
|
| 19 |
+
- "!add"
|
| 20 |
+
- "!get_bounds_pu"
|
| 21 |
+
|
| 22 |
+
::: pypsa.components.components.ComponentsData
|
| 23 |
+
options:
|
| 24 |
+
heading_level: 2
|
PyPSA/source/docs/api/components/types/buses.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!--
|
| 2 |
+
SPDX-FileCopyrightText: PyPSA Contributors
|
| 3 |
+
|
| 4 |
+
SPDX-License-Identifier: CC-BY-4.0
|
| 5 |
+
-->
|
| 6 |
+
|
| 7 |
+
::: pypsa.components.Buses
|
PyPSA/source/docs/api/components/types/carriers.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!--
|
| 2 |
+
SPDX-FileCopyrightText: PyPSA Contributors
|
| 3 |
+
|
| 4 |
+
SPDX-License-Identifier: CC-BY-4.0
|
| 5 |
+
-->
|
| 6 |
+
|
| 7 |
+
::: pypsa.components.Carriers
|
PyPSA/source/docs/api/components/types/generators.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!--
|
| 2 |
+
SPDX-FileCopyrightText: PyPSA Contributors
|
| 3 |
+
|
| 4 |
+
SPDX-License-Identifier: CC-BY-4.0
|
| 5 |
+
-->
|
| 6 |
+
|
| 7 |
+
::: pypsa.components.Generators
|
PyPSA/source/docs/api/components/types/global-constraints.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!--
|
| 2 |
+
SPDX-FileCopyrightText: PyPSA Contributors
|
| 3 |
+
|
| 4 |
+
SPDX-License-Identifier: CC-BY-4.0
|
| 5 |
+
-->
|
| 6 |
+
|
| 7 |
+
::: pypsa.components.GlobalConstraints
|
PyPSA/source/docs/api/components/types/lines.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!--
|
| 2 |
+
SPDX-FileCopyrightText: PyPSA Contributors
|
| 3 |
+
|
| 4 |
+
SPDX-License-Identifier: CC-BY-4.0
|
| 5 |
+
-->
|
| 6 |
+
|
| 7 |
+
::: pypsa.components.Lines
|
| 8 |
+
options:
|
| 9 |
+
heading_level: 2
|
| 10 |
+
|
| 11 |
+
::: pypsa.components.LineTypes
|
| 12 |
+
options:
|
| 13 |
+
heading_level: 2
|