{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "id": "g5M6M93v1Vlj" }, "outputs": [], "source": [ "# Instalación de la librería Pyomo\n", "! pip install pyomo\n" ] }, { "cell_type": "code", "source": [ " # Instalación del \"open source solver glpk\"\n", "!apt install glpk-utils\n", "!pip install glpk" ], "metadata": { "id": "MfRVb4Map8ZW" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "F4KwDZmy2F4t" }, "outputs": [], "source": [ "!pip list" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "akB94YgO2TJQ" }, "outputs": [], "source": [ "!pyomo --version\n", "!pyomo --help" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "qWqxpWVW2i8o" }, "outputs": [], "source": [ "!glpsol --version\n", "!glpsol --help" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "qk6MrrdD2rKM" }, "outputs": [], "source": [ "#importar librerias\n", "\n", "import pandas as pd #manejo de datos\n", "from pyomo.environ import *\n", "# import pyomo.environ as pyo\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "owRzvctg29XU" }, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.cm as cm\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Z3RNfecW35hR" }, "outputs": [], "source": [ "! pyomo help --data-managers" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "hOx7w7YY3hVf" }, "outputs": [], "source": [ "## crear instancia del modelo\n", "#Montar drive\n", "from google.colab import drive\n", "drive.mount('/content/drive')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "bgdbOFHS4UbZ" }, "outputs": [], "source": [ "!pyomo help --solvers" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "3mtCM4p04tlw" }, "outputs": [], "source": [ "###Crear modelo\n", "model = ConcreteModel()\n", "\n", "# Cargar datos de Excel\n", "df_perfiles=pd.read_excel(\"/content/drive/MyDrive/ColabCurso/250613Pot.xlsx\",sheet_name='Hoja1',header=0,index_col=0)\n", "\n", "\n", "\n", "###Crear conjuntos (Sets)\n", "T=df_perfiles.index.tolist()#Tiempo\n", "\n", "model.T=Set(initialize=T, ordered=True)\n" ] }, { "cell_type": "markdown", "source": [ "# New Section" ], "metadata": { "id": "ZBYudgWTsKY-" } }, { "cell_type": "markdown", "source": [ "# New Section" ], "metadata": { "id": "dGmLej2ssK9K" } }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "wEK37zLta_8H" }, "outputs": [], "source": [ "x=list(range(0, 25 ))\n", "\n", "PV_print=df_perfiles.P_PV.tolist()\n", "PV_print.insert(0, PV_print[0])\n", "\n", "PL_print=df_perfiles.P_Load.tolist()\n", "PL_print.insert(0, PL_print[0])\n", "\n", "plt.figure(figsize=(7,3));\n", "plt.step(x, PV_print, 'b', label='Generación Fotovoltaica');\n", "plt.step(x, PL_print, 'r', label='Perfil de Carga');\n", "\n", "plt.xlabel('Tiempo [h]')\n", "plt.ylabel('Potencia [kW]')\n", "plt.xticks(x)\n", "plt.yticks(np.arange(0, 1.2, step=0.2))\n", "\n", "plt.legend()\n", "plt.grid()\n", "plt.show()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "aI3t2lgPsvWD" }, "outputs": [], "source": [ "CP_print=df_perfiles.Tarifa_CP.tolist()\n", "CP_print.insert(0, CP_print[0])\n", "CP_print.insert(0, CP_print[0])\n", "\n", "TOU_print=df_perfiles.Tarifa_TOU.tolist()\n", "TOU_print.insert(0, TOU_print[0])\n", "TOU_print.insert(0, TOU_print[0])\n", "\n", "plt.figure(figsize=(7,3));\n", "plt.step(CP_print, 'y', label='Tarifa Constante (CP)');\n", "plt.step(TOU_print, 'b', label='Tarifa Tiempo de Uso (ToU)');\n", "\n", "plt.xlabel('Tiempo [h]')\n", "plt.ylabel('Costo normalizado')\n", "\n", "plt.yticks(np.arange(0, 1.3, step=0.2))\n", "\n", "plt.legend()\n", "plt.grid()\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "rv8mttqP7G_f" }, "outputs": [], "source": [ "#####Parametros\n", "\n", "Delta_t=1\n", "\n", "#####Parametros de la red\n", "Predabs_max=5 #kW\n", "Prediny_max=5 #kW\n", "\n", "## Parámetros del ESS\n", "Vbatt=48*14; # Banco de baterias\n", "CapAh=5;\n", "CapkWh=Vbatt*CapAh/1000\n", "PESScargamax=0.6; #Potencia Maxima de carga\n", "PESSdescmax=2;\n", "SoC0=0.5;\n", "SoCmax=0.90;\n", "SoCmin=0.20;\n", "Eff_dcg=0.98;\n", "Eff_cg=0.95;" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "zeBKWyhk7Zx9" }, "outputs": [], "source": [ "#####Variables\n", "###Positivas\n", "\n", "model.Prediny = Var(model.T, domain=NonNegativeReals,bounds=(0,Prediny_max)) #Inyección de potencia\n", "model.Predabs = Var(model.T, domain=NonNegativeReals,bounds=(0,Predabs_max)) #Absorción de potencia\n", "model.PESSdesc = Var(model.T, domain=NonNegativeReals,bounds=(0,PESSdescmax)) #Potencia descarga ESS\n", "model.PESScarga = Var(model.T, domain=NonNegativeReals,bounds=(0,PESScargamax)) #Potencia carga ESS\n", "model.SOC= Var(model.T, domain=NonNegativeReals,bounds=(SoCmin,SoCmax)) #Estado de Carga ESS\n", "\n", "#Variables binarias/Toma de decisiones logicas (0,1) para carga/descarga\n", "model.xESS = Var(model.T,within=Binary)" ] }, { "cell_type": "code", "source": [ "from google.colab import drive\n", "drive.mount('/content/drive')" ], "metadata": { "id": "BKr4WXr-Dynk" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "f-E07Oj88QWh" }, "outputs": [], "source": [ "#Función objetivo Eq1\n", "def obj_rule(model):#regla(Función python)\n", " #return sum(df_perfiles.Tarifa_CP[t]*model.Predabs[t] for t in T)\n", " return sum(df_perfiles.Tarifa_TOU[t]*model.Predabs[t] for t in T)\n", "model.Obj=Objective(rule=obj_rule,sense=minimize)#mininizar función" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "uEO_6cUy_Jyq" }, "outputs": [], "source": [ "# Restricciones\n", "#Balance de energia electrica\n", "def Elec_rule(model,t):#t para todo t en T\n", " return df_perfiles.P_PV[t]+model.Predabs[t]-model.Prediny[t]+model.PESSdesc[t]-model.PESScarga[t]==df_perfiles.P_Load[t]\n", "\n", "model.Balance=Constraint(model.T,rule=Elec_rule)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Ix95dJB4_OPG" }, "outputs": [], "source": [ "#ESS\n", "\n", "def SOC_rule(model,t):\n", " if t==1:\n", " return model.SOC[t]==SoC0+Eff_cg*(model.PESScarga[t]*Delta_t)/CapkWh-(model.PESSdesc[t]*Delta_t)/(Eff_dcg*CapkWh)\n", " else:\n", " return model.SOC[t]==model.SOC[t-1]+Eff_cg/CapkWh*model.PESScarga[t]*Delta_t-model.PESSdesc[t]*Delta_t/(Eff_dcg*CapkWh)\n", "model.ResSOC=Constraint(model.T,rule=SOC_rule)\n", "\n", "# Límites de carga y descarga\n", "def c_lim_rule(model,t):\n", " return model.PESScarga[t]<=PESScargamax*model.xESS[t]\n", "model.ESScarga_lim=Constraint(T,rule=c_lim_rule)\n", "\n", "def d_lim_rule(model,t):\n", " return model.PESSdesc[t]<=PESSdescmax*(1-model.xESS[t])\n", "model.d_lim=Constraint(T,rule=d_lim_rule)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ez1v30kS_VW6" }, "outputs": [], "source": [ "#Acceder a opciones del solver\n", "\n", "###Solution / Imprimir resultados#####\n", "def pyomo_postprocess(options=None, instance=None, results=None):\n", " results.write()\n", " model.Obj.display()\n", " model.Predabs.display()\n", " # model.Pes.display()\n", " # model.Pg_chp.display()\n", " # model.Pg_f.display()\n", " # model.Pc.display()\n", " # model.Pd.display()\n", "if __name__ == '__main__':\n", " # resolver y verificar el estado del solver/solucionador\n", " results=SolverFactory('glpk').solve(model)\n", " # results=SolverManagerFactory('neos').solve(model, opt='cplex')\n", "\n", " ### Resolver el modelo de optimización con CPLEX en NEOS\n", " #import os\n", " # provide an email address\n", " #os.environ['NEOS_EMAIL'] = 'aclunah@gmail.com'\n", " # solve optimization model\n", " #results=SolverManagerFactory('neos').solve(model, opt='cplex',tee=True)\n", "\n", " #Estado del solucionador\n", " print (\"El solucionador devolvió un estado de:\"+str(results.solver.status))\n", " if (results.solver.status == SolverStatus.ok) and (results.solver.termination_condition == TerminationCondition.optimal):\n", " print (\"El problema es factible y óptimo\")\n", " elif results.solver.termination_condition == TerminationCondition.infeasible:\n", " print (\"Hacer algo al respecto ? o salir\")\n", " else:\n", " # something else is wrong\n", " print (str(results.solver))\n", " print(\"\\nMostrar solución\\n\" + '-'*60)\n", " pyomo_postprocess(None, model, results)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "zNS23_2a_qky" }, "outputs": [], "source": [ "#Imprimir resultados\n", "\n", "#tipo de elementos pyomo\n", "print(type(model.Predabs))\n", "print(type(model.Obj))\n", "#### Graficar resultados\n", "E_compra=[model.Predabs[t].value for t in T]\n", "E_compra.insert(0, E_compra[0]) # Para graficar desde 0\n", "E_venta=[model.Prediny[t].value for t in T]\n", "E_venta.insert(0, E_venta[0]) # Para graficar desde 0\n", "PESSc=[model.PESScarga[t].value for t in T]\n", "PESSc.insert(0, PESSc[0]) # Para graficar desde 0\n", "PESSdc=[-1*model.PESSdesc[t].value for t in T]\n", "PESSdc.insert(0, PESSdc[0]) # Para graficar desde 0\n", "E3=[model.SOC[t].value for t in T]\n", "E3.insert(0, SoC0) # Para graficar desde 0\n", "\n", "xESSp=[model.xESS[t].value for t in T]\n", "xESSp.insert(0, xESSp[0]) # Para graficar desde 0\n", "\n", "\n", "print(E_compra)\n", "print(E_venta)\n", "print(type(E_compra))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "D2OmyoyPo_l6" }, "outputs": [], "source": [ "x=list(range(0, 25 ))\n", "fig = plt.figure(figsize=(7,3))\n", "plt.step(x,E_compra,'b',label='P absorbida de la red')\n", "plt.step(x,E_venta,'r',label='P inyectada a la red')\n", "plt.xlabel('Tiempo [h]')\n", "plt.ylabel('Potencia [kW]')\n", "plt.xticks(x)\n", "plt.legend()\n", "plt.grid()\n", "plt.show()\n", "fig.savefig('grid_exchange') # save the figure to file\n", "plt.close(fig)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "K7bETszhjS9x" }, "outputs": [], "source": [ "x=list(range(0, 25 ))\n", "fig = plt.figure(figsize=(7,3))\n", "plt.step(x,PESSc,'b',label='Cargando')\n", "plt.step(x,PESSdc,'r',label='Descargando')\n", "plt.xlabel('Tiempo [h]')\n", "plt.ylabel('Potencia [kW]')\n", "plt.xticks(x)\n", "plt.legend()\n", "plt.grid()\n", "plt.show()\n", "fig.savefig('grid_exchange') # save the figure to file\n", "plt.close(fig)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "jKTAEjMJAKYV" }, "outputs": [], "source": [ "x=list(range(0, 25 ))\n", "fig = plt.figure(figsize=(7,3))\n", "plt.step(x,xESSp,'b',label='xESS (1-carga, 0-descarga)')\n", "#plt.step(x,E_venta,'r',label='Venta')\n", "plt.xlabel('Tiempo [h]')\n", "plt.ylabel('xESS')\n", "plt.xticks(x)\n", "plt.legend()\n", "plt.grid()\n", "plt.show()\n", "fig.savefig('xESS') # save the figure to file\n", "plt.close(fig)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Rb-Sj20ph5bs" }, "outputs": [], "source": [ "x=list(range(0, 25 ));\n", "fig = plt.figure(figsize=(7,3));\n", "plt.plot(x,E3,'-ob',label='SoC');\n", "plt.xlabel('Tiempo [h]')\n", "plt.ylabel('Estado de Carga')\n", "plt.xticks(x)\n", "plt.yticks(np.arange(0.1, 1, step=0.1))\n", "plt.legend()\n", "plt.grid()\n", "plt.show()\n", "fig.savefig('grid_exchange') # save the figure to file\n", "plt.close(fig)" ] } ], "metadata": { "colab": { "provenance": [] }, "kernelspec": { "display_name": "Python 3", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 0 }