from __future__ import division import logging import traceback from os import path import sys import pandas as pd import pyutilib.subprocess.GlobalData from numpy import array, zeros from pandas import DataFrame, ExcelWriter from pyomo.environ import * from pyomo.environ import SolverFactory from pyomo.kernel import value from common.data import APPDIRS from mct.makeMCT import linmct, readmct, set_dir_flujo from red.orderC import nodec from red.create import * from red.create1 import * from red.makeBdc import makeBdc from red.read import excel2net from utils.arr2dict import arr2dict pyutilib.subprocess.GlobalData.DEFINE_SIGNAL_HANDLERS_DEFAULT = False logger = logging.getLogger('spr.run.modelo') def setmodel(file, p_exec, all_day=True): # Determinar si se ejecuta todo el día o solo un período en específico if all_day: min = 0 max = p_exec + 1 logger.info("Se ejecuta el Modelo de Predespacho para las 24 horas") else: min = p_exec max = p_exec + 1 logger.info( "Se ejecuta el Modelo de Predespacho para la hora {}".format(p_exec)) logger.info("Modelo de Predespacho Regional") logger.info("Mercados Eléctricos de Centroamérica (c) 2020") # ============================================================================ # Importación de datos desde archivo Excel # ============================================================================ # Parametros de la linea logger.info("Inicio Predespacho Regional") logger.info("Leyendo información de RTR...") net_t = excel2net(file) dirf = set_dir_flujo() mct = readmct(file) # Informacion de los despachos nacionales dg_t = read_D_G(file) # Ofertas de todos los periodos ex_cnfff_t = readofertas_cnfffs(file) ex_ooi_t = readofertas_oois(file) ex_oor_t = readofertas_oors(file) ex_cf_t = readofertas_cfs(file) # Dataframe para almacenar la informacion de cada predespacho flujos_t = DataFrame() iep_t = DataFrame() pon_t = DataFrame() result_foo_i_t = DataFrame() result_foo_r_t = DataFrame() result_fof_t = DataFrame() result_foff_t = DataFrame() # El range del for se modifica dependiendo los periodos que se quieren correr. for PERIODO in range(min, max): logger.info("Inicio de la ejecución para el periodo {}".format(PERIODO)) net=net_t[net_t.periodo.isin([PERIODO])].copy() net.reset_index(drop=True, inplace=True) net.drop(['periodo'], axis='columns', inplace=True) bus = setbus(net)#Nodos branch = setbranch(net, bus)#Set lineas bu = branch[:, 5]#potenica max de la linea bl = branch[:, 6]#potenica min de la linea xc = branch[:,3]#Reactancia de la linea rc = branch[:,4]#Resistencia de la linea nb = bus.shape[0] #Numero de nodos nbr = branch.shape[0]#Numero de lineas A = makeBdc(bus, branch)#Matriz incidente brnames = branchnames(bus, branch)#Nombre de las lineas inc = A.toarray()*-1 # Lineas para límites de MCT br_t = brnames['Total'].to_numpy() lin_mct = linmct(br_t) logger.info("Leyendo información de los despacho nacionales.") # Dependiendo de los valores de la columna periodo del df son los valores que toma dg = dg_t[dg_t.periodo.isin([PERIODO])] # Resetea valores de ordenamiento del DF dg.reset_index(drop=True, inplace=True) # Ordena los valores que tiene segun los nodos de rtr dg_n = set_dgnacional(bus, dg) logger.info("Leyendo información de ofertas.") # Funcion leer contratos no firmes fisicos flexibles # Dependiendo de los valores de la columna periodo del df son los valores que toma ex_cnfff = ex_cnfff_t[ex_cnfff_t.periodo.isin([PERIODO])] # Resetea valores de ordenamiento del DF ex_cnfff.reset_index(drop=True, inplace=True) # Energia declarada con respecto al nodo vnfff_ed = setvariable(ex_cnfff['energía_dec']) # Magnitud de energia ofertada -flexibilizacion vnfff_m_i = setvariable_s( ex_cnfff[['magnitud_i1', 'magnitud_i2', 'magnitud_i3', 'magnitud_i4', 'magnitud_i5']]) vnfff_m_r = setvariable_s( ex_cnfff[['magnitud_r1', 'magnitud_r2', 'magnitud_r3', 'magnitud_r4', 'magnitud_r5']]) vnfff_m_cvt = setvariable_s( ex_cnfff[['magnitud_cvt1', 'magnitud_cvt2', 'magnitud_cvt3', 'magnitud_cvt4', 'magnitud_cvt5']]) # Precio de la ofertas de inyeccion p_cnfffi = setvariable_s( ex_cnfff[['precio_i1', 'precio_i2', 'precio_i3', 'precio_i4', 'precio_i5']]) # Precio de la ofertas de retiro p_cnfffr = setvariable_s( ex_cnfff[['precio_r1', 'precio_r2', 'precio_r3', 'precio_r4', 'precio_r5']]) # Precio de la ofertas de inyeccion p_cnfffcvt = setvariable_s( ex_cnfff[['precio_cvt1', 'precio_cvt2', 'precio_cvt3', 'precio_cvt4', 'precio_cvt5']]) # Precio de la ofertas de inyeccion k_cnfffcvt = setvariable(ex_cnfff['k']) NCFF = ex_cnfff.shape[0] # Numero de contratos firmes var_bin_cnfffr = MATRIZ_VNFFF_R(bus, ex_cnfff) var_bin_cnfffi = MATRIZ_VNFFF_I(bus, ex_cnfff) dem = setvariable(dg_n['Demanda']) gen = setvariable(dg_n['Generacion']) # Funcion leer parametros oferta de oportunidad inyeccion # Dependiendo de los valores de la columna periodo del df son los valores que toma ex_ooi = ex_ooi_t[ex_ooi_t.periodo.isin([PERIODO])] # Resetea valores de ordenamiento del DF ex_ooi.reset_index(drop=True, inplace=True) vooi_m = setvariable_s(ex_ooi[['magnitud_ooi1', 'magnitud_ooi2', 'magnitud_ooi3', 'magnitud_ooi4', 'magnitud_ooi5']]) # Ofertas con respecto al nodo p_ooi = setvariable_s(ex_ooi[['precio_ooi1', 'precio_ooi2', 'precio_ooi3', 'precio_ooi4', 'precio_ooi5']]) # Precio de la ofertas NOI = ex_ooi.shape[0] # Numero de ofertas de inyeccion var_bin_ooi = MATRIZ_OOI(bus, ex_ooi) # Funcion leer parametros oferta de oportunidad retiro ex_oor = ex_oor_t[ex_oor_t.periodo.isin([PERIODO])] # Resetea valores de ordenamiento del DF ex_oor.reset_index(drop=True, inplace=True) voor_m = setvariable_s(ex_oor[['magnitud_oor1', 'magnitud_oor2', 'magnitud_oor3', 'magnitud_oor4', 'magnitud_oor5']]) # Ofertas con respecto al nodo # Precio de la ofertas - flexibilizacion p_oor = setvariable_s( ex_oor[['precio_oor1', 'precio_oor2', 'precio_oor3', 'precio_oor4', 'precio_oor5']]) NOR = ex_oor.shape[0] # Numero de ofertas de retiro var_bin_oor = MATRIZ_OOR(bus, ex_oor) # Funcion leer parametros contratos firmes # Dependiendo de los valores de la columna periodo del df son los valores que toma ex_cf = ex_cf_t[ex_cf_t.periodo.isin([PERIODO])] # Resetea valores de ordenamiento del DF ex_cf.reset_index(drop=True, inplace=True) # Energia declarada con respecto al nodo vcf_ed = setvariable(ex_cf['energía_dec']) # Potencia requerida con respecto al nodo vcf_pr = setvariable(ex_cf['potencia_req']) # Magnitud de energia ofertada -flexibilizacion vcf_m = setvariable_s( ex_cf[['magnitu_cf1', 'magnitu_cf2', 'magnitu_cf3', 'magnitu_cf4', 'magnitu_cf5']]) # Precio de la ofertas vcf_p = setvariable_s( ex_cf[['precio_cf1', 'precio_cf2', 'precio_cf3', 'precio_cf4', 'precio_cf5']]) NCF = ex_cf.shape[0] # Numero de contratos firmes var_bin_cfr = MATRIZ_CFR(bus, ex_cf) var_bin_cfi = MATRIZ_CFI(bus, ex_cf) # Inicio del modelo de optimización model = ConcreteModel() # sets model.i = Set(initialize=range(0, nb)) # numero de nodos model.c = Set(initialize=range(0, nbr)) # Numero de lineas # numero de ofertas de oportuniddad retiro model.OR = Set(initialize=range(0, NOR)) # numero de ofertas de oportunidad inyeccion model.OI = Set(initialize=range(0, NOI)) # numero de ofertas de CNFFF model.CFF = Set(initialize=range(0, NCFF)) # numero de ofertas de contratos firmes model.CF = Set(initialize=range(0, NCF)) model.s = Set(initialize=range(0, 5)) # Numero de bloques model.inter = Set(initialize=lin_mct.keys()) # Interconexiones # Sentidos de interconexiones model.sen = Set(initialize=['sn', 'ns']) model.per = Set(initialize=range(0, 24)) # numero de periodos # Parametros # Parametros de la red model.rtmw_min = Param(model.c, initialize=dict(enumerate(bl))) model.rtmw_max = Param(model.c, initialize=dict(enumerate(bu))) model.Inc = Param(model.c, model.i, initialize=arr2dict(inc)) model.Xc = Param(model.c, initialize=dict(enumerate(xc))) model.Rc = Param(model.c, initialize=dict(enumerate(rc))) # Parametros de los predespachos nacionales model.D = Param(model.i, initialize=dict(enumerate(dem))) model.G = Param(model.i, initialize=dict(enumerate(gen))) # Ofertas de oportunidad # Oferta de oportunidad de retiro # Oferta bloques 1 model.fr = Param(model.OR, model.s, initialize=arr2dict(p_oor)) model.pr_ofertado = Param(model.OR, model.s, initialize=arr2dict( voor_m)) # Magnitud de la oferta MW-h model.bin_pr = Param( model.i, model.OR, initialize=arr2dict(var_bin_oor)) # Oferta de oportunidad de inyeccion # Precio de bloques - Oferta de oportunidad de inyeccion model.fi = Param(model.OI, model.s, initialize=arr2dict(p_ooi)) model.pi_ofertado = Param(model.OI, model.s, initialize=arr2dict( vooi_m)) # Magnitud de la oferta MW-h model.bin_pi = Param( model.i, model.OI, initialize=arr2dict(var_bin_ooi)) # Contratos firmes model.pf_declarada = Param(model.CF, initialize=dict( enumerate(vcf_ed))) # Energia declarada # Potencia requerida - Si no se flexbiliza deberian de ser igual la energia y la potencia model.pf_req = Param(model.CF, initialize=dict(enumerate(vcf_pr))) # Precio de flexibilidad de contrato # Precio de bloques - Contrato firme - Oferta de flexibilidad model.ffi = Param(model.CF, model.s, initialize=arr2dict(vcf_p)) # Magnitud de la oferta - tiene que ser igual a la suma de la energia declarada model.pfi_ofertado = Param( model.CF, model.s, initialize=arr2dict(vcf_m)) model.bin_cfi = Param( model.i, model.CF, initialize=arr2dict(var_bin_cfi)) model.bin_cfr = Param( model.i, model.CF, initialize=arr2dict(var_bin_cfr)) # Ofertas de flexibilidad de contratos fisicos flexibles # Ofertas de inyeccion model.pff_declarada = Param( model.CFF, initialize=dict(enumerate(vnfff_ed))) model.pffi_ofertado = Param( model.CFF, model.s, initialize=arr2dict(vnfff_m_i)) # Magnitud del bloque model.fffi = Param(model.CFF, model.s, initialize=arr2dict( p_cnfffi)) # Precio de inyeccion model.bin_pffi = Param( model.i, model.CFF, initialize=arr2dict(var_bin_cnfffi)) # Oferta de retiro model.pffr_ofertado = Param(model.CFF, model.s, initialize=arr2dict( vnfff_m_r)) # Magnitud de bloque de retiro ofertado # Precio de bloques - Contrato no firme fisico flexible model.fffr = Param(model.CFF, model.s, initialize=arr2dict(p_cnfffr)) model.bin_pffr = Param( model.i, model.CFF, initialize=arr2dict(var_bin_cnfffr)) # Ofertad de pago maximo por CVT model.k = Param(model.CFF, initialize=dict( enumerate(k_cnfffcvt))) # Indicador de oferta model.pfft_ofertado = Param(model.CFF, model.s, initialize=arr2dict( vnfff_m_cvt)) # Magnitud del bloque model.ffft = Param(model.CFF, model.s, initialize=arr2dict( p_cnfffcvt)) # Precio de pago maximo CVT # Variabeles # Variable ofertas de oportunidad # Parte aceptada de cada bloques de las ofertas de oportunidad de retiro model.pr = Var(model.OR, model.s, domain=NonNegativeReals) # Parte aceptada de cada bloques de las ofertas de oportunidad de inyeccion model.pi = Var(model.OI, model.s, domain=NonNegativeReals) # Variables CF # Parte aceptada de cada bloques de las ofertas de flexibilidad de contratos firmes model.pfi = Var(model.CF, model.s, domain=NonNegativeReals) # Variables CNFFF # Parte aceptada de cada bloques de las oferta de flexibilidad de retiro model.pffr = Var(model.CFF, model.s, domain=NonNegativeReals) # Parte aceptada de cada bloques de las ofertas de flexibilidad de inyección de los contratos físicos flexibles model.pffi = Var(model.CFF, model.s, domain=NonNegativeReals) # Parte aceptada de cada bloques de las oferta de pago máximo de CVT de los contratos físicos flexibles model.pfft = Var(model.CFF, model.s, domain=NonNegativeReals) # Componente fisica de energia PERIODOria de inyeecion model.pff_iny_fisico = Var(model.CFF, domain=NonNegativeReals) # Componente fisica de energia PERIODOria de retiro model.pff_ret_fisico = Var(model.CFF, domain=NonNegativeReals) # Variables FOENS # Energia firme de lo CF model.pf_cortada = Var(model.CF, domain=NonNegativeReals) model.pf_pre_cortada = Var(model.CF, domain=NonNegativeReals) # Energia firme de los CNFFF model.pff_cortada = Var(model.CFF, domain=NonNegativeReals) model.fens = Var() # Variable problema de optimizacion # Inyeccion por nodo model.inyeccion = Var(model.i, domain=NonNegativeReals) model.retiro = Var(model.i, domain=NonNegativeReals) # Retiro por nodo model.ref_angular = Var(model.i) # Fase del voltaje en el nodo model.rtmw_c = Var(model.c) # Flujo de potencia actica por linea # Máximas Capacidades de Trasferencia # Maxima transferenica(interconexion,sentido,periodo) model.Mct = Param(model.per, model.inter, model.sen, initialize=mct.MCT.to_dict(), default=300, mutable=True) model.DirF = Param(model.inter, initialize=dirf) logger.info("Ecuación de Función Objetivo Max.") def objfunc(model): return ((sum(model.fr[OR, s]*model.pr[OR, s] for OR in model.OR for s in model.s) - # ┌ FOO # └ sum(model.fi[OI, s]*model.pi[OI, s] for OI in model.OI for s in model.s) - # [ FOF sum(model.ffi[CF, s]*model.pfi[CF, s] for CF in model.CF for s in model.s) + # ┌ sum(model.fffr[CFF, s]*model.pffr[CFF, s] for CFF in model.CFF for s in model.s) - # │ FOFF sum(model.fffi[CFF, s]*model.pffi[CFF, s] for CFF in model.CFF for s in model.s) + # └ sum(model.ffft[CFF, s]*model.pfft[CFF, s] for CFF in model.CFF for s in model.s))) # - # ┌ FOENS # 0*model.fens*sum(model.pf_cortada[CF] for CF in model.CF) - # 0*model.fens*0.5*sum(model.pff_cortada[CFF] for CFF in model.CFF))) # └ model.OBJ = Objective(rule=objfunc, sense=maximize) logger.info("Restricciones del Modelo de Optimización. ") # Esta restricción no es utilizada y se encarga de efectuar la reducción # de los contratos firmes (idem FOENS línea 327) # def fens_restriccion(model): # if NOR == 0 & NCF == 0 & NCFF > 0: # return model.fens == 3*max(model.fffr[CFF, s] for CFF in model.CFF for s in model.s) # elif NOR == 0 & NCF > 0 & NCFF == 0: # return model.fens == 3*max(model.ffi[CF, s] for CF in model.CF for s in model.s) # elif NOR == 0 & NCF > 0 & NCFF > 0: # return model.fens == 3*max(max(model.ffi[CF, s] for CF in model.CF for s in model.s), # max(model.fffr[CFF, s] for CFF in model.CFF for s in model.s)) # elif NOR > 0 & NCF == 0 & NCFF == 0: # return model.fens == 3*max(model.fr[OR, s] for OR in model.OR for s in model.s) # elif NOR > 0 & NCF == 0 & NCFF > 0: # return model.fens == 3*max(max(model.fr[OR, s] for OR in model.OR for s in model.s), # max(model.fffr[CFF, s] for CFF in model.CFF for s in model.s)) # elif NOR > 0 & NCF > 0 & NCFF == 0: # return model.fens == 3*max(max(model.fr[OR, s] for OR in model.OR for s in model.s), # max(model.ffi[CF, s] for CF in model.CF for s in model.s)) # elif NOR > 0 & NCF > 0 & NCFF > 0: # return model.fens == 3*max(max(model.fr[OR, s] for OR in model.OR for s in model.s), # max(model.fffr[CFF, s] # for CFF in model.CFF for s in model.s), # max(model.ffi[CF, s] for CF in model.CF for s in model.s)) # model.fens_constraint = Constraint(rule=fens_restriccion) # Restrecciones FOO def pi_restriccion(model, OI, s): return ((model.pi[OI, s] <= model.pi_ofertado[OI, s])) model.pi_constraint = Constraint( model.OI, model.s, rule=pi_restriccion) def pr_restriccion(model, OR, s): return ((model.pr[OR, s] <= model.pr_ofertado[OR, s])) model.pr_constraint = Constraint( model.OR, model.s, rule=pr_restriccion) # Restricciones FOF def pfi_restriccion(model, CF, s): return (model.pfi[CF, s] <= model.pfi_ofertado[CF, s]) model.pfi_constraint = Constraint( model.CF, model.s, rule=pfi_restriccion) # Restricciones FOFF def pffr_restriccion(model, CFF, s): return (model.pffr[CFF, s] <= model.pffr_ofertado[CFF, s]) model.pffr_constraint = Constraint( model.CFF, model.s, rule=pffr_restriccion) def pffi_restriccion(model, CFF, s): return (model.pffi[CFF, s] <= model.pffi_ofertado[CFF, s]) model.pffi_constraint = Constraint( model.CFF, model.s, rule=pffi_restriccion) if (model.k[CFF] == 0 for CFF in model.CFF): def pfft_restriccion(model, CFF, s): # if model.k[CFF] ==0: return (model.pfft[CFF, s] <= model.pfft_ofertado[CFF, s]) model.pfft_constraint = Constraint( model.CFF, model.s, rule=pfft_restriccion) # K(cff) vale 0 si hay oferta de pago maximo por CVT def pff_iny_fisico_restriccion(model, CFF): if model.k[CFF] == 0: return (model.pff_iny_fisico[CFF] == sum(model.pfft[CFF, s] for s in model.s) - sum(model.pffr[CFF, s] for s in model.s)) elif model.k[CFF] == 1: return (model.pff_iny_fisico[CFF] == model.pff_declarada[CFF] - sum(model.pffr[CFF, s] for s in model.s)) model.pff_iny_fisico_constraint = Constraint( model.CFF, rule=pff_iny_fisico_restriccion) def pff_ret_fisico_restriccion(model, CFF): if model.k[CFF] == 0: return (model.pff_ret_fisico[CFF] == sum(model.pfft[CFF, s] for s in model.s) - sum(model.pffi[CFF, s] for s in model.s)) elif model.k[CFF] == 1: return (model.pff_ret_fisico[CFF] == model.pff_declarada[CFF] - model.pff_cortada[CFF] - sum(model.pffi[CFF, s] for s in model.s)) model.pff_ret_fisico_constraint = Constraint( model.CFF, rule=pff_ret_fisico_restriccion) # Restriccion FOENS def pff_cortada_restriccion(model, CFF): return (model.pff_cortada[CFF] <= model.pff_declarada[CFF]) model.pff_cortada_constraint = Constraint( model.CFF, rule=pff_cortada_restriccion) def pf_cortada_restriccion(model, CF): return (model.pf_cortada[CF] <= model.pf_req[CF]) model.pf_cortada_constraint = Constraint( model.CF, rule=pf_cortada_restriccion) logger.info('Restricciones de transmision.') # Restricciones de transmision def inyec(model, i): return (model.inyeccion[i] == model.G[i] + sum(model.pi[OI, s]*model.bin_pi[i, OI] for OI in model.OI for s in model.s) + sum(model.pfi[CF, s]*model.bin_cfi[i, CF] for CF in model.CF for s in model.s) + sum(model.pff_iny_fisico[CFF]*model.bin_pffi[i, CFF] for CFF in model.CFF)) model.inyec_constraint = Constraint(model.i, rule=inyec) def retiro(model, i): return (model.retiro[i] == model.D[i] + sum(model.pr[OR, s]*model.bin_pr[i, OR] for OR in model.OR for s in model.s) + sum(model.pf_req[CF]*model.bin_cfr[i, CF] for CF in model.CF) + sum(model.pff_ret_fisico[CFF]*model.bin_pffr[i, CFF] for CFF in model.CFF) - 0*sum(model.pf_cortada[CF]*model.bin_cfr[i, CF] for CF in model.CF) - 0*sum(model.pf_pre_cortada[CF]*model.bin_cfr[i, CF] for CF in model.CF)) model.retiro_constraint = Constraint(model.i, rule=retiro) # Los multiplicadore o variable duales de esta restriccion son los precios nodales def balance_inyeccion_retiro(model, i): return (model.inyeccion[i] + sum(model.Inc[c, i]*model.rtmw_c[c] for c in model.c) - # Al dividir entre 100 Rc # toda la ec. se pasa a p.u. 0.5*sum(((model.Inc[c, i]*model.rtmw_c[c])**2) * (model.Rc[c]/100) for c in model.c) == model.retiro[i]) model.balance_inyeccion_retiro_constraint = Constraint( model.i, rule=balance_inyeccion_retiro) def rtmw_min_restriccion(model, c): return (model.rtmw_c[c] >= -model.rtmw_min[c]) model.rtmw_min_constraint = Constraint( model.c, rule=rtmw_min_restriccion) def rtmw_max_restriccion(model, c): return (model.rtmw_c[c] <= model.rtmw_max[c]) model.rtmw_max_constraint = Constraint( model.c, rule=rtmw_max_restriccion) def flujo_potencia_actica(model, c): return ((model.Xc[c])*model.rtmw_c[c]+sum(model.Inc[c, i]*model.ref_angular[i] for i in model.i) == 0) model.flujo_potencia_actica_constraint = Constraint( model.c, rule=flujo_potencia_actica) # Máximas capacidades de trasferencia entre áreas de control def eq_mct_ns_rule(model, inter): if inter=='IMP_TOT_SAL':#Maxima exportacion de El Salvador return ((sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['ELSHON']))- (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['GUAELS']))) <= model.Mct[PERIODO, inter, 'ns'] elif inter=='EXP_TOT_GUA_NS': return ((sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['GUAHON'])) + (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['GUAELS']))) <= model.Mct[PERIODO, inter, 'ns'] elif inter=='IMP_TOT_HON':#Maxima importacion de Honduras return (-(sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['ELSHON'])) - (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['GUAHON'])) + (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['HONNIC']))) <= model.Mct[PERIODO, inter, 'sn'] elif inter=='IMP_TOT_NIC':#Maxima exportacion de Nicaragua return ((sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['NICCRI'])) - (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['HONNIC']))) <= model.Mct[PERIODO, inter, 'ns'] elif inter=='IMP_TOT_CRI':#Maxima exportacion de Costa Rica return ((sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['NICCRI'])) + (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['CRIPAN']))) <= model.Mct[PERIODO, inter, 'ns'] elif inter=='IMP_TOT_PAN': return sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['CRIPAN']) <= model.Mct[PERIODO, inter, 'ns'] else: return (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct[inter])) <= model.Mct[PERIODO, inter, 'ns'] model.eq_mct_ns = Constraint(model.inter, rule=eq_mct_ns_rule) def eq_mct_sn_rule(model, inter): if inter=='IMP_TOT_SAL':#Maxima importacion de El Salvador return ((sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['ELSHON'])) - (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['GUAELS']))) >= -model.Mct[PERIODO, inter, 'sn'] elif inter=='EXP_TOT_GUA_NS': return ((sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['GUAHON'])) + (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['GUAELS']))) >= -model.Mct[PERIODO, inter, 'sn'] elif inter=='IMP_TOT_HON':#Maxima importacion de Honduras return (-((sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['ELSHON'])) + (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['GUAHON']))) + (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['HONNIC']))) >= -model.Mct[PERIODO, inter, 'ns'] elif inter=='IMP_TOT_NIC':#Maxima exportacion de Nicaragua return ((sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['NICCRI'])) - (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['HONNIC']))) >= -model.Mct[PERIODO, inter, 'sn'] elif inter=='IMP_TOT_CRI':#Maxima exportacion de Costa Rica return ((sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['NICCRI'])) + (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['CRIPAN'])))>= -model.Mct[PERIODO, inter, 'sn'] elif inter=='IMP_TOT_PAN': return sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct['CRIPAN']) >= -model.Mct[PERIODO, inter, 'sn'] else: return (sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct[inter])) >= -model.Mct[PERIODO, inter, 'sn'] model.eq_mct_sn = Constraint(model.inter, rule=eq_mct_sn_rule) model.dual = Suffix(direction=Suffix.IMPORT) print("Construcción del modelo terminada. Periodo: "+str(PERIODO)) opt = SolverFactory('ipopt') #opt.options['max_iter']= 10000 result = opt.solve(model) model.solutions.store_to(result) # Cálculo de Precios Nodales # ============================================================================= print("Calculando Precios Nodales. Periodo:" + str(PERIODO)) Sigma = zeros(nb) for i in model.i: Sigma[i] = model.dual[model.balance_inyeccion_retiro_constraint[i]] # Construcción de array para grabar # ============================================================================= flujos=DataFrame() flujos['Periodo']=set_periodo(nbr,PERIODO) flujos['BUS I'] = brnames['BUS I'] flujos['BUS J'] = brnames['BUS J'] flujos['CKT'] = brnames['CKT'] f = array(list(model.rtmw_c.get_values().values())) perdidas=zeros(nbr) for c in model.c: perdidas[c]=(f[c]**2)*rc[c]/100 flujos['Flujo'] = f flujos['Perdidas'] = perdidas flujos=flujos.round({'Flujo':3,'Perdidas':3}) flujos_t=concat([flujos_t,flujos].copy())#Guarda los resultados con los anteriores pon = DataFrame() result_inyeccion = array(list(model.inyeccion.get_values().values())) result_retiro = array(list(model.retiro.get_values().values())) pon['Periodo']=set_periodo(nb,PERIODO) pon['Nodo']= bus pon['Precio Exante'] = Sigma*-1 pon=pon.round({'Precio Exante':2}) pon_t=concat([pon_t,pon]).copy()#Guarda los resultados con los anteriores #print(pon) iep=DataFrame() iep['Periodo']=set_periodo(nb,PERIODO) iep['nodo']= bus iep['Inyeccion'] = result_inyeccion iep['Retiro'] = result_retiro iep=iep.round({'Inyeccion':3,'Retiro':3}) iep_t=concat([iep_t,iep]).copy()#Guarda los resultados con los anteriores result_pff_iny=array(list(model.pff_iny_fisico.get_values().values())) result_pff_ret=array(list(model.pff_ret_fisico.get_values().values())) result_pr = setvariable_p(array(list(model.pr.get_values().values())),NOR) result_pi = setvariable_p(array(list(model.pi.get_values().values())),NOI) result_pfi = setvariable_p(array(list(model.pfi.get_values().values())),NCF) result_pffr = setvariable_p(array(list(model.pffr.get_values().values())),NCFF) result_pffi = setvariable_p(array(list(model.pffi.get_values().values())),NCFF) result_pfft = setvariable_p(array(list(model.pfft.get_values().values())),NCFF) result_foo_r=DataFrame() result_foo_r['ID']=ex_oor['N°'] result_foo_r['Fecha']=ex_oor['Fecha'].apply( lambda d : d.date() ) result_foo_r['Periodo']=ex_oor['periodo'] result_foo_r['Nodo']=ex_oor['nodo_oor'] pais_foo_r=pd.concat([result_foo_r.set_index('Nodo'),nodec.set_index('ID_NODO')], axis=1, join='inner').reset_index() pex_foo_r=pd.concat([result_foo_r.set_index('Nodo'),pon.set_index('Nodo')], axis=1, join='inner').reset_index() result_foo_r.drop(['Nodo'], axis='columns', inplace=True) result_foo_r['Pais']=pais_foo_r['ID_AREA'] result_foo_r['Nodo']=ex_oor['nodo_oor'] result_foo_r['Precio Exante']=pex_foo_r['Precio Exante'] result_foo_r['Agente']=ex_oor['Agente'] result_foo_r['MW Predespachados']=result_pr[:,0] + result_pr[:,1] + result_pr[:,2]+result_pr[:,3]+result_pr[:,4] result_foo_r=result_foo_r.round({'MW Predespachados':3}) result_foo_r_t=concat([result_foo_r_t,result_foo_r]).copy()#Guarda los resultados con los anteriores result_foo_i=DataFrame() result_foo_i['ID']=ex_ooi['N°'] result_foo_i['Fecha']=ex_ooi['Fecha'].apply( lambda d : d.date() ) result_foo_i['Periodo']=ex_ooi['periodo'] result_foo_i['Nodo']=ex_ooi['nodo_i'] pex_foo_i=pd.concat([result_foo_i.set_index('Nodo'),pon.set_index('Nodo')], axis=1, join='inner').reset_index() pais_foo_i=pd.concat([result_foo_i.set_index('Nodo'),nodec.set_index('ID_NODO')], axis=1, join='inner').reset_index() result_foo_i.drop(['Nodo'], axis='columns', inplace=True) result_foo_i['Pais']=pais_foo_i['ID_AREA'] result_foo_i['Nodo']=ex_ooi['nodo_i'] result_foo_i['Precio Exante']=pex_foo_i['Precio Exante'] result_foo_i['Agente']=ex_ooi['Agente'] result_foo_i['MW Predespachados']=result_pi[:,0]+result_pi[:,1]+result_pi[:,2]+result_pi[:,3]+result_pi[:,4] result_foo_i=result_foo_i.round({'MW Predespachados':3}) result_foo_i_t=concat([result_foo_i_t,result_foo_i]).copy()#Guarda los resultados con los anteriores result_fof=DataFrame() result_fof['ID']=ex_cf['N°'] result_fof['Fecha']=ex_cf['Fecha'].apply( lambda d : d.date() ) result_fof['Periodo']=ex_cf['periodo'] result_fof['Nodo Inyeccion']=ex_cf['nodo_cfi'] pex_fof_i=pd.concat([result_fof.set_index('Nodo Inyeccion'),pon.set_index('Nodo')], axis=1, join='inner').reset_index() pais_fof_i=pd.concat([result_fof.set_index('Nodo Inyeccion'),nodec.set_index('ID_NODO')], axis=1, join='inner').reset_index() result_fof.drop(['Nodo Inyeccion'], axis='columns', inplace=True) result_fof['Pais Inyeccion']=pais_fof_i['ID_AREA'] result_fof['Nodo Inyeccion']=ex_cf['nodo_cfi'] result_fof['Precio Exante Inyeccion']=pex_fof_i['Precio Exante'] result_fof['Agente Inyeccion']=ex_cf['agente_cfi'] result_fof['Nodo Retiro']=ex_cf['nodo_cfr'] pais_fof_r=pd.concat([result_fof.set_index('Nodo Retiro'),nodec.set_index('ID_NODO')], axis=1, join='inner').reset_index() pex_fof_r=pd.concat([result_fof.set_index('Nodo Retiro'),pon.set_index('Nodo')], axis=1, join='inner').reset_index() result_fof.drop(['Nodo Retiro'], axis='columns', inplace=True) result_fof['Pais Retiro']=pais_fof_r['ID_AREA'] result_fof['Nodo Retiro']=ex_cf['nodo_cfr'] result_fof['Precio Exante Retiro']=pex_fof_r['Precio Exante'] result_fof['Agente Retiro']=ex_cf['agente_cfr'] result_fof['MW Predespachados O.I. Flexibilidad']=result_pfi[:,0]+result_pfi[:,1]+result_pfi[:,2]+result_pfi[:,3]+result_pfi[:,4] result_fof['MW Predespachados Ret. Requerido']=ex_cf['potencia_req'] result_fof=result_fof.round({'MW Predespachados O.I. Flexibilidad':3,'MW Predespachados Ret. Requerido':3}) result_fof_t=concat([result_fof_t,result_fof]).copy()#Guarda los resultados con los anteriores result_foff=DataFrame() result_foff['ID']=ex_cnfff['N°'] result_foff['Fecha']=ex_cnfff['Fecha'].apply( lambda d : d.date() ) result_foff['Periodo']=ex_cnfff['periodo'] result_foff['Nodo Inyeccion']=ex_cnfff['nodo_cnfffi'] pex_foff_i=pd.concat([result_foff.set_index('Nodo Inyeccion'),pon.set_index('Nodo')], axis=1, join='inner').reset_index() pais_foff_i=pd.concat([result_foff.set_index('Nodo Inyeccion'),nodec.set_index('ID_NODO')], axis=1, join='inner').reset_index() result_foff.drop(['Nodo Inyeccion'], axis='columns', inplace=True) result_foff['Pais Inyeccion']=pais_foff_i['ID_AREA'] result_foff['Nodo Inyeccion']=ex_cnfff['nodo_cnfffi'] result_foff['Precio Exante Inyeccion']=pex_foff_i['Precio Exante'] result_foff['Agente Inyeccion']=ex_cnfff['agente_cnfffi'] result_foff['Nodo Retiro']=ex_cnfff['nodo_cnfffr'] pais_foff_r=pd.concat([result_foff.set_index('Nodo Retiro'),nodec.set_index('ID_NODO')], axis=1, join='inner').reset_index() pex_foff_r=pd.concat([result_foff.set_index('Nodo Retiro'),pon.set_index('Nodo')], axis=1, join='inner').reset_index() result_foff.drop(['Nodo Retiro'], axis='columns', inplace=True) result_foff['Pais Retiro']=pais_foff_r['ID_AREA'] result_foff['Nodo Retiro']=ex_cnfff['nodo_cnfffr'] result_foff['Precio Exante Retiro']=pex_foff_r['Precio Exante'] result_foff['Agente Retiro']=ex_cnfff['agente_cnfffr'] result_foff['CVT']=result_foff['Precio Exante Retiro'] - result_foff['Precio Exante Inyeccion'] result_foff['MW Predespachados CNFFF']=result_pfft[:,0]+result_pfft[:,1]+result_pfft[:,2]+result_pfft[:,3]+result_pfft[:,4] result_foff['MW Predespachados O.I. Flexibilidad']=result_pffi[:,0]+result_pffi[:,1]+result_pffi[:,2]+result_pffi[:,3]+result_pffi[:,4] result_foff['MW Predespachados O.R. Flexibilidad']=result_pffr[:,0]+result_pffr[:,1]+result_pffr[:,2]+result_pffr[:,3]+result_pffr[:,4] result_foff=result_foff.round({'CVT':2,'MW Predespachados CNFFF':3,'MW Predespachados O.R. Flexibilidad':3,'MW Predespachados O.I. Flexibilidad':3}) result_foff_t=concat([result_foff_t,result_foff])#Guarda los resultados con los anteriores logger.info("Escribiendo resultados en carpeta.") filename = path.basename(file).split('.') filepath = path.dirname(file) if all_day: new_filename = filename[0]+'_results.'+filename[1] new_file = path.join(filepath, new_filename) else: new_filename = filename[0]+'_results_{}.'.format(p_exec)+filename[1] new_file = path.join(filepath, new_filename) writer=ExcelWriter(new_file) flujos_t.to_excel(writer,'IEP-RTR',index=False) iep_t.to_excel(writer,'IEP-TOTAL',index=False) pon_t.to_excel(writer,'PEXANTE',index=False) result_foo_i_t.to_excel(writer,'TOP-I',index=False) result_foo_r_t.to_excel(writer,'TOP-R',index=False) result_fof_t.to_excel(writer,'TCP-CF',index=False) result_foff_t.to_excel(writer,'TCP-CNFFF',index=False) writer.save() print("{:=^100}".format("")) print("{:^100}".format(" Script Finalizado ")) print("{:^100}".format(" Mercados Eléctricos de Centroamérica (c) 2020 ")) print("{:=^100}".format("")) return 0 if __name__ == "__main__": setmodel() # faltan argumentos