#ifndef ENSH #define ENSH /***************************************************************************************** * ENS 1.0 - Electric Network Simulator * * Author: * * Lluís Ros (c) 1995-2007 * Institut de Robōtica i Informātica Industrial (CSIC-UPC) * Llorens Artigas 4-6, 2a planta * 08028 Barcelona * Web: http://www-iri.upc.es/people/ros * E-mail: llros@iri.upc.es * * What is ENS? * * ENS is a library of functions to simulate the state of an electric * distribution network. The simulator implements, with minor variations, * the sweeping/compensation method by Luo and Semlyen, published in * * G. X. Luo and A. Semlyen. "Efficient load flow for large weakly * meshed networks", IEEE Trans. on Power Systems, Vol. 5, No. 4, * November 1990. * * Associated files: * * ens.c, ens.h - functions to simulate the network * glr.c, glr.h - functions to handle the network graph * llr.c, llr.h - functions to handle lists * * Conditions of use: * * The following software may be used by anyone (hereafter the "user") agreeing with the * following conditions: * * 1. The user will only use the software for nonprofit, nonmilitary purposes. * Any commercial use of this software requires the obtention of an appropriate * software license jointly issued by the author and the Institut de Robōtica * i Informātica Industrial (UPC/CSIC). Should you be interested in such license, * please contact the author at the address above. * 2. On any publication reporting results using this software, the user commits * to make a reference to the software, as follows: * * L. Ros, "ENS: An Electric Network Simulator for Distribution * Networks". Institut de Robōtica i Informātica Industrial, Barcelona, * Spain. Available through http://www-iri.upc.es/people/ros * * 3. The user will report the software's author about any trouble he meets in the use of * this software. The author will remove bugs, if any, at his earliest convenience. * 4. The author assumes no responsibility for any trouble or damage caused by the * user when using this software for any purpose. * 5. The user will notify the author (to the address given above) that she will use the * software. In her notification the user is asked to please identify herself, to state * she accepts these conditions, and briefly report the purpose for which the software * will be used. * * The functions are organized into the following sections: * * Section 1 - Network constructors * Functions to read an electric network from file * Section 2 - Network destructors * Functions to destroy an electric network * Section 3 - Network simulations * Functions to compute a power flow (for the moment) * Section 4 - Network manoeuvers * Functions to open/close switches and locally recompute the network state * Section 5 - Miscellaneous functions * Miscellaneous functions * *********************************************************************************************/ #include #include #include #include #include #include "glr.h" #include "complex.h" /*********************************************************** * Numerical Recipes declarations ***********************************************************/ #include "ens_nrutil.h" void dludcmp(double **a, int n, int *indx, double *d); void dlubksb(double** a, int n, int* indx, double* b); /*********************************************************** * Location of network data files ***********************************************************/ #define DATA_PATH "/home/ros/ens/data/" #define AREAS_FILENAME "areas.dis" #define AREA_SWITCHES_FILENAME "area_switches.dis" /*********************************************************** * Specific_vertex_data and its accessor macros ***********************************************************/ typedef unsigned int vertex_id_type; typedef unsigned int edge_id_type; typedef unsigned int area_id_type; typedef struct{ vertex_id_type vertex_id; /* Vertex identifyer */ area_id_type vertex_area; /* Area to which the vertex belongs */ int vertex_state; /* Defines whether the vertex is energized (see below) */ int vertex_type; /* Type of the vertex (see below) */ dcomplex vertex_injected_pwr; /* Injected complex power of this vertex */ dcomplex vertex_accumulated_pwr; /* Accumulated complex power on downstream tree */ dcomplex vertex_voltage; /* Complex voltage of the vertex */ double vertex_base_voltage; /* Base voltage of this vertex */ double vertex_base_power; /* Base power of this vertex */ } specific_vertex_data; /* Possible vertex types (V is vertex voltage, S is vertex injected/consumed power) */ #define FEEDER_VERTEX 1 /* Vtx is a feeder. V is known. May have additional S. */ #define NORMAL_VERTEX 2 /* Vtx is an ordinary one. V is unknown. When the vertex */ /* has S, then it has power injection or consumption */ /* Possible vertex states */ #define CONNECTED 1 /* Vtx is connected to some feeder */ #define DISCONNECTED 2 /* Vtx is not connected to any feeder */ #define UNKNOWN 0 /* It is unknown whether the vtx connects to some feeder */ #define VERTEX_ID(L) \ (((specific_vertex_data*)(((vertex_data*)DATA(L))->specific_data)) \ ->vertex_id) #define VERTEX_AREA(L) \ (((specific_vertex_data*)(((vertex_data*)DATA(L))->specific_data)) \ ->vertex_area) #define VERTEX_STATE(L) \ (((specific_vertex_data*)(((vertex_data*)DATA(L))->specific_data)) \ ->vertex_state) #define VERTEX_TYPE(L) \ (((specific_vertex_data*)(((vertex_data*)DATA(L))->specific_data)) \ ->vertex_type) #define VERTEX_INJ_PWR(L) \ (((specific_vertex_data*)(((vertex_data*)DATA(L))->specific_data)) \ ->vertex_injected_pwr) #define VERTEX_ACUM_PWR(L) \ (((specific_vertex_data*)(((vertex_data*)DATA(L))->specific_data)) \ ->vertex_accumulated_pwr) #define VERTEX_VOLTAGE(L) \ (((specific_vertex_data*)(((vertex_data*)DATA(L))->specific_data)) \ ->vertex_voltage) #define VERTEX_BASE_VOLTAGE(L) \ (((specific_vertex_data*)(((vertex_data*)DATA(L))->specific_data)) \ ->vertex_base_voltage) #define VERTEX_BASE_POWER(L) \ (((specific_vertex_data*)(((vertex_data*)DATA(L))->specific_data)) \ ->vertex_base_power) /*********************************************************** * Specific_edge_data and its accessor macros ***********************************************************/ typedef struct{ edge_id_type edge_id; /* Edge identifyer */ int edge_type; /* Edge type (see below) */ vertex_id_type edge_vertex1; /* Identifyier of one end bus */ vertex_id_type edge_vertex2; /* Identifyier of the other end bus */ int edge_state; /* State of the edge (see below) */ int edge_state_nominal; /* Nominal state of the edge (see below) */ dcomplex edge_impedance; /* Impedance of the edge */ dcomplex edge_intensity; /* Intensity of the edge */ double edge_max_intensity; /* Maximum allowed intensity */ } specific_edge_data; /* Edge types: */ #define SWITCH_EDGE 0 /* Edge is a switch */ #define NORMAL_EDGE 1 /* Edge is an ordinary branch */ /* Edge states: */ #define OPEN 0 /* Edge is open */ #define CLOSED 1 /* Edge is closed */ #define EDGE_ID(L) \ (((specific_edge_data*)(((edge_data*)DATA(L))->specific_data)) \ ->edge_id) #define EDGE_TYPE(L) \ (((specific_edge_data*)(((edge_data*)DATA(L))->specific_data)) \ ->edge_type) #define EDGE_VERTEX1(L) \ (((specific_edge_data*)(((edge_data*)DATA(L))->specific_data)) \ ->edge_vertex1) #define EDGE_VERTEX2(L) \ (((specific_edge_data*)(((edge_data*)DATA(L))->specific_data)) \ ->edge_vertex2) #define EDGE_STATE(L) \ (((specific_edge_data*)(((edge_data*)DATA(L))->specific_data)) \ ->edge_state) #define EDGE_STATE_NOMINAL(L) \ (((specific_edge_data*)(((edge_data*)DATA(L))->specific_data)) \ ->edge_state_nominal) #define EDGE_IMPEDANCE(L) \ (((specific_edge_data*)(((edge_data*)DATA(L))->specific_data)) \ ->edge_impedance) #define EDGE_INTENSITY(L) \ (((specific_edge_data*)(((edge_data*)DATA(L))->specific_data)) \ ->edge_intensity) #define EDGE_MAX_INTENSITY(L) \ (((specific_edge_data*)(((edge_data*)DATA(L))->specific_data)) \ ->edge_max_intensity) /*********************************************************** * Constants and parameters ***********************************************************/ /* Electric constants */ #define VBASE 25.0 /* KV */ #define IBASE 40.0 /* A */ #define SBASE 1000.0 /* KVA (VBASE * IBASE) */ #define ZBASE 625.0 /* Ohm (VBASE * 1000 / IBASE) */ #define LOAD_FACTOR .1 /* Load factor in per one */ #define COS_FI 0.9 /* Cosine(fi) of consumers */ #define SIN_FI 0.4358898943541 /* Sine(fi) of consumers */ /* Computation parameters */ #define MAX_ITER 20 /* Max. number of iterations in the sweepings */ #define MAX_ERROR 1e-10 /* Max. voltage error permitted for the power flow */ #define TINY_THRESH 1e-12 /* Threshold for tiny floating point numbers */ /********************************************************************* * Primitive operations of the "graph" abstract data type *********************************************************************/ /* * Section 1 - Network constructors */ status init_network(graph* p_N); void load_network(FILE* fd, graph* p_N, boolean allareas, area_id_type* areas, int nareas); void load_bus(char* file_line, graph* p_N, boolean allareas, area_id_type* areas, int nareas); void load_branch(char* file_line, graph* p_N, boolean allareas, area_id_type* areas, int nareas); /* * Section 2 - Network destructors */ /* * Section 3 - Network simulations */ void power_flow_network(graph N); void power_flow_subnetwork(list vertices); void remove_null_impedance_cycles(list* chords); void compute_sensitivity_matrix(list chords, double** z, int dim); void mark_negative_positive_paths(list chords); void unmark_negative_positive_paths(list chords); dcomplex self_impedance(list ch); dcomplex mutual_impedance(list chi, list chj); void open_chords(list chords); void close_chords(list chords); void inject_power_corrections(list chords, double** Z, int dim, int* indx); int count_non_null_impedance_cycles(list chords); void sweep_back_sv(list feeders); void sweep_forw_sv(list feeders); status calc_acum_power(graph_vertex vertex_ptr, graph_vertex parent_vertex_ptr, generic_ptr* input, generic_ptr* output); status calc_voltages_intensities(graph_vertex vertex_ptr, graph_vertex parent_vertex_ptr, generic_ptr* input, generic_ptr* output); void reset_subnetwork(list vertices); status reset_bus_branch(graph_vertex vertex_ptr, graph_vertex parent_vertex_ptr, generic_ptr* input, generic_ptr* output); void init_subnetwork(list vertices); status init_bus_branch(graph_vertex vertex_ptr, graph_vertex parent_vertex_ptr, generic_ptr* input, generic_ptr* output); /* * Section 4 - Network manoeuvers */ void set_nominal_state(graph N); void set_state_branch_with_id(graph N, edge_id_type branch_id, int state); void toggle_branch_state_with_id(graph N, edge_id_type branch_id); void toggle_branch_state_with_ptr(graph_edge edge_ptr); void close_branch_with_id(graph N, edge_id_type branch_id); void close_branch_with_ptr(graph_edge edge_ptr); void close_all_branches(graph N); void open_branch_with_id(graph N, edge_id_type branch_id); void open_branch_with_ptr(graph_edge edge_ptr); /* * Section 5 - Miscelaneous functions */ void ens_error(char* error); boolean branch_state_is_closed(graph_edge edge_ptr, graph_vertex vertex_ptr); boolean branch_nominal_state_is_closed(graph_edge edge_ptr, graph_vertex vertex_ptr); void find_feeders(list vertices, list* feeders, boolean (*p_is_reachable)(graph_edge,graph_vertex)); status collect_feeder(graph_vertex v, graph_vertex parent, generic_ptr* input, generic_ptr* feeders); void print_list_feeders(FILE* fd, list feeders); void coordenatize_network(graph N); void coordenatize_subnetwork(list feeders, boolean (*p_is_reachable)(graph_edge,graph_vertex)); graph_vertex find_bus_with_id(graph N, vertex_id_type id); graph_edge find_branch_with_id(graph N, edge_id_type id); void print_dmatrix(double** m, int imin, int imax, int jmin, int jmax); boolean non_tiny_complex(dcomplex z); #endif /* ENSH */