From f8503728b5f238c825ea2b63567b0261e3c8d9eb Mon Sep 17 00:00:00 2001 From: jinningwang Date: Sun, 17 Dec 2023 09:43:36 -0500 Subject: [PATCH] Refactor RTED --- ams/routines/ed.py | 2 +- ams/routines/rted.py | 90 ++++++++++++++++++++++---------------------- ams/routines/uc.py | 6 ++- 3 files changed, 50 insertions(+), 48 deletions(-) diff --git a/ams/routines/ed.py b/ams/routines/ed.py index cba07982..80c0a493 100644 --- a/ams/routines/ed.py +++ b/ams/routines/ed.py @@ -20,7 +20,7 @@ class SRBase: """ Base class for spinning reserve. """ - + def __init__(self) -> None: self.dsrp = RParam(info='spinning reserve requirement in percentage', name='dsr', tex_name=r'd_{sr}', diff --git a/ams/routines/rted.py b/ams/routines/rted.py index 7215dda9..89d49fb2 100644 --- a/ams/routines/rted.py +++ b/ams/routines/rted.py @@ -14,15 +14,12 @@ logger = logging.getLogger(__name__) -class RTEDBase(DCOPF): +class RTEDBase: """ Base class for real-time economic dispatch (RTED). - - Overload ``dc2ac``, ``run``. """ - def __init__(self, system, config): - DCOPF.__init__(self, system, config) + def __init__(self): # --- region --- self.zg = RParam(info='Gen zone', name='zg', tex_name='z_{one,g}', @@ -46,7 +43,6 @@ def __init__(self, system, config): name='pdz', tex_name=r'p_{d,z}', unit='p.u.', info='zonal total load', no_parse=True,) - # --- generator --- self.R10 = RParam(info='10-min ramp rate', name='R10', tex_name=r'R_{10}', @@ -60,9 +56,7 @@ class SFRBase: """ def __init__(self): - - # 1. reserve - # --- reserve cost --- + # --- SFR cost --- self.cru = RParam(info='RegUp reserve coefficient', name='cru', tex_name=r'c_{r,u}', model='SFRCost', src='cru', @@ -82,9 +76,37 @@ def __init__(self): name='dd', tex_name=r'd_{d}', model='SFR', src='dd', unit='%', no_parse=True,) + self.dud = NumOpDual(u=self.pdz, u2=self.du, fun=np.multiply, + rfun=np.reshape, rargs=dict(newshape=(-1,)), + name='dud', tex_name=r'd_{u, d}', + info='zonal RegUp reserve requirement',) + self.ddd = NumOpDual(u=self.pdz, u2=self.dd, fun=np.multiply, + rfun=np.reshape, rargs=dict(newshape=(-1,)), + name='ddd', tex_name=r'd_{d, d}', + info='zonal RegDn reserve requirement',) + # --- SFR --- + self.pru = Var(info='RegUp reserve', + unit='p.u.', name='pru', tex_name=r'p_{r,u}', + model='StaticGen', nonneg=True,) + self.prd = Var(info='RegDn reserve', + unit='p.u.', name='prd', tex_name=r'p_{r,d}', + model='StaticGen', nonneg=True,) + # NOTE: define e_str in dispatch routine + self.rbu = Constraint(name='rbu', type='eq', + info='RegUp reserve balance',) + self.rbd = Constraint(name='rbd', type='eq', + info='RegDn reserve balance',) + self.rru = Constraint(name='rru', type='uq', + info='RegUp reserve source',) + self.rrd = Constraint(name='rrd', type='uq', + info='RegDn reserve source',) + self.rgu = Constraint(name='rgu', type='uq', + info='Gen ramping up',) + self.rgd = Constraint(name='rgd', type='uq', + info='Gen ramping down',) -class RTED(RTEDBase, SFRBase): +class RTED(DCOPF, RTEDBase, SFRBase): """ DC-based real-time economic dispatch (RTED). RTED extends DCOPF with: @@ -115,7 +137,8 @@ class RTED(RTEDBase, SFRBase): """ def __init__(self, system, config): - RTEDBase.__init__(self, system, config) + DCOPF.__init__(self, system, config) + RTEDBase.__init__(self) SFRBase.__init__(self) self.config.add(OrderedDict((('t', 5/60), @@ -143,41 +166,18 @@ def __init__(self, system, config): self.info = 'Real-time economic dispatch' self.type = 'DCED' - # --- vars --- - self.pru = Var(info='RegUp reserve', - unit='p.u.', name='pru', tex_name=r'p_{r,u}', - model='StaticGen', nonneg=True,) - self.prd = Var(info='RegDn reserve', - unit='p.u.', name='prd', tex_name=r'p_{r,d}', - model='StaticGen', nonneg=True,) + # --- Model Section --- + # --- SFR --- + # RegUp/Dn reserve balance + self.rbu.e_str = 'gs @ mul(ug, pru) - dud' + self.rbd.e_str = 'gs @ mul(ug, prd) - ddd' + # RegUp/Dn reserve source + self.rru.e_str = 'mul(ug, pg + pru) - mul(ug, pmax)' + self.rrd.e_str = 'mul(ug, -pg + prd) - mul(ug, pmin)' + # Gen ramping up/down + self.rgu.e_str = 'mul(ug, pg-pg0-R10)' + self.rgd.e_str='mul(ug, -pg+pg0-R10)' - # --- constraints --- - self.dud = NumOpDual(u=self.pdz, u2=self.du, fun=np.multiply, - rfun=np.reshape, rargs=dict(newshape=(-1,)), - name='dud', tex_name=r'd_{u, d}', - info='zonal RegUp reserve requirement',) - self.ddd = NumOpDual(u=self.pdz, u2=self.dd, fun=np.multiply, - rfun=np.reshape, rargs=dict(newshape=(-1,)), - name='ddd', tex_name=r'd_{d, d}', - info='zonal RegDn reserve requirement',) - self.rbu = Constraint(name='rbu', type='eq', - info='RegUp reserve balance', - e_str='gs @ mul(ug, pru) - dud',) - self.rbd = Constraint(name='rbd', type='eq', - info='RegDn reserve balance', - e_str='gs @ mul(ug, prd) - ddd',) - self.rru = Constraint(name='rru', type='uq', - info='RegUp reserve source', - e_str='mul(ug, pg + pru) - mul(ug, pmax)',) - self.rrd = Constraint(name='rrd', type='uq', - info='RegDn reserve source', - e_str='mul(ug, -pg + prd) - mul(ug, pmin)',) - self.rgu = Constraint(name='rgu', type='uq', - info='Gen ramping up', - e_str='mul(ug, pg-pg0-R10)',) - self.rgd = Constraint(name='rgd', type='uq', - info='Gen ramping down', - e_str='mul(ug, -pg+pg0-R10)',) # --- objective --- self.obj.info = 'total generation and reserve cost' # NOTE: the product of dt and pg is processed using ``dot``, diff --git a/ams/routines/uc.py b/ams/routines/uc.py index 1921bfe3..4cee283f 100644 --- a/ams/routines/uc.py +++ b/ams/routines/uc.py @@ -8,6 +8,7 @@ from ams.core.param import RParam from ams.core.service import (NumOp, NumOpDual, MinDur) +from ams.routines.dcopf import DCOPF from ams.routines.rted import RTEDBase from ams.routines.ed import SRBase, MPBase, ESD1MPBase @@ -51,7 +52,7 @@ def __init__(self) -> None: name='rnsr', type='uq',) -class UC(RTEDBase, MPBase, SRBase, NSRBase): +class UC(DCOPF, RTEDBase, MPBase, SRBase, NSRBase): """ DC-based unit commitment (UC). The bilinear term in the formulation is linearized with big-M method. @@ -84,7 +85,8 @@ class UC(RTEDBase, MPBase, SRBase, NSRBase): """ def __init__(self, system, config): - RTEDBase.__init__(self, system, config) + DCOPF.__init__(self, system, config) + RTEDBase.__init__(self) MPBase.__init__(self) SRBase.__init__(self) NSRBase.__init__(self)