Source code for VeraGridEngine.Simulations.PowerFlow.power_flow_ts_input

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0

import numpy as np
import pandas as pd


[docs] class PowerFlowTimeSeriesInput: def __init__(self, s_profile: pd.DataFrame = None, i_profile: pd.DataFrame = None, y_profile: pd.DataFrame = None): """ Time series input @param s_profile: DataFrame with the profile of the injected power at the buses @param i_profile: DataFrame with the profile of the injected current at the buses @param y_profile: DataFrame with the profile of the shunt admittance at the buses """ # master time array. All the profiles must match its length self.time_array = None self.Sprof = s_profile self.Iprof = i_profile self.Yprof = y_profile # Array of load admittances (shunt) self.Y = None # Array of load currents self.I = None # Array of aggregated bus power (loads, generators, storage, etc...) self.S = None # is this timeSeriesInput valid? typically it is valid after compiling it self.valid = False
[docs] def compile(self): """ Generate time-consistent arrays @return: """ cols = list() self.valid = False merged = None for profile in [self.Sprof, self.Iprof, self.Yprof]: if profile is None: cols.append(None) else: if merged is None: merged = profile else: merged = pd.concat([merged, profile], axis=1) cols.append(profile.columns) self.valid = True # by merging there could have been time inconsistencies that would produce NaN # to solve it we "interpolate" by replacing the NaN by the nearest value if merged is not None: merged.interpolate(method='nearest', axis=0, inplace=True) t, n = merged.shape # pick the merged series time self.time_array = merged.index.values # Array of aggregated bus power (loads, generators, storage, etc...) if cols[0] is not None: self.S = merged[cols[0]].values else: self.S = np.zeros((t, n), dtype=complex) # Array of load currents if cols[1] is not None: self.I = merged[cols[1]].values else: self.I = np.zeros((t, n), dtype=complex) # Array of load admittances (shunt) if cols[2] is not None: self.Y = merged[cols[2]].values else: self.Y = np.zeros((t, n), dtype=complex)
[docs] def get_at(self, t): """ Returns the necessary values @param t: time index @return: """ return self.Y[t, :], self.I[t, :], self.S[t, :]
[docs] def get_from_buses(self, bus_idx): """ @param bus_idx: @return: """ ts = PowerFlowTimeSeriesInput() ts.S = self.S[:, bus_idx] ts.I = self.I[:, bus_idx] ts.Y = self.Y[:, bus_idx] ts.valid = True return ts
# def apply_from_island(self, res, bus_original_idx, branch_original_idx, nbus_full, nbranch_full): # """ # # :param res: TimeSeriesInput # :param bus_original_idx: # :param branch_original_idx: # :param nbus_full: # :param nbranch_full: # :return: # """ # # if res is not None: # if self.Sprof is None: # self.time_array = res.time_array # # t = len(self.time_array) # self.Sprof = pd.DataFrame() # zeros((t, nbus_full), dtype=complex) # self.Iprof = pd.DataFrame() # zeros((t, nbranch_full), dtype=complex) # self.Yprof = pd.DataFrame() # zeros((t, nbus_full), dtype=complex) # # self.Sprof[res.Sprof.columns.values] = res.Sprof # self.Iprof[res.Iprof.columns.values] = res.Iprof # self.Yprof[res.Yprof.columns.values] = res.Yprof
[docs] def copy(self): cpy = PowerFlowTimeSeriesInput() # master time array. All the profiles must match its length cpy.time_array = self.time_array cpy.Sprof = self.Sprof.copy() cpy.Iprof = self.Iprof.copy() cpy.Yprof = self.Yprof.copy() # Array of load admittances (shunt) cpy.Y = self.Y.copy() # Array of load currents cpy.I = self.I.copy() # Array of aggregated bus power (loads, generators, storage, etc...) cpy.S = self.S.copy() # is this timeSeriesInput valid? typically it is valid after compiling it cpy.valid = self.valid return cpy