yg-smile / RL_VVC_dataset

A Reinforcement Learning-based Volt-VAR Control Dataset
MIT License
20 stars 7 forks source link

Question about Data Generation #7

Open Awii0709 opened 9 months ago

Awii0709 commented 9 months ago

Dear @yg-smile,

Can you describe how you generated data for offline training. It would be much appreciated if you could share how you solved the opendss script for offline training with relevant modes.

Thank you.

yg-smile commented 9 months ago

Hi @Awii0709,

The data for offline training are generated by follows:

  1. Download the London smart meter data and preprocess them using this notebook: https://github.com/yg-smile/RL_VVC_dataset/blob/9546fa468d00ed5f0b4b2a7872d24eff464e4b6f/data/pipeline.ipynb
  2. Provide the load to the opendss code and solve the powerflow. I believe the following script solved the opendss script with relevant modes
import opendssdirect as dss
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from tqdm import tqdm
from env_123_utils import load_base, load_node
from collections import OrderedDict

# the reference of this code is at:
# https://dss-extensions.org/OpenDSSDirect.py/index.html

# load circuit model
dss.run_command('Redirect IEEE_123dss/IEEE123Master.dss')
dss.run_command('Set Controlmode=STATIC')

all_transformer_names = dss.Transformers.AllNames()
all_regulator_names = dss.RegControls.AllNames()
all_capacitor_names = dss.Capacitors.AllNames()

print('Num of LTC: {}'.format(len(all_regulator_names)))
print('Num of CAP: {}'.format(len(all_capacitor_names)))

# load london dataset
skip_first = 0  # ignoring rows which contain too many nan's
df = pd.read_csv('../data/processed/first_2897_ami_aggto_580.csv', index_col=0)
df = df.iloc[skip_first:, :]
df = df / (df.mean() * 1.0)  # normalize each column

# plt.figure(1)
# for i, k in enumerate(load_base.keys()):
#     plt.plot(df.iloc[:2000, i].to_numpy(), label=k)
# plt.legend()
# plt.grid()
# plt.title('normalized profile')

volt_all = []
load_all = []
tap_all = []
status_all = []

load_mode = 'I'
model = {'PQ': 1,
         'Z': 2,
         'I': 5}

def tappu_to_tap(tap_pu):
    pu_per_ltc_tap = 5 / 8 / 100
    tap = (tap_pu - 1.0) / pu_per_ltc_tap + 16
    return tap

for t in tqdm(range(df.shape[0])):
    # change some load
    # hint: https://githubmemory.com/repo/dss-extensions/OpenDSSDirect.py/issues/86

    load_kw = [val[0] * df.iloc[t, i] for i, (key, val) in enumerate(load_base.items())]
    load_kvar = [val[1] * df.iloc[t, i] for i, (key, val) in enumerate(load_base.items())]

    for i, (key, val) in enumerate(load_base.items()):
        dss.run_command('Load.{}.kW={}'.format(key, load_kw[i]))
    for i, (key, val) in enumerate(load_base.items()):
        dss.run_command('Load.{}.kvar={}'.format(key, load_kvar[i]))

    # solve power flow and get results
    dss.Solution.Solve()

    converged = dss.Solution.Converged()
    if not converged:
        print('Non-converging power flow')
        break

    # network loss
    ll = dss.Circuit.Losses()

    # get voltage magnitude by bus name:
    # ref.1: https://sourceforge.net/p/electricdss/discussion/861977/thread/a53badb5/
    # ref.2: https://github.com/dss-extensions/OpenDSSDirect.py/issues/15
    v_all = []
    for bus in load_node.keys():
        dss.Circuit.SetActiveBus(bus)
        # https: // github.com / dss - extensions / OpenDSSDirect.py / blob / master / opendssdirect / Bus.py
        v_mag_angle = dss.Bus.puVmagAngle()
        # (read-only) Array of doubles containing voltage magnitude, angle pairs in per unit
        v = v_mag_angle[::2]
        if load_node[bus]:
            for i in range(len(load_node[bus])):
                v_all.append(v[i])
        else:
            v_all.append(v[0])

    # LTC taps in per unit
    tap = []
    dss.Transformers.First()  # activate the first transformer
    dss.Transformers.Next()  # our LTC starts from the second one
    tap_pu = dss.Transformers.Tap()
    tap.append(tappu_to_tap(tap_pu))

    dss.Transformers.Next()  # our LTC starts from the second one
    tap_pu = dss.Transformers.Tap()
    tap.append(tappu_to_tap(tap_pu))

    dss.Transformers.Next()  # our LTC starts from the second one
    tap_pu = dss.Transformers.Tap()
    tap.append(tappu_to_tap(tap_pu))

    dss.Transformers.Next()  # our LTC starts from the second one
    tap_pu = dss.Transformers.Tap()
    tap.append(tappu_to_tap(tap_pu))

    dss.Transformers.Next()  # our LTC starts from the second one
    tap_pu = dss.Transformers.Tap()
    tap.append(tappu_to_tap(tap_pu))

    # capacitor status
    dss.Capacitors.First()
    cap1_state = dss.Capacitors.States()
    dss.Capacitors.Next()
    cap2_state = dss.Capacitors.States()
    dss.Capacitors.Next()
    cap3_state = dss.Capacitors.States()
    dss.Capacitors.Next()
    cap4_state = dss.Capacitors.States()

    volt_all.append(np.around(np.array(v_all) * 120.0, decimals=1))
    load_all.append(np.around(np.array(load_kw + load_kvar), decimals=1))
    tap_all.append(np.array(tap).astype(int))
    status_all.append(np.array(cap1_state + cap2_state + cap3_state + cap4_state).astype(int))

