From 7188333dbd46e5006df11525ce1a8267b09376a1 Mon Sep 17 00:00:00 2001 From: jliang9 <101606229+jliang9@users.noreply.github.com> Date: Mon, 19 Sep 2022 16:59:54 -0600 Subject: [PATCH 1/2] Adding limits --- wls_federate/state_estimator_federate.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/wls_federate/state_estimator_federate.py b/wls_federate/state_estimator_federate.py index 23f77dc..8adfc59 100644 --- a/wls_federate/state_estimator_federate.py +++ b/wls_federate/state_estimator_federate.py @@ -155,15 +155,17 @@ def state_estimator(parameters: AlgorithmParameters, topology, P, Q, V, initial_ logging.debug(delta) X0 = np.concatenate((delta, Vabs)) logging.debug(X0) + ang_low = np.concatenate(([-1e-5], np.ones(num_node -1)* (- np.inf))) + ang_up = np.concatenate(([1e-5], np.ones(num_node -1)* ( np.inf))) + mag_low = np.ones(num_node)* (- np.inf) + mag_up = np.ones(num_node)* (np.inf) + low_limit = np.concatenate((ang_low, mag_low)) + up_limit = np.concatenate((ang_up, mag_up)) # Weights are ignored since errors are sampled from Gaussian # Real dimension of solutions is # 2 * num_node - len(knownP) - len(knownV) - len(knownQ) if len(knownP) + len(knownV) + len(knownQ) < num_node * 2: #If not observable - low_limit = np.concatenate((np.ones(num_node)* (- np.pi - np.pi/6), - np.ones(num_node)*0.90)) - up_limit = np.concatenate((np.ones(num_node)* (np.pi + np.pi/6), - np.ones(num_node)*1.05)) res_1 = least_squares( residual, X0, @@ -181,7 +183,7 @@ def state_estimator(parameters: AlgorithmParameters, topology, P, Q, V, initial_ residual, X0, jac=cal_H, - # bounds = (low_limit, up_limit), + bounds = (low_limit, up_limit), #method = 'lm', verbose=2, ftol=tol, From 1f8ede15e785c28c61222b5cf290e1f7b8a71f47 Mon Sep 17 00:00:00 2001 From: jliang9 <101606229+jliang9@users.noreply.github.com> Date: Tue, 20 Sep 2022 13:51:12 -0600 Subject: [PATCH 2/2] Using flat start for initial V if observable --- wls_federate/state_estimator_federate.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/wls_federate/state_estimator_federate.py b/wls_federate/state_estimator_federate.py index 8adfc59..7672b4d 100644 --- a/wls_federate/state_estimator_federate.py +++ b/wls_federate/state_estimator_federate.py @@ -274,21 +274,21 @@ def run(self): slack_index = i voltages = VoltagesMagnitude.parse_obj(self.sub_voltages_magnitude.json) + power_Q = PowersImaginary.parse_obj(self.sub_power_Q.json) + power_P = PowersReal.parse_obj(self.sub_power_P.json) + knownP = get_indices(topology, power_P) + knownQ = get_indices(topology, power_Q) knownV = get_indices(topology, voltages) + if self.initial_V is None: - self.initial_V = np.mean( - np.array(voltages.values) / np.array(topology.base_voltage_magnitudes.values)[knownV]) - - #if self.initial_V is None: - # self.initial_V = 1.025 #*np.array(topology.base_voltages) + #Flat start or using average measurements + if len(knownP) + len(knownV) + len(knownQ) > len(topology.admittance.ids) * 2: + self.initial_V = 1.0 + else: + self.initial_V = np.mean(np.array(voltages.values) / np.array(topology.base_voltage_magnitudes.values)[knownV]) if self.initial_ang is None: self.initial_ang = np.array(topology.base_voltage_angles.values) - - - power_P = PowersReal.parse_obj(self.sub_power_P.json) - power_Q = PowersImaginary.parse_obj(self.sub_power_Q.json) - voltage_magnitudes, voltage_angles = state_estimator( self.algorithm_parameters, topology, power_P, power_Q, voltages, initial_V=self.initial_V,