Future-Power-Networks / MAPDN

This repository is for an open-source environment for multi-agent active voltage control on power distribution networks (MAPDN).
MIT License
203 stars 55 forks source link

Why is reactive power loss defined as “q = self.powergrid.res_sgen["q_mvar"].sort_index().to_numpy(copy=True)” #8

Closed zly987 closed 2 years ago

zly987 commented 2 years ago

code in voltage_control_env.py

    # reactive power (q) loss 
    q = self.powergrid.res_sgen["q_mvar"].sort_index().to_numpy(copy=True)
    q_loss = np.mean(np.abs(q))

1.Why is reactive power loss defined as “q = self.powergrid.res_sgen["q_mvar"].sort_index().to_numpy(copy=True)”?

  1. "q_loss = np.mean(np.abs(q))" How do I understand this code?

Thank you very much for answering my question in your busy schedule.

xuwkk commented 2 years ago

Thanks for the question. We consider the term pv reactive power (e.g. in eq(2) of our paper) as a penalization on minimizing voltage deviation. The pv reactive power is minimized, e.g. to increase the power factor and reduces the line flow burdens. Meanwhile, as can be shown by eq.3 in supplementary file, large amount of pv reactive power can also increase the power loss.

zly987 commented 2 years ago

code in voltage_control_env.py

    def get_state(self):    
    """return the global state for the power system
       the default state: voltage, active power of generators, bus state, load active power, load reactive power
    """
    state = []
    if "demand" in self.state_space:
        state += list(self.powergrid.res_bus["p_mw"].sort_index().to_numpy(copy=True))
        state += list(self.powergrid.res_bus["q_mvar"].sort_index().to_numpy(copy=True))
    if "pv" in self.state_space:
        state += list(self.powergrid.sgen["p_mw"].sort_index().to_numpy(copy=True))
    if "reactive" in self.state_space:
        state += list(self.powergrid.sgen["q_mvar"].sort_index().to_numpy(copy=True))
    if "vm_pu" in self.state_space:
        state += list(self.powergrid.res_bus["vm_pu"].sort_index().to_numpy(copy=True))
    if "va_degree" in self.state_space:
        state += list(self.powergrid.res_bus["va_degree"].sort_index().to_numpy(copy=True))
    state = np.array(state)
    return state

1.Why is ''state of pv_active=self.powergrid.sgen["p_mw"]'' "state of pv_reactive=self.powergrid.sgen["q_mvar"]"? not as "state of pv_active=self.powergrid.res_sgen["p_mw"]'' "state of pv_reactive=self.powergrid.res_sgen["q_mvar"]"?

hsvgbkhgbv commented 2 years ago

Hi,

Since sgen is not set to be optimized in power flow calculation, sgen and res_sgen are equal after power flow calculation and either one is feasible to be used as a feature of the next state.

zly987 commented 2 years ago

OK,I got it,but I have some new questions. Q1: Such as : manual_reset(1095,0,0) self.pv_histories = self.pv_data[525600:525842].values ,The time frame within 2014,12.31,00:03 to 2014,12.31,12:06

`# get one episode of data
        self.pv_histories = self._get_episode_pv_history()
        self.active_demand_histories = self._get_episode_active_demand_history()
        self.reactive_demand_histories = self._get_episode_reactive_demand_history()
        self._set_demand_and_pv()`

    ` def _get_pv_history(self):  
    """returns pv history
    """
    t = self.steps  
    history = self.history
    return self.pv_histories[t:t+history, :]`

In the above code, fuction _set_demand_and_pv() return pv = pv_histories[1:2,:], that is data for 2014,12.31,00:06,why not data for 2014,12.31,00:03? why not first data of pv_histories but second data of pv_histories?

Q2: During training, you randomly sample the initial state for an episode and each episode lasts for 240 time steps (i.e. a half day). Why is the testing each episode lasts for 480 time steps?I've been looking for it for a long time, I don't found in code set 480 time steps.Please point it out for me,Thank you very much!

Q3: I'm a little confused about the training process,You mentioned in the article "you randomly sample the initial state for an episode and each episode lasts for 240 time steps". Does it mean to extract one time section data (training data, such as pv_active data), and then continue for 240 steps, and then extract the next time section data? Or take one step to extract a time section data. I comprehend the the former,But looking at the code carefully, I'm not sure. Please help me!

Thank you very much!

hsvgbkhgbv commented 2 years ago

Answer for Q1: This is since our original data structure is one time resolution delay, but for the published data we fixed it. So, you can adjust it to starting from the initial point, however, it would not change too much for training.

Answer for Q2: There are two reasons. The first reason is that if setting the episode as a whole day the training time would become so long (though you can do it if you don't care the training time). The second reason is that we would like to test the generalization of the trained agents, since in realistic situations it is difficult (or impossible) to collect a full episode of data.

Answer for Q3: If I understand your words correctly, "Does it mean to extract one time section data (training data, such as pv_active data), and then continue for 240 steps, and then extract the next time section data?" should be the answer.

zly987 commented 2 years ago

OK, I got it. Thank you very much!