volt_all = np.array(volt_all)
load_all = np.array(load_all)
tap_all = np.array(tap_all)
status_all = np.array(status_all)

np.savetxt('../data/processed/IEEE_123/volt.csv', volt_all, delimiter=",")
np.savetxt('../data/processed/IEEE_123/load.csv', load_all, delimiter=",")
np.savetxt('../data/processed/IEEE_123/tap.csv', tap_all, delimiter=",")
np.savetxt('../data/processed/IEEE_123/status.csv', status_all, delimiter=",")
np.savetxt('../data/processed/IEEE_123/timestamp.csv', np.arange(df.shape[0])[:, None], delimiter=",")

and env_123_utils:

from collections import OrderedDict

# load_base: key=name of load object in the dss script
#            value=(kw, k-var)
# the actual load in each timestamp will be load_base multiplied by the scaled London AMI data-set

load_base = OrderedDict([
    ('S1a', (40.0, 20.0)),  #load name: (kw, k-var)
    ('S2b', (20.0, 10.0)),
    ('S4c', (40.0, 20.0)),
    ('S5c', (20.0, 10.0)),
    ('S6c', (40.0, 20.0)),
    ('S7a', (20.0, 10.0)),
    ('S9a', (40.0, 20.0)),
    ('S10a', (20.0, 10.0)),
    ('S11a', (40.0, 20.0)),
    ('S12b', (20.0, 10.0)),
    ('S16c', (40.0, 20.0)),
    ('S17c', (20.0, 10.0)),
    ('S19a', (40.0, 20.0)),
    ('S20a', (40.0, 20.0)),
    ('S22b', (40.0, 20.0)),
    ('S24c', (40.0, 20.0)),
    ('S28a', (40.0, 20.0)),
    ('S29a', (40.0, 20.0)),
    ('S30c', (40.0, 20.0)),
    ('S31c', (20.0, 10.0)),
    ('S32c', (20.0, 10.0)),
    ('S33a', (40.0, 20.0)),
    ('S34c', (40.0, 20.0)),
    ('S35a', (40.0, 20.0)),
    ('S37a', (40.0, 20.0)),
    ('S38b', (20.0, 10.0)),
    ('S39b', (20.0, 10.0)),
    ('S41c', (20.0, 10.0)),
    ('S42a', (20.0, 10.0)),
    ('S43b', (40.0, 20.0)),
    ('S45a', (20.0, 10.0)),
    ('S46a', (20.0, 10.0)),
    ('S47', (105.0, 75.0)),
    ('S48', (210.0, 150.0)),
    ('S49a', (35.0, 25.0)),
    ('S49b', (70.0, 50.0)),
    ('S49c', (35.0, 20.0)),
    ('S50c', (40.0, 20.0)),
    ('S51a', (20.0, 10.0)),
    ('S52a', (40.0, 20.0)),
    ('S53a', (40.0, 20.0)),
    ('S55a', (20.0, 10.0)),
    ('S56b', (20.0, 10.0)),
    ('S58b', (20.0, 10.0)),
    ('S59b', (20.0, 10.0)),
    ('S60a', (20.0, 10.0)),
    ('S62c', (40.0, 20.0)),
    ('S63a', (40.0, 20.0)),
    ('S64b', (75.0, 35.0)),
    ('S65a', (35.0, 25.0)),
    ('S65b', (35.0, 25.0)),
    ('S65c', (70.0, 50.0)),
    ('S66c', (75.0, 35.0)),
    ('S68a', (20.0, 10.0)),
    ('S69a', (40.0, 20.0)),
    ('S70a', (20.0, 10.0)),
    ('S71a', (40.0, 20.0)),
    ('S73c', (40.0, 20.0)),
    ('S74c', (40.0, 20.0)),
    ('S75c', (40.0, 20.0)),
    ('S76a', (105.0, 80.0)),
    ('S76b', (70.0, 50.0)),
    ('S76c', (70.0, 50.0)),
    ('S77b', (40.0, 20.0)),
    ('S79a', (40.0, 20.0)),
    ('S80b', (40.0, 20.0)),
    ('S82a', (40.0, 20.0)),
    ('S83c', (20.0, 10.0)),
    ('S84c', (20.0, 10.0)),
    ('S85c', (40.0, 20.0)),
    ('S86b', (20.0, 10.0)),
    ('S87b', (40.0, 20.0)),
    ('S88a', (40.0, 20.0)),
    ('S90b', (40.0, 20.0)),
    ('S92c', (40.0, 20.0)),
    ('S94a', (40.0, 20.0)),
    ('S95b', (20.0, 10.0)),
    ('S96b', (20.0, 10.0)),
    ('S98a', (40.0, 20.0)),
    ('S99b', (40.0, 20.0)),
    ('S100c', (40.0, 20.0)),
    ('S102c', (20.0, 10.0)),
    ('S103c', (40.0, 20.0)),
    ('S104c', (40.0, 20.0)),
    ('S106b', (40.0, 20.0)),
    ('S107b', (40.0, 20.0)),
    ('S109a', (40.0, 20.0)),
    ('S111a', (20.0, 10.0)),
    ('S112a', (20.0, 10.0)),
    ('S113a', (40.0, 20.0)),
    ('S114a', (20.0, 10.0)),
])

# load_node: key=name of load object in the dss script
#            value= phases of the load. Must be in the order (a,b,c)
load_node = OrderedDict([
    ('1', 'a'),  # (kw, k-var)
    ('2', 'b'),
    ('4', 'c'),
    ('5', 'c'),
    ('6', 'c'),
    ('7', 'a'),
    ('9', 'a'),
    ('10', 'a'),
    ('11', 'a'),
    ('12', 'b'),
    ('16', 'c'),
    ('17', 'c'),
    ('19', 'a'),
    ('20', 'a'),
    ('22', 'b'),
    ('24', 'c'),
    ('28', 'a'),
    ('29', 'a'),
    ('30', 'c'),
    ('31', 'c'),
    ('32', 'c'),
    ('33', 'a'),
    ('34', 'c'),
    ('35', 'a'),
    ('37', 'a'),
    ('38', 'b'),
    ('39', 'b'),
    ('41', 'c'),
    ('42', 'a'),
    ('43', 'b'),
    ('45', 'a'),
    ('46', 'a'),
    ('47', ''),
    ('48', ''),
    ('49', 'a'),
    ('49', 'b'),
    ('49', 'c'),
    ('50', 'c'),
    ('51', 'a'),
    ('52', 'a'),
    ('53', 'a'),
    ('55', 'a'),
    ('56', 'b'),
    ('58', 'b'),
    ('59', 'b'),
    ('60', 'a'),
    ('62', 'c'),
    ('63', 'a'),
    ('64', 'b'),
    ('65', 'a'),
    ('65', 'b'),
    ('65', 'c'),
    ('66', 'c'),
    ('68', 'a'),
    ('69', 'a'),
    ('70', 'a'),
    ('71', 'a'),
    ('73', 'c'),
    ('74', 'c'),
    ('75', 'c'),
    ('76', 'a'),
    ('76', 'b'),
    ('76', 'c'),
    ('77', 'b'),
    ('79', 'a'),
    ('80', 'b'),
    ('82', 'a'),
    ('83', 'c'),
    ('84', 'c'),
    ('85', 'c'),
    ('86', 'b'),
    ('87', 'b'),
    ('88', 'a'),
    ('90', 'b'),
    ('92', 'c'),
    ('94', 'a'),
    ('95', 'b'),
    ('96', 'b'),
    ('98', 'a'),
    ('99', 'b'),
    ('100', 'c'),
    ('102', 'c'),
    ('103', 'c'),
    ('104', 'c'),
    ('106', 'b'),
    ('107', 'b'),
    ('109', 'a'),
    ('111', 'a'),
    ('112', 'a'),
    ('113', 'a'),
    ('114', 'a'),
    ])