Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: script for generating pv module coefficients #11

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.ipynb_checkpoints
.pytest_cache
.venv
*.xlsx
result.csv
*.zip
.idea
*.log
*.pyc

10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
# pvmodules
Code to generate parameters for PV module models


## Develop
Install dependencies:`poetry install`

Run tests: `pytest test`


## Run PV parameter generation
`python pvmodules/cec_pv_modules.py <CEC-dataset-path>.xlsx <output-path>.csv <number of processes>`
224 changes: 224 additions & 0 deletions convert-cec-inverters-to-sam.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 47,
"id": "c015bfe7",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"from PySAM.InvCecCg import new as InvCecCg\n",
"from itertools import product\n",
"from pvlib.inverter import fit_sandia"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "a6c92a2e",
"metadata": {},
"outputs": [],
"source": [
"inverter_columns = ['Name', 'Vac', 'Pso', 'Paco', 'Pdco', 'Vdco', 'C0', 'C1', 'C2', 'C3',\n",
" 'Pnt', 'Vdcmax', 'Idcmax', 'Mppt_low', 'Mppt_high', 'CEC_Date',\n",
" 'CEC_Type', 'CEC_hybrid']"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "1e1b9bcf",
"metadata": {},
"outputs": [],
"source": [
"cec_inverters = pd.read_excel('/home/allen/Downloads/Grid_Support_Inverter_List_Full_Data_ADA.xlsm',\n",
" engine='openpyxl', skiprows=[*range(14), 15], usecols=range(60))"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "8ae10c60",
"metadata": {},
"outputs": [],
"source": [
"cec_inverters['Name'] = cec_inverters.apply(lambda row: f\"{row['Manufacturer Name']} {row['Model Number1']}\", axis=1)"
]
},
{
"cell_type": "code",
"execution_count": 56,
"id": "5489c7ec",
"metadata": {},
"outputs": [],
"source": [
"inverter = cec_inverters.loc[cec_inverters['Model Number1'].str.contains('PV4400')].squeeze()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "25dd3ca2",
"metadata": {},
"outputs": [],
"source": [
"voltages = [k for k in cec_inverters.columns if k.startswith('Voltage ')]\n",
"\n",
"powers = [k for k in cec_inverters.columns if k.startswith('Power Level')]\n",
"\n",
"efficiencies = [k for k in cec_inverters.columns if k.startswith('Efficiency @V') and '6' not in k]"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "fcaaa574",
"metadata": {},
"outputs": [],
"source": [
"curve_keys = [[*v_p, e] for v_p, e in zip(product(voltages, powers), efficiencies)]\n",
"curve_keys = [[p, v, e] for v, p, e in curve_keys]"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "7a9d8d40",
"metadata": {},
"outputs": [],
"source": [
"def get_curve_pvlib(inverter: pd.Series):\n",
" curve = pd.DataFrame(columns=['Pac', 'Vdc', 'Eff'], data=[[inverter[k] for k in row] for row in curve_keys])\n",
"\n",
" curve['Eff'] *= 1e-2\n",
"\n",
" curve['Pdc'] = curve['Pac'] / curve['Eff']\n",
" curve['Vlvl'] = curve['Vdc'].replace(\n",
" curve['Vdc'].min(), 'Vmin').replace(\n",
" curve['Vdc'].median(), 'Vnom').replace(\n",
" curve['Vdc'].max(), 'Vmax')\n",
" return curve\n",
" \n",
" \n",
"\n",
"def get_params_pvlib(inverter: pd.Series):\n",
" curve = get_curve(inverter)\n",
" return fit_sandia(\n",
" ac_power=curve['Pac'] * 1e3,\n",
" dc_power=curve['Pdc'] * 1e3,\n",
" dc_voltage=curve['Vdc'],\n",
" dc_voltage_level=curve['Vlvl'],\n",
" p_ac_0=inverter['Maximum Continuous Output Power at Unity Power Factor'] * 1e3,\n",
" p_nt=inverter['Night Tare Loss'],\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 50,
"id": "0ce11459",
"metadata": {},
"outputs": [],
"source": [
"def get_params_sam(inverter: pd.Series):\n",
" curve = [[inverter[k] for k in row] for row in curve_keys]\n",
" solver = InvCecCg()\n",
"\n",
" solver.Common.assign({\n",
" 'inv_cec_cg_paco': inverter['Maximum Continuous Output Power at Unity Power Factor'] * 1e3,\n",
" 'inv_cec_cg_sample_power_units': 1,\n",
" 'inv_cec_cg_test_samples': curve\n",
" })\n",
"\n",
" solver.execute()\n",
" return {\n",
" k: v\n",
" for k, v in solver.export()['Outputs'].items()\n",
" if k in {'Pdco', 'Pso', 'Vdco', 'c0', 'c1', 'c2', 'c3'}\n",
" }"
]
},
{
"cell_type": "code",
"execution_count": 102,
"id": "776e4d41",
"metadata": {},
"outputs": [],
"source": [
"def cec_row_to_sam_row(cec_row: pd.Series, get_params) -> pd.Series:\n",
" params = get_params(cec_row)\n",
" return pd.Series({\n",
" 'Name': f\"{cec_row['Manufacturer Name']} {cec_row['Model Number1']}\",\n",
" 'Vac': cec_row['Nominal Voltage'],\n",
" 'Vdco': cec_row['Voltage Nominal'],\n",
" 'Vdcmax': cec_row['Voltage Maximum'],\n",
" 'Pnt': cec_row['Night Tare Loss'],\n",
" 'Paco': cec_row['Maximum Continuous Output Power at Unity Power Factor'] * 1e3,\n",
" 'Pdco': params['Pdco'],\n",
" 'Pso': params['Pso'],\n",
" 'C0': params['c0'],\n",
" 'C1': params['c1'],\n",
" 'C2': params['c2'],\n",
" 'C3': params['c3'],\n",
" 'Idcmax': params['Pdco'] / params['Vdco'],\n",
" 'Mppt_low': cec_row['Voltage Minimum'],\n",
" 'Mppt_high': cec_row['Voltage Maximum'],\n",
" 'CEC_Date': inverter['Grid Support Listing Date'].date().isoformat(), # TODO: or latest update\n",
" 'CEC_Type': 'Grid Support',\n",
" 'CEC_hybrid': 'N'\n",
" })[inverter_columns]\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 103,
"id": "2d2105c2",
"metadata": {},
"outputs": [],
"source": [
"sam_inverter = cec_row_to_sam_row(inverter, get_params_sam)"
]
},
{
"cell_type": "code",
"execution_count": 104,
"id": "543b32d2",
"metadata": {},
"outputs": [],
"source": [
"sam_inverter.to_frame().transpose().to_csv('production/nrel_sam/CEC_Inverters.csv', mode='a', header=False, index=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7fec9c48",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading