predespacho_24h.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. from __future__ import division
  2. from pyomo.environ import *
  3. from red.read import excel2net
  4. from red.create import *
  5. from red.create1 import *
  6. from red.makeBdc import makeBdc
  7. from utils.arr2dict import arr2dict
  8. from pyomo.environ import SolverFactory
  9. from pyomo.kernel import value
  10. from numpy import zeros, array
  11. from pandas import DataFrame, ExcelWriter
  12. from mct.makeMCT import linmct, readmct, set_dir_flujo
  13. from os import path
  14. def setmodel(file):
  15. print("{:=^100}".format(""))
  16. print("{:^100}".format(" Modelo de Predespacho Regional"))
  17. print("{:^100}".format(" Mercados Eléctricos de Centroamérica (c) 2020 "))
  18. print("{:=^100}".format(""))
  19. # ============================================================================
  20. # Importación de datos desde archivo Excel
  21. # ============================================================================
  22. #Parametros de la linea
  23. print("Inicio del Script de Predespacho")
  24. print("Leyendo información de red...")
  25. net = excel2net(file)
  26. bus = setbus(net)#Nodos
  27. branch = setbranch(net, bus)#Set lineas
  28. bu = branch[:, 5]#potenica max de la linea
  29. bl = branch[:, 6]#potenica min de la linea
  30. xc = branch[:,3]#Reactancia de la linea
  31. rc = branch[:,4]#Resistencia de la linea
  32. nb = bus.shape[0] #Numero de nodos
  33. nbr = branch.shape[0]#Numero de lineas
  34. A = makeBdc(bus, branch)#Matriz incidente
  35. brnames = branchnames(bus, branch)#Nombre de las lineas
  36. inc = A.toarray()*-1
  37. # Lineas para límites de MCT
  38. br_t = brnames['Total'].to_numpy()
  39. lin_mct = linmct(br_t)
  40. dirf = set_dir_flujo()
  41. mct = readmct(file)
  42. #Informacion de los despachos nacionales
  43. dg_t =read_D_G(file)
  44. #Ofertas de todos los periodos
  45. ex_cnfff_t = readofertas_cnfffs(file)
  46. ex_ooi_t = readofertas_oois(file)
  47. ex_oor_t = readofertas_oors(file)
  48. ex_cf_t = readofertas_cfs(file)
  49. #Dataframe para almacenar la informacion de cada predespacho
  50. flujos_t=DataFrame()
  51. iep_t=DataFrame()
  52. pon_t = DataFrame()
  53. result_foo_i_t = DataFrame()
  54. result_foo_r_t = DataFrame()
  55. result_fof_t = DataFrame()
  56. result_foff_t = DataFrame()
  57. foo_ret_iny_t = DataFrame()
  58. #El range del for se modifica dependiendo los periodos que se quieren correr.
  59. for PERIODO in range(0,24):
  60. print("Leyendo información de los despacho nacionales. Periodo: " + str(PERIODO))
  61. dg=dg_t[dg_t.periodo.isin([PERIODO])]#Dependiendo de los valores de la columna periodo del df son los valores que toma
  62. dg.reset_index(drop=True, inplace=True)#Resetea valores de ordenamiento del DF
  63. dg_n=set_dgnacional(bus,dg)#Ordena los valores que tiene segun los nodos de rtr
  64. print("Leyendo información de ofertas. Periodo: " + str(PERIODO))
  65. #Funcion leer contratos no firmes fisicos flexibles
  66. ex_cnfff=ex_cnfff_t[ex_cnfff_t.periodo.isin([PERIODO])]#Dependiendo de los valores de la columna periodo del df son los valores que toma
  67. ex_cnfff.reset_index(drop=True, inplace=True)#Resetea valores de ordenamiento del DF
  68. vnfff_ed= setvariable(ex_cnfff['energía_dec'])#Energia declarada con respecto al nodo
  69. vnfff_m_i= setvariable_s(ex_cnfff[['magnitud_i1','magnitud_i2','magnitud_i3','magnitud_i4','magnitud_i5']])#Magnitud de energia ofertada -flexibilizacion
  70. vnfff_m_r= setvariable_s(ex_cnfff[['magnitud_r1','magnitud_r2','magnitud_r3','magnitud_r4','magnitud_r5']])
  71. vnfff_m_cvt=setvariable_s(ex_cnfff[['magnitud_cvt1','magnitud_cvt2','magnitud_cvt3','magnitud_cvt4','magnitud_cvt5']])
  72. p_cnfffi= setvariable_s(ex_cnfff[['precio_i1','precio_i2','precio_i3','precio_i4','precio_i5']])#Precio de la ofertas de inyeccion
  73. p_cnfffr= setvariable_s(ex_cnfff[['precio_r1','precio_r2','precio_r3','precio_r4','precio_r5']])#Precio de la ofertas de retiro
  74. p_cnfffcvt= setvariable_s(ex_cnfff[['precio_cvt1','precio_cvt2','precio_cvt3','precio_cvt4','precio_cvt5']])#Precio de la ofertas de inyeccion
  75. k_cnfffcvt= setvariable(ex_cnfff['k'])#Precio de la ofertas de inyeccion
  76. NCFF = ex_cnfff.shape[0]#Numero de contratos firmes
  77. var_bin_cnfffr=MATRIZ_VNFFF_R(bus,ex_cnfff)
  78. var_bin_cnfffi=MATRIZ_VNFFF_I(bus,ex_cnfff)
  79. dem=setvariable(dg_n['Demanda'])
  80. gen=setvariable(dg_n['Generacion'])
  81. #Funcion leer parametros oferta de oportunidad inyeccion
  82. ex_ooi = ex_ooi_t[ex_ooi_t.periodo.isin([PERIODO])]#Dependiendo de los valores de la columna periodo del df son los valores que toma
  83. ex_ooi.reset_index(drop=True, inplace=True)#Resetea valores de ordenamiento del DF
  84. vooi_m=setvariable_s(ex_ooi[['magnitud_ooi1','magnitud_ooi2','magnitud_ooi3','magnitud_ooi4','magnitud_ooi5']])#Ofertas con respecto al nodo
  85. p_ooi= setvariable_s(ex_ooi[['precio_ooi1','precio_ooi2','precio_ooi3','precio_ooi4','precio_ooi5']])#Precio de la ofertas
  86. NOI = ex_ooi.shape[0]#Numero de ofertas de inyeccion
  87. var_bin_ooi=MATRIZ_OOI(bus,ex_ooi)
  88. #Funcion leer parametros oferta de oportunidad retiro
  89. ex_oor=ex_oor_t[ex_oor_t.periodo.isin([PERIODO])]
  90. ex_oor.reset_index(drop=True, inplace=True)#Resetea valores de ordenamiento del DF
  91. voor_m=setvariable_s(ex_oor[['magnitud_oor1','magnitud_oor2','magnitud_oor3','magnitud_oor4','magnitud_oor5']])#Ofertas con respecto al nodo
  92. p_oor= setvariable_s(ex_oor[['precio_oor1','precio_oor2','precio_oor3','precio_oor4','precio_oor5']])#Precio de la ofertas - flexibilizacion
  93. NOR = ex_oor.shape[0]#Numero de ofertas de retiro
  94. var_bin_oor=MATRIZ_OOR(bus,ex_oor)
  95. #Funcion leer parametros contratos firmes
  96. ex_cf=ex_cf_t[ex_cf_t.periodo.isin([PERIODO])]#Dependiendo de los valores de la columna periodo del df son los valores que toma
  97. ex_cf.reset_index(drop=True, inplace=True)#Resetea valores de ordenamiento del DF
  98. vcf_ed=setvariable(ex_cf['energía_dec'])#Energia declarada con respecto al nodo
  99. vcf_pr=setvariable(ex_cf['potencia_req'])#Potencia requerida con respecto al nodo
  100. vcf_m=setvariable_s(ex_cf[['magnitu_cf1','magnitu_cf2','magnitu_cf3','magnitu_cf4','magnitu_cf5']])#Magnitud de energia ofertada -flexibilizacion
  101. vcf_p= setvariable_s(ex_cf[['precio_cf1','precio_cf2','precio_cf3','precio_cf4','precio_cf5']])#Precio de la ofertas
  102. NCF = ex_cf.shape[0]#Numero de contratos firmes
  103. var_bin_cfr=MATRIZ_CFR(bus, ex_cf)
  104. var_bin_cfi=MATRIZ_CFI(bus, ex_cf)
  105. # Inicio del modelo de optimización
  106. model=ConcreteModel()
  107. #sets
  108. model.i=Set(initialize=range(0, nb))#numero de nodos
  109. model.c=Set(initialize=range(0, nbr))#Numero de lineas
  110. model.OR = Set(initialize=range(0, NOR))#numero de ofertas de oportuniddad retiro
  111. model.OI = Set(initialize=range(0, NOI))#numero de ofertas de oportunidad inyeccion
  112. model.CFF=Set(initialize=range(0, NCFF))#numero de ofertas de CNFFF
  113. model.CF=Set(initialize=range(0, NCF))#numero de ofertas de contratos firmes
  114. model.s=Set(initialize=range(0, 5))#Numero de bloques
  115. model.inter = Set(initialize=lin_mct.keys()) # Interconexiones
  116. model.sen = Set(initialize=['sn', 'ns']) # Sentidos de interconexiones
  117. model.per=Set(initialize=range(0, 24))#numero de periodos
  118. #Parametros
  119. #Parametros de la red
  120. model.rtmw_min= Param(model.c, initialize=dict(enumerate(bl)))
  121. model.rtmw_max= Param(model.c, initialize=dict(enumerate(bu)))
  122. model.Inc = Param(model.c, model.i, initialize=arr2dict(inc))
  123. model.Xc = Param(model.c, initialize=dict(enumerate(xc)))
  124. model.Rc = Param(model.c, initialize=dict(enumerate(rc)))
  125. #Parametros de los predespachos nacionales
  126. model.D = Param(model.i, initialize=dict(enumerate(dem)))
  127. model.G = Param(model.i, initialize=dict(enumerate(gen)))
  128. #Ofertas de oportunidad
  129. #Oferta de oportunidad de retiro
  130. model.fr= Param(model.OR, model.s, initialize=arr2dict(p_oor))#Oferta bloques 1
  131. model.pr_ofertado = Param(model.OR, model.s, initialize=arr2dict(voor_m))#Magnitud de la oferta MW-h
  132. model.bin_pr = Param(model.i, model.OR, initialize=arr2dict(var_bin_oor))
  133. #Oferta de oportunidad de inyeccion
  134. model.fi= Param(model.OI, model.s, initialize=arr2dict(p_ooi))#Precio de bloques - Oferta de oportunidad de inyeccion
  135. model.pi_ofertado= Param(model.OI, model.s, initialize=arr2dict(vooi_m))#Magnitud de la oferta MW-h
  136. model.bin_pi = Param(model.i,model.OI,initialize=arr2dict(var_bin_ooi))
  137. #Contratos firmes
  138. model.pf_declarada=Param(model.CF, initialize=dict(enumerate(vcf_ed)))#Energia declarada
  139. model.pf_req=Param(model.CF, initialize=dict(enumerate(vcf_pr)))# Potencia requerida - Si no se flexbiliza deberian de ser igual la energia y la potencia
  140. #Precio de flexibilidad de contrato
  141. model.ffi=Param(model.CF, model.s, initialize=arr2dict(vcf_p))#Precio de bloques - Contrato firme - Oferta de flexibilidad
  142. model.pfi_ofertado=Param(model.CF, model.s, initialize=arr2dict(vcf_m))#Magnitud de la oferta - tiene que ser igual a la suma de la energia declarada
  143. model.bin_cfi=Param(model.i, model.CF,initialize=arr2dict(var_bin_cfi))
  144. model.bin_cfr=Param(model.i, model.CF,initialize=arr2dict(var_bin_cfr))
  145. #Ofertas de flexibilidad de contratos fisicos flexibles
  146. #Ofertas de inyeccion
  147. model.pff_declarada=Param(model.CFF, initialize=dict(enumerate(vnfff_ed)))
  148. model.pffi_ofertado=Param(model.CFF, model.s, initialize=arr2dict(vnfff_m_i))#Magnitud del bloque
  149. model.fffi=Param(model.CFF, model.s, initialize=arr2dict(p_cnfffi))#Precio de inyeccion
  150. model.bin_pffi=Param(model.i,model.CFF, initialize=arr2dict(var_bin_cnfffi))
  151. #Oferta de retiro
  152. model.pffr_ofertado=Param(model.CFF, model.s, initialize=arr2dict(vnfff_m_r))#Magnitud de bloque de retiro ofertado
  153. model.fffr=Param(model.CFF, model.s, initialize=arr2dict(p_cnfffr))#Precio de bloques - Contrato no firme fisico flexible
  154. model.bin_pffr=Param(model.i,model.CFF, initialize=arr2dict(var_bin_cnfffr))
  155. #Ofertad de pago maximo por CVT
  156. model.k=Param(model.CFF, initialize=dict(enumerate(k_cnfffcvt)))#Indicador de oferta
  157. model.pfft_ofertado=Param(model.CFF, model.s, initialize=arr2dict(vnfff_m_cvt))#Magnitud del bloque
  158. model.ffft=Param(model.CFF, model.s, initialize=arr2dict(p_cnfffcvt))#Precio de pago maximo CVT
  159. #Variabeles
  160. #Variable ofertas de oportunidad
  161. model.pr= Var(model.OR, model.s, domain=NonNegativeReals)#Parte aceptada de cada bloques de las ofertas de oportunidad de retiro
  162. model.pi= Var(model.OI, model.s, domain=NonNegativeReals)#Parte aceptada de cada bloques de las ofertas de oportunidad de inyeccion
  163. #Variables CF
  164. model.pfi=Var(model.CF, model.s, domain=NonNegativeReals)#Parte aceptada de cada bloques de las ofertas de flexibilidad de contratos firmes
  165. #Variables CNFFF
  166. model.pffr=Var(model.CFF, model.s, domain=NonNegativeReals)#Parte aceptada de cada bloques de las oferta de flexibilidad de retiro
  167. model.pffi=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
  168. model.pfft=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
  169. model.pff_iny_fisico=Var(model.CFF, domain=NonNegativeReals)#Componente fisica de energia PERIODOria de inyeecion
  170. model.pff_ret_fisico=Var(model.CFF, domain=NonNegativeReals)#Componente fisica de energia PERIODOria de retiro
  171. #Variables FOENS
  172. model.pf_cortada=Var(model.CF, domain=NonNegativeReals)#Energia firme de lo CF
  173. model.pf_pre_cortada=Var(model.CF, domain=NonNegativeReals)
  174. model.pff_cortada=Var(model.CFF, domain=NonNegativeReals)#Energia firme de los CNFFF
  175. model.fens=Var()
  176. #Variable problema de optimizacion
  177. model.inyeccion= Var(model.i, domain=NonNegativeReals)#Inyeccion por nodo
  178. model.retiro= Var(model.i, domain=NonNegativeReals)#Retiro por nodo
  179. model.ref_angular= Var(model.i)#Fase del voltaje en el nodo
  180. model.rtmw_c= Var(model.c)#Flujo de potencia actica por linea
  181. # Máximas Capacidades de Trasferencia
  182. model.Mct = Param(model.inter, model.sen, model.per, initialize=mct.mct.to_dict())#Maxima transferenica(interconexion,sentido,periodo)
  183. model.DirF = Param(model.inter, initialize=dirf)
  184. print("Ecuación de Función Objetivo Max. Periodo: " + str(PERIODO))
  185. def objfunc(model):
  186. return ((sum(model.fr[OR,s]*model.pr[OR,s] for OR in model.OR for s in model.s) - # ┌ FOO
  187. sum(model.fi[OI,s]*model.pi[OI,s] for OI in model.OI for s in model.s) - # └
  188. sum(model.ffi[CF,s]*model.pfi[CF,s] for CF in model.CF for s in model.s) + # [ FOF
  189. sum(model.fffr[CFF,s]*model.pffr[CFF,s] for CFF in model.CFF for s in model.s) - # ┌
  190. sum(model.fffi[CFF,s]*model.pffi[CFF,s] for CFF in model.CFF for s in model.s) + # │ FOFF
  191. sum(model.ffft[CFF,s]*model.pfft[CFF,s] for CFF in model.CFF for s in model.s) - # └
  192. 0*model.fens*sum(model.pf_cortada[CF] for CF in model.CF) - # ┌ FOENS
  193. 0*model.fens*0.5*sum(model.pff_cortada[CFF] for CFF in model.CFF))) # └
  194. model.OBJ= Objective(rule=objfunc, sense=maximize)
  195. print("Restricciones del Modelo de Optimización. Periodo: "+str(PERIODO))
  196. def fens_restriccion(model):
  197. if NOR==0 & NCF==0 & NCFF>0:
  198. return model.fens == 3*max(model.fffr[CFF,s] for CFF in model.CFF for s in model.s)
  199. elif NOR==0 & NCF>0 & NCFF==0:
  200. return model.fens == 3*max(model.ffi[CF,s] for CF in model.CF for s in model.s)
  201. elif NOR==0 & NCF>0 & NCFF>0:
  202. return model.fens == 3*max(max(model.ffi[CF,s] for CF in model.CF for s in model.s),
  203. max(model.fffr[CFF,s] for CFF in model.CFF for s in model.s))
  204. elif NOR>0 & NCF==0 & NCFF==0:
  205. return model.fens == 3*max(model.fr[OR,s] for OR in model.OR for s in model.s)
  206. elif NOR>0 & NCF==0 & NCFF>0:
  207. return model.fens == 3*max(max(model.fr[OR,s] for OR in model.OR for s in model.s),
  208. max(model.fffr[CFF,s] for CFF in model.CFF for s in model.s))
  209. elif NOR>0 & NCF>0 & NCFF==0:
  210. return model.fens == 3*max(max(model.fr[OR,s] for OR in model.OR for s in model.s),
  211. max(model.ffi[CF,s] for CF in model.CF for s in model.s))
  212. elif NOR>0 & NCF>0 & NCFF>0:
  213. return model.fens == 3*max(max(model.fr[OR,s] for OR in model.OR for s in model.s),
  214. max(model.fffr[CFF,s] for CFF in model.CFF for s in model.s),
  215. max(model.ffi[CF,s] for CF in model.CF for s in model.s))
  216. model.fens_constraint= Constraint(rule=fens_restriccion)
  217. #Restrecciones FOO
  218. def pi_restriccion(model,OI,s):
  219. return ((model.pi[OI,s] <=model.pi_ofertado[OI,s]))
  220. model.pi_constraint= Constraint(model.OI, model.s, rule=pi_restriccion)
  221. def pr_restriccion(model,OR,s):
  222. return ((model.pr[OR,s]<=model.pr_ofertado[OR,s]))
  223. model.pr_constraint= Constraint(model.OR, model.s, rule=pr_restriccion)
  224. #Restricciones FOF
  225. def pfi_restriccion(model,CF,s):
  226. return (model.pfi[CF,s]<=model.pfi_ofertado[CF,s])
  227. model.pfi_constraint= Constraint(model.CF, model.s, rule=pfi_restriccion)
  228. #Restricciones FOFF
  229. def pffr_restriccion(model,CFF,s):
  230. return (model.pffr[CFF,s]<=model.pffr_ofertado[CFF,s])
  231. model.pffr_constraint= Constraint(model.CFF, model.s, rule=pffr_restriccion)
  232. def pffi_restriccion(model,CFF,s):
  233. return (model.pffi[CFF,s]<=model.pffi_ofertado[CFF,s])
  234. model.pffi_constraint= Constraint(model.CFF, model.s, rule=pffi_restriccion)
  235. if (model.k[CFF] ==0 for CFF in model.CFF):
  236. def pfft_restriccion(model,CFF,s):
  237. #if model.k[CFF] ==0:
  238. return (model.pfft[CFF,s]<=model.pfft_ofertado[CFF,s])
  239. model.pfft_constraint= Constraint(model.CFF, model.s, rule=pfft_restriccion)
  240. #K(cff) vale 0 si hay oferta de pago maximo por CVT
  241. def pff_iny_fisico_restriccion(model,CFF):
  242. if model.k[CFF] ==0:
  243. 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))
  244. elif model.k[CFF] ==1:
  245. return (model.pff_iny_fisico[CFF]==model.pff_declarada[CFF] - sum(model.pffr[CFF,s] for s in model.s))
  246. model.pff_iny_fisico_constraint=Constraint(model.CFF, rule=pff_iny_fisico_restriccion)
  247. def pff_ret_fisico_restriccion(model,CFF):
  248. if model.k[CFF] ==0:
  249. 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))
  250. elif model.k[CFF] ==1:
  251. return (model.pff_ret_fisico[CFF]==model.pff_declarada[CFF] - model.pff_cortada[CFF]- sum(model.pffi[CFF,s] for s in model.s))
  252. model.pff_ret_fisico_constraint=Constraint(model.CFF, rule=pff_ret_fisico_restriccion)
  253. #Restriccion FOENS
  254. def pff_cortada_restriccion(model,CFF):
  255. return (model.pff_cortada[CFF]<=model.pff_declarada[CFF])
  256. model.pff_cortada_constraint=Constraint(model.CFF, rule=pff_cortada_restriccion)
  257. def pf_cortada_restriccion(model,CF):
  258. return (model.pf_cortada[CF]<=model.pf_req[CF])
  259. model.pf_cortada_constraint=Constraint(model.CF, rule=pf_cortada_restriccion)
  260. print('Restricciones de transmision. Periodo: ' + str(PERIODO))
  261. #Restricciones de transmision
  262. def inyec(model,i):
  263. return (model.inyeccion[i] == model.G[i] +
  264. sum(model.pi[OI,s]*model.bin_pi[i,OI] for OI in model.OI for s in model.s) +
  265. sum(model.pfi[CF,s]*model.bin_cfi[i,CF] for CF in model.CF for s in model.s) +
  266. sum(model.pff_iny_fisico[CFF]*model.bin_pffi[i,CFF] for CFF in model.CFF))
  267. model.inyec_constraint= Constraint(model.i, rule=inyec)
  268. def retiro(model,i):
  269. return (model.retiro[i] == model.D[i] +
  270. sum(model.pr[OR,s]*model.bin_pr[i,OR] for OR in model.OR for s in model.s) +
  271. sum(model.pf_req[CF]*model.bin_cfr[i,CF] for CF in model.CF) +
  272. sum(model.pff_ret_fisico[CFF]*model.bin_pffr[i,CFF] for CFF in model.CFF) -
  273. 0*sum(model.pf_cortada[CF]*model.bin_cfr[i,CF] for CF in model.CF) -
  274. 0*sum(model.pf_pre_cortada[CF]*model.bin_cfr[i,CF] for CF in model.CF))
  275. model.retiro_constraint= Constraint(model.i, rule=retiro)
  276. #Los multiplicadore o variable duales de esta restriccion son los precios nodales
  277. def balance_inyeccion_retiro(model,i):
  278. return (model.inyeccion[i] + sum(model.Inc[c,i]*model.rtmw_c[c] for c in model.c) - # Al dividir entre 100 Rc
  279. 0.5*sum(((model.Inc[c,i]*model.rtmw_c[c])**2)*(model.Rc[c]/100) for c in model.c) # toda la ec. se pasa a p.u.
  280. == model.retiro[i])
  281. model.balance_inyeccion_retiro_constraint= Constraint(model.i,rule=balance_inyeccion_retiro)
  282. def rtmw_min_restriccion(model,c):
  283. return (model.rtmw_c[c] >=-model.rtmw_min[c])
  284. model.rtmw_min_constraint= Constraint(model.c, rule=rtmw_min_restriccion)
  285. def rtmw_max_restriccion(model,c):
  286. return (model.rtmw_c[c] <=model.rtmw_max[c])
  287. model.rtmw_max_constraint= Constraint(model.c, rule=rtmw_max_restriccion)
  288. def flujo_potencia_actica(model,c):
  289. return ((model.Xc[c])*model.rtmw_c[c]+sum(model.Inc[c,i]*model.ref_angular[i] for i in model.i)== 0)
  290. model.flujo_potencia_actica_constraint= Constraint(model.c, rule=flujo_potencia_actica)
  291. # Máximas capacidades de trasferencia entre áreas de control
  292. def eq_mct_ns_rule(model, inter):
  293. if inter=='ES':#Maxima exportacion de El Salvador
  294. return (-(model.DirF[inter]*model.rtmw_c[lin_mct[inter][0]]+model.DirF[inter]*model.rtmw_c[lin_mct[inter][1]]) +
  295. (model.DirF[inter]*model.rtmw_c[lin_mct[inter][2]]+model.DirF[inter]*model.rtmw_c[lin_mct[inter][3]])) <= model.Mct[inter, 'ns', PERIODO] + 0.001
  296. elif inter=='HON':#Maxima importacion de Honduras
  297. return (-(model.DirF[inter]*model.rtmw_c[lin_mct[inter][0]]+model.DirF[inter]*model.rtmw_c[lin_mct[inter][1]] +
  298. model.DirF[inter]*model.rtmw_c[lin_mct[inter][2]]) + (model.DirF[inter]*model.rtmw_c[lin_mct[inter][3]]+
  299. model.DirF[inter]*model.rtmw_c[lin_mct[inter][4]])) <= model.Mct[inter, 'sn', PERIODO] + 0.001
  300. else:
  301. return sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct[inter]) <= model.Mct[inter, 'ns', PERIODO] + 0.001
  302. model.eq_mct_ns = Constraint(model.inter, rule=eq_mct_ns_rule)
  303. def eq_mct_sn_rule(model, inter):
  304. if inter=='ES':#Maxima importacion de El Salvador
  305. return (-(model.DirF[inter]*model.rtmw_c[lin_mct[inter][0]]+model.DirF[inter]*model.rtmw_c[lin_mct[inter][1]]) +
  306. (model.DirF[inter]*model.rtmw_c[lin_mct[inter][2]]+model.DirF[inter]*model.rtmw_c[lin_mct[inter][3]])) >= -model.Mct[inter, 'sn', PERIODO] + 0.00001
  307. elif inter=='HON':#Maxima importacion de Honduras
  308. return (-(model.DirF[inter]*model.rtmw_c[lin_mct[inter][0]]+model.DirF[inter]*model.rtmw_c[lin_mct[inter][1]] +
  309. model.DirF[inter]*model.rtmw_c[lin_mct[inter][2]]) + (model.DirF[inter]*model.rtmw_c[lin_mct[inter][3]]+
  310. model.DirF[inter]*model.rtmw_c[lin_mct[inter][4]])) >= -model.Mct[inter, 'ns', PERIODO] + 0.00001
  311. else:
  312. return sum(model.DirF[inter]*model.rtmw_c[c] for c in lin_mct[inter]) >= -model.Mct[inter, 'sn', PERIODO] + 0.00001
  313. model.eq_mct_sn = Constraint(model.inter, rule=eq_mct_sn_rule)
  314. model.dual = Suffix(direction=Suffix.IMPORT)
  315. print("Construcción del modelo terminada. Periodo: "+str(PERIODO))
  316. opt = SolverFactory('ipopt')
  317. #opt.options['max_iter']= 10000
  318. result = opt.solve(model)
  319. model.solutions.store_to(result)
  320. # Cálculo de Precios Nodales
  321. # =============================================================================
  322. print("Calculando Precios Nodales. Periodo:" + str(PERIODO))
  323. Sigma = zeros(nb)
  324. for i in model.i:
  325. Sigma[i] = model.dual[model.balance_inyeccion_retiro_constraint[i]]
  326. # Construcción de array para grabar
  327. # =============================================================================
  328. flujos=DataFrame()
  329. flujos['Periodo']=set_periodo(nbr,PERIODO)
  330. flujos['BUS I'] = brnames['BUS I']
  331. flujos['BUS J'] = brnames['BUS J']
  332. flujos['CKT'] = brnames['CKT']
  333. f = array(list(model.rtmw_c.get_values().values()))
  334. perdidas=zeros(nbr)
  335. for c in model.c:
  336. perdidas[c]=(f[c]**2)*rc[c]/100
  337. flujos['Flujo'] = f
  338. flujos['Perdidas'] = perdidas
  339. flujos_t=concat([flujos_t,flujos])#Guarda los resultados con los anteriores
  340. pon = DataFrame()
  341. result_inyeccion = array(list(model.inyeccion.get_values().values()))
  342. result_retiro = array(list(model.retiro.get_values().values()))
  343. pon['Periodo']=set_periodo(nb,PERIODO)
  344. pon['nodo']= bus
  345. pon['Precio Exante'] = Sigma*-1
  346. pon_t=concat([pon_t,pon])#Guarda los resultados con los anteriores
  347. #print(pon)
  348. iep=DataFrame()
  349. iep['Periodo']=set_periodo(nb,PERIODO)
  350. iep['nodo']= bus
  351. iep['Inyeccion'] = result_inyeccion
  352. iep['Retiro'] = result_retiro
  353. iep_t=concat([iep_t,iep])#Guarda los resultados con los anteriores
  354. result_pff_iny=array(list(model.pff_iny_fisico.get_values().values()))
  355. result_pff_ret=array(list(model.pff_ret_fisico.get_values().values()))
  356. result_pr = setvariable_p(array(list(model.pr.get_values().values())),NOR)
  357. result_pi = setvariable_p(array(list(model.pi.get_values().values())),NOI)
  358. result_pfi = setvariable_p(array(list(model.pfi.get_values().values())),NCF)
  359. result_pffr = setvariable_p(array(list(model.pffr.get_values().values())),NCFF)
  360. result_pffi = setvariable_p(array(list(model.pffi.get_values().values())),NCFF)
  361. result_pfft = setvariable_p(array(list(model.pfft.get_values().values())),NCFF)
  362. result_foo_r=DataFrame()
  363. result_foo_r['Periodo']=ex_oor['periodo']
  364. result_foo_r['N°']=ex_oor['N°']
  365. result_foo_r['Pr Bloque 1']=result_pr[:,0]
  366. result_foo_r['Pr Bloque 2']=result_pr[:,1]
  367. result_foo_r['Pr Bloque 3']=result_pr[:,2]
  368. result_foo_r['Pr Bloque 4']=result_pr[:,3]
  369. result_foo_r['Pr Bloque 5']=result_pr[:,4]
  370. result_foo_r_t=concat([result_foo_r_t,result_foo_r])#Guarda los resultados con los anteriores
  371. result_foo_i=DataFrame()
  372. result_foo_i['Periodo']=ex_ooi['periodo']
  373. result_foo_i['N°']=ex_ooi['N°']
  374. result_foo_i['Pi Bloque 1']=result_pi[:,0]
  375. result_foo_i['Pi Bloque 2']=result_pi[:,1]
  376. result_foo_i['Pi Bloque 3']=result_pi[:,2]
  377. result_foo_i['Pi Bloque 4']=result_pi[:,3]
  378. result_foo_i['Pi Bloque 5']=result_pi[:,4]
  379. result_foo_i_t=concat([result_foo_i_t,result_foo_i])#Guarda los resultados con los anteriores
  380. result_fof=DataFrame()
  381. result_fof['Periodo']=ex_cf['periodo']
  382. result_fof['N°']=ex_cf['N°']
  383. result_fof['Pfi Bloque 1']=result_pfi[:,0]
  384. result_fof['Pfi Bloque 2']=result_pfi[:,1]
  385. result_fof['Pfi Bloque 3']=result_pfi[:,2]
  386. result_fof['Pfi Bloque 4']=result_pfi[:,3]
  387. result_fof['Pfi Bloque 5']=result_pfi[:,4]
  388. result_fof_t=concat([result_fof_t,result_fof])#Guarda los resultados con los anteriores
  389. result_foff=DataFrame()
  390. result_foff['Periodo']=ex_cnfff['periodo']
  391. result_foff['N°']=ex_cnfff['N°']
  392. result_foff['Pffr Bloque 1']=result_pffr[:,0]
  393. result_foff['Pffr Bloque 2']=result_pffr[:,1]
  394. result_foff['Pffr Bloque 3']=result_pffr[:,2]
  395. result_foff['Pffr Bloque 4']=result_pffr[:,3]
  396. result_foff['Pffr Bloque 5']=result_pffr[:,4]
  397. result_foff['Pffi Bloque 1']=result_pffi[:,0]
  398. result_foff['Pffi Bloque 2']=result_pffi[:,1]
  399. result_foff['Pffi Bloque 3']=result_pffi[:,2]
  400. result_foff['Pffi Bloque 4']=result_pffi[:,3]
  401. result_foff['Pffi Bloque 5']=result_pffi[:,4]
  402. result_foff['Pfft Bloque 1']=result_pfft[:,0]
  403. result_foff['Pfft Bloque 2']=result_pfft[:,1]
  404. result_foff['Pfft Bloque 3']=result_pfft[:,2]
  405. result_foff['Pfft Bloque 4']=result_pfft[:,3]
  406. result_foff['Pfft Bloque 5']=result_pfft[:,4]
  407. result_foff_t=concat([result_foff_t,result_foff])#Guarda los resultados con los anteriores
  408. foo_ret_iny=DataFrame()
  409. foo_ret_iny['Periodo']=ex_cnfff['periodo']
  410. foo_ret_iny['N°']=ex_cnfff['N°']
  411. foo_ret_iny['Inyeccion']=result_pff_iny
  412. foo_ret_iny['Retiro']=result_pff_ret
  413. foo_ret_iny_t=concat([foo_ret_iny_t,foo_ret_iny])#Guarda los resultados con los anteriores
  414. print("Escribiendo resultados en carpeta.")
  415. filename = path.basename(file).split('.')
  416. filepath = path.dirname(file)
  417. new_filename = filename[0]+'_results.'+filename[1]
  418. new_file = path.join(filepath, new_filename)
  419. writer=ExcelWriter(new_file)
  420. flujos_t.to_excel(writer,'IEP-RTR',index=False)
  421. iep_t.to_excel(writer,'IEP-TOTAL',index=False)
  422. pon_t.to_excel(writer,'PEXANTES',index=False)
  423. result_foo_i_t.to_excel(writer,'TOP-I',index=False)
  424. result_foo_r_t.to_excel(writer,'TOP-R',index=False)
  425. result_fof_t.to_excel(writer,'TCP-CF',index=False)
  426. result_foff_t.to_excel(writer,'TCP-CNFFF-1',index=False)
  427. foo_ret_iny_t.to_excel(writer,'TCP-CNFFF-2',index=False)
  428. writer.save()
  429. print("{:=^100}".format(""))
  430. print("{:^100}".format(" Script Finalizado "))
  431. print("{:^100}".format(" Mercados Eléctricos de Centroamérica (c) 2020 "))
  432. print("{:=^100}".format(""))
  433. return 0