00001
00050 #include <stdlib.h>
00051 #include <stdio.h>
00052 #include <errno.h>
00053 #include <math.h>
00054
00055 #include "solver_nr.h"
00056 #include "node.h"
00057 #include "link.h"
00058
00059
00060 #include "capacitor.h"
00061 #include "load.h"
00062 #include "triplex_meter.h"
00063
00064
00065 #if defined(WIN32) && !defined(__MINGW32__)
00066 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
00067 #define _WIN32_WINNT 0x0400
00068 #include <windows.h>
00069 #ifndef DLEXT
00070 #define DLEXT ".dll"
00071 #endif
00072 #define DLLOAD(P) LoadLibrary(P)
00073 #define DLSYM(H,S) (void *)GetProcAddress((HINSTANCE)H,S)
00074 #define snprintf _snprintf
00075 #else
00076 #include "dlfcn.h"
00077 #ifndef DLEXT
00078 #ifdef __MINGW32__
00079 #define DLEXT ".dll"
00080 #else
00081 #define DLEXT ".so"
00082 #endif
00083 #endif
00084 #define DLLOAD(P) dlopen(P,RTLD_LAZY)
00085 #define DLSYM(H,S) dlsym(H,S)
00086 #endif
00087
00088
00089
00090 #define MULTTERM 0.00000000000001
00091
00092
00093
00094 CLASS *node::oclass = NULL;
00095 CLASS *node::pclass = NULL;
00096
00097 unsigned int node::n = 0;
00098
00099 node::node(MODULE *mod) : powerflow_object(mod)
00100 {
00101 if(oclass == NULL)
00102 {
00103 pclass = powerflow_object::oclass;
00104 oclass = gl_register_class(mod,"node",sizeof(node),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_UNSAFE_OVERRIDE_OMIT|PC_AUTOLOCK);
00105 if (oclass==NULL)
00106 throw "unable to register class node";
00107 else
00108 oclass->trl = TRL_PROVEN;
00109
00110 if(gl_publish_variable(oclass,
00111 PT_INHERIT, "powerflow_object",
00112 PT_enumeration, "bustype", PADDR(bustype),PT_DESCRIPTION,"defines whether the node is a PQ, PV, or SWING node",
00113 PT_KEYWORD, "PQ", (enumeration)PQ,
00114 PT_KEYWORD, "PV", (enumeration)PV,
00115 PT_KEYWORD, "SWING", (enumeration)SWING,
00116 PT_KEYWORD, "SWING_PQ", (enumeration)SWING_PQ,
00117 PT_set, "busflags", PADDR(busflags),PT_DESCRIPTION,"flag indicates node has a source for voltage, i.e. connects to the swing node",
00118 PT_KEYWORD, "HASSOURCE", (set)NF_HASSOURCE,
00119 PT_KEYWORD, "ISSOURCE", (set)NF_ISSOURCE,
00120 PT_object, "reference_bus", PADDR(reference_bus),PT_DESCRIPTION,"reference bus from which frequency is defined",
00121 PT_double,"maximum_voltage_error[V]",PADDR(maximum_voltage_error),PT_DESCRIPTION,"convergence voltage limit or convergence criteria",
00122
00123 PT_complex, "voltage_A[V]", PADDR(voltage[0]),PT_DESCRIPTION,"bus voltage, Phase A to ground",
00124 PT_complex, "voltage_B[V]", PADDR(voltage[1]),PT_DESCRIPTION,"bus voltage, Phase B to ground",
00125 PT_complex, "voltage_C[V]", PADDR(voltage[2]),PT_DESCRIPTION,"bus voltage, Phase C to ground",
00126 PT_complex, "voltage_AB[V]", PADDR(voltaged[0]),PT_DESCRIPTION,"line voltages, Phase AB",
00127 PT_complex, "voltage_BC[V]", PADDR(voltaged[1]),PT_DESCRIPTION,"line voltages, Phase BC",
00128 PT_complex, "voltage_CA[V]", PADDR(voltaged[2]),PT_DESCRIPTION,"line voltages, Phase CA",
00129 PT_complex, "current_A[A]", PADDR(current[0]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current injection (in = positive), this an accumulator only, not a output or input variable",
00130 PT_complex, "current_B[A]", PADDR(current[1]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current injection (in = positive), this an accumulator only, not a output or input variable",
00131 PT_complex, "current_C[A]", PADDR(current[2]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current injection (in = positive), this an accumulator only, not a output or input variable",
00132 PT_complex, "power_A[VA]", PADDR(power[0]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus power injection (in = positive), this an accumulator only, not a output or input variable",
00133 PT_complex, "power_B[VA]", PADDR(power[1]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus power injection (in = positive), this an accumulator only, not a output or input variable",
00134 PT_complex, "power_C[VA]", PADDR(power[2]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus power injection (in = positive), this an accumulator only, not a output or input variable",
00135 PT_complex, "shunt_A[S]", PADDR(shunt[0]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus shunt admittance, this an accumulator only, not a output or input variable",
00136 PT_complex, "shunt_B[S]", PADDR(shunt[1]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus shunt admittance, this an accumulator only, not a output or input variable",
00137 PT_complex, "shunt_C[S]", PADDR(shunt[2]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus shunt admittance, this an accumulator only, not a output or input variable",
00138
00139 PT_complex, "prerotated_current_A[A]", PADDR(pre_rotated_current[0]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"deltamode-functionality - bus current injection (in = positive), but will not be rotated by powerflow for off-nominal frequency, this an accumulator only, not a output or input variable",
00140 PT_complex, "prerotated_current_B[A]", PADDR(pre_rotated_current[1]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"deltamode-functionality - bus current injection (in = positive), but will not be rotated by powerflow for off-nominal frequency, this an accumulator only, not a output or input variable",
00141 PT_complex, "prerotated_current_C[A]", PADDR(pre_rotated_current[2]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"deltamode-functionality - bus current injection (in = positive), but will not be rotated by powerflow for off-nominal frequency, this an accumulator only, not a output or input variable",
00142
00143 PT_complex, "deltamode_generator_current_A[A]", PADDR(deltamode_dynamic_current[0]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"deltamode-functionality - bus current injection (in = positive), direct generator injection (so may be overwritten internally), this an accumulator only, not a output or input variable",
00144 PT_complex, "deltamode_generator_current_B[A]", PADDR(deltamode_dynamic_current[1]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"deltamode-functionality - bus current injection (in = positive), direct generator injection (so may be overwritten internally), this an accumulator only, not a output or input variable",
00145 PT_complex, "deltamode_generator_current_C[A]", PADDR(deltamode_dynamic_current[2]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"deltamode-functionality - bus current injection (in = positive), direct generator injection (so may be overwritten internally), this an accumulator only, not a output or input variable",
00146
00147 PT_complex, "deltamode_PGenTotal",PADDR(deltamode_PGenTotal),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"deltamode-functionality - power value for a diesel generator -- accumulator only, not an output or input",
00148
00149 PT_complex_array, "deltamode_full_Y_matrix", get_full_Y_matrix_offset(),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"deltamode-functionality full_Y matrix exposes so generator objects can interact for Norton equivalents",
00150 PT_complex_array, "deltamode_full_Y_all_matrix", get_full_Y_all_matrix_offset(),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"deltamode-functionality full_Y_all matrix exposes so generator objects can interact for Norton equivalents",
00151
00152 PT_complex, "current_inj_A[A]", PADDR(current_inj[0]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current injection (in = positive), but will not be rotated by powerflow for off-nominal frequency, this an accumulator only, not a output or input variable",
00153 PT_complex, "current_inj_B[A]", PADDR(current_inj[1]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current injection (in = positive), but will not be rotated by powerflow for off-nominal frequency, this an accumulator only, not a output or input variable",
00154 PT_complex, "current_inj_C[A]", PADDR(current_inj[2]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current injection (in = positive), but will not be rotated by powerflow for off-nominal frequency, this an accumulator only, not a output or input variable",
00155
00156 PT_complex, "current_AB[A]", PADDR(current_dy[0]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current delta-connected injection (in = positive), this an accumulator only, not a output or input variable",
00157 PT_complex, "current_BC[A]", PADDR(current_dy[1]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current delta-connected injection (in = positive), this an accumulator only, not a output or input variable",
00158 PT_complex, "current_CA[A]", PADDR(current_dy[2]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current delta-connected injection (in = positive), this an accumulator only, not a output or input variable",
00159 PT_complex, "current_AN[A]", PADDR(current_dy[3]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current wye-connected injection (in = positive), this an accumulator only, not a output or input variable",
00160 PT_complex, "current_BN[A]", PADDR(current_dy[4]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current wye-connected injection (in = positive), this an accumulator only, not a output or input variable",
00161 PT_complex, "current_CN[A]", PADDR(current_dy[5]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus current wye-connected injection (in = positive), this an accumulator only, not a output or input variable",
00162 PT_complex, "power_AB[VA]", PADDR(power_dy[0]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus power delta-connected injection (in = positive), this an accumulator only, not a output or input variable",
00163 PT_complex, "power_BC[VA]", PADDR(power_dy[1]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus power delta-connected injection (in = positive), this an accumulator only, not a output or input variable",
00164 PT_complex, "power_CA[VA]", PADDR(power_dy[2]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus power delta-connected injection (in = positive), this an accumulator only, not a output or input variable",
00165 PT_complex, "power_AN[VA]", PADDR(power_dy[3]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus power wye-connected injection (in = positive), this an accumulator only, not a output or input variable",
00166 PT_complex, "power_BN[VA]", PADDR(power_dy[4]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus power wye-connected injection (in = positive), this an accumulator only, not a output or input variable",
00167 PT_complex, "power_CN[VA]", PADDR(power_dy[5]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus power wye-connected injection (in = positive), this an accumulator only, not a output or input variable",
00168 PT_complex, "shunt_AB[S]", PADDR(power_dy[0]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus shunt delta-connected admittance, this an accumulator only, not a output or input variable",
00169 PT_complex, "shunt_BC[S]", PADDR(power_dy[1]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus shunt delta-connected admittance, this an accumulator only, not a output or input variable",
00170 PT_complex, "shunt_CA[S]", PADDR(power_dy[2]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus shunt delta-connected admittance, this an accumulator only, not a output or input variable",
00171 PT_complex, "shunt_AN[S]", PADDR(power_dy[3]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus shunt wye-connected admittance, this an accumulator only, not a output or input variable",
00172 PT_complex, "shunt_BN[S]", PADDR(power_dy[4]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus shunt wye-connected admittance, this an accumulator only, not a output or input variable",
00173 PT_complex, "shunt_CN[S]", PADDR(power_dy[5]),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"bus shunt wye-connected admittance, this an accumulator only, not a output or input variable",
00174
00175 PT_double, "mean_repair_time[s]",PADDR(mean_repair_time), PT_DESCRIPTION, "Time after a fault clears for the object to be back in service",
00176
00177
00178 PT_enumeration,"frequency_measure_type",PADDR(fmeas_type),PT_DESCRIPTION,"Frequency measurement dynamics-capable implementation",
00179 PT_KEYWORD,"NONE",(enumeration)FM_NONE,PT_DESCRIPTION,"No frequency measurement",
00180 PT_KEYWORD,"SIMPLE",(enumeration)FM_SIMPLE,PT_DESCRIPTION,"Simplified frequency measurement",
00181 PT_KEYWORD,"PLL",(enumeration)FM_PLL,PT_DESCRIPTION,"PLL frequency measurement",
00182
00183 PT_double,"sfm_Tf[s]",PADDR(freq_sfm_Tf),PT_DESCRIPTION,"Transducer time constant for simplified frequency measurement (seconds)",
00184 PT_double,"pll_Kp[pu]",PADDR(freq_pll_Kp),PT_DESCRIPTION,"Proportional gain of PLL frequency measurement",
00185 PT_double,"pll_Ki[pu]",PADDR(freq_pll_Ki),PT_DESCRIPTION,"Integration gain of PLL frequency measurement",
00186
00187
00188 PT_double,"measured_angle_A[rad]", PADDR(curr_freq_state.anglemeas[0]),PT_DESCRIPTION,"bus angle measurement, phase A",
00189 PT_double,"measured_frequency_A[Hz]", PADDR(curr_freq_state.fmeas[0]),PT_DESCRIPTION,"frequency measurement, phase A",
00190 PT_double,"measured_angle_B[rad]", PADDR(curr_freq_state.anglemeas[1]),PT_DESCRIPTION,"bus angle measurement, phase B",
00191 PT_double,"measured_frequency_B[Hz]", PADDR(curr_freq_state.fmeas[1]),PT_DESCRIPTION,"frequency measurement, phase B",
00192 PT_double,"measured_angle_C[rad]", PADDR(curr_freq_state.anglemeas[2]),PT_DESCRIPTION,"bus angle measurement, phase C",
00193 PT_double,"measured_frequency_C[Hz]", PADDR(curr_freq_state.fmeas[2]),PT_DESCRIPTION,"frequency measurement, phase C",
00194 PT_double,"measured_frequency[Hz]", PADDR(curr_freq_state.average_freq), PT_DESCRIPTION, "frequency measurement - average of present phases",
00195
00196 PT_enumeration, "service_status", PADDR(service_status),PT_DESCRIPTION,"In and out of service flag",
00197 PT_KEYWORD, "IN_SERVICE", (enumeration)ND_IN_SERVICE,
00198 PT_KEYWORD, "OUT_OF_SERVICE", (enumeration)ND_OUT_OF_SERVICE,
00199 PT_double, "service_status_double", PADDR(service_status_dbl),PT_DESCRIPTION,"In and out of service flag - type double - will indiscriminately override service_status - useful for schedules",
00200 PT_double, "previous_uptime[min]", PADDR(previous_uptime),PT_DESCRIPTION,"Previous time between disconnects of node in minutes",
00201 PT_double, "current_uptime[min]", PADDR(current_uptime),PT_DESCRIPTION,"Current time since last disconnect of node in minutes",
00202 PT_bool, "Norton_dynamic", PADDR(dynamic_norton),PT_DESCRIPTION,"Flag to indicate a Norton-equivalent connection -- used for generators and deltamode",
00203 PT_bool, "generator_dynamic", PADDR(dynamic_generator),PT_DESCRIPTION,"Flag to indicate a voltage-sourcing or swing-type generator is present -- used for generators and deltamode",
00204
00205 PT_bool, "reset_disabled_island_state", PADDR(reset_island_state), PT_ACCESS, PA_HIDDEN, PT_DESCRIPTION, "Deltamode/multi-island flag -- used to reset disabled status (and reform an island)",
00206
00207
00208 PT_bool, "GFA_enable", PADDR(GFA_enable), PT_DESCRIPTION, "Disable/Enable Grid Friendly Appliance(TM)-type functionality",
00209 PT_double, "GFA_freq_low_trip[Hz]", PADDR(GFA_freq_low_trip), PT_DESCRIPTION, "Low frequency trip point for Grid Friendly Appliance(TM)-type functionality",
00210 PT_double, "GFA_freq_high_trip[Hz]", PADDR(GFA_freq_high_trip), PT_DESCRIPTION, "High frequency trip point for Grid Friendly Appliance(TM)-type functionality",
00211 PT_double, "GFA_volt_low_trip[pu]", PADDR(GFA_voltage_low_trip), PT_DESCRIPTION, "Low voltage trip point for Grid Friendly Appliance(TM)-type functionality",
00212 PT_double, "GFA_volt_high_trip[pu]", PADDR(GFA_voltage_high_trip), PT_DESCRIPTION, "High voltage trip point for Grid Friendly Appliance(TM)-type functionality",
00213 PT_double, "GFA_reconnect_time[s]", PADDR(GFA_reconnect_time), PT_DESCRIPTION, "Reconnect time for Grid Friendly Appliance(TM)-type functionality",
00214 PT_double, "GFA_freq_disconnect_time[s]", PADDR(GFA_freq_disconnect_time), PT_DESCRIPTION, "Frequency violation disconnect time for Grid Friendly Appliance(TM)-type functionality",
00215 PT_double, "GFA_volt_disconnect_time[s]", PADDR(GFA_volt_disconnect_time), PT_DESCRIPTION, "Voltage violation disconnect time for Grid Friendly Appliance(TM)-type functionality",
00216 PT_bool, "GFA_status", PADDR(GFA_status), PT_DESCRIPTION, "Low frequency trip point for Grid Friendly Appliance(TM)-type functionality",
00217
00218 PT_enumeration, "GFA_trip_method", PADDR(GFA_trip_method), PT_DESCRIPTION, "Reason for GFA trip - what caused the GFA to activate",
00219 PT_KEYWORD, "NONE", (enumeration)GFA_NONE, PT_DESCRIPTION, "No GFA trip",
00220 PT_KEYWORD, "UNDER_FREQUENCY", (enumeration)GFA_UF, PT_DESCRIPTION, "GFA trip for under-frequency",
00221 PT_KEYWORD, "OVER_FREQUENCY", (enumeration)GFA_OF, PT_DESCRIPTION, "GFA trip for over-frequency",
00222 PT_KEYWORD, "UNDER_VOLTAGE", (enumeration)GFA_UV, PT_DESCRIPTION, "GFA trip for under-voltage",
00223 PT_KEYWORD, "OVER_VOLTAGE", (enumeration)GFA_OV, PT_DESCRIPTION, "GFA trip for over-voltage",
00224
00225 PT_object, "topological_parent", PADDR(TopologicalParent),PT_DESCRIPTION,"topological parent as per GLM configuration",
00226 NULL) < 1) GL_THROW("unable to publish properties in %s",__FILE__);
00227
00228 if (gl_publish_function(oclass, "interupdate_pwr_object", (FUNCTIONADDR)interupdate_node)==NULL)
00229 GL_THROW("Unable to publish node deltamode function");
00230 if (gl_publish_function(oclass, "pwr_object_swing_swapper", (FUNCTIONADDR)swap_node_swing_status)==NULL)
00231 GL_THROW("Unable to publish node swing-swapping function");
00232 if (gl_publish_function(oclass, "pwr_current_injection_update_map", (FUNCTIONADDR)node_map_current_update_function)==NULL)
00233 GL_THROW("Unable to publish node current injection update mapping function");
00234 if (gl_publish_function(oclass, "attach_vfd_to_pwr_object", (FUNCTIONADDR)attach_vfd_to_node)==NULL)
00235 GL_THROW("Unable to publish node VFD attachment function");
00236 if (gl_publish_function(oclass, "pwr_object_reset_disabled_status", (FUNCTIONADDR)node_reset_disabled_status) == NULL)
00237 GL_THROW("Unable to publish node island-status-reset function");
00238 }
00239 }
00240
00241 int node::isa(char *classname)
00242 {
00243 return strcmp(classname,"node")==0 || powerflow_object::isa(classname);
00244 }
00245
00246 int node::create(void)
00247 {
00248 int result = powerflow_object::create();
00249
00250 #ifdef SUPPORT_OUTAGES
00251 condition=OC_NORMAL;
00252 #endif
00253
00254 n++;
00255
00256 bustype = PQ;
00257 busflags = NF_HASSOURCE;
00258 busphasesIn = 0;
00259 busphasesOut = 0;
00260 reference_bus = NULL;
00261 nominal_voltage = 0.0;
00262 maximum_voltage_error = 0.0;
00263 frequency = nominal_frequency;
00264 fault_Z = 1e-6;
00265 prev_NTime = 0;
00266 SubNode = NONE;
00267 SubNodeParent = NULL;
00268 TopologicalParent = NULL;
00269 NR_subnode_reference = NULL;
00270 Extra_Data=NULL;
00271 NR_link_table = NULL;
00272 NR_connected_links[0] = NR_connected_links[1] = 0;
00273 NR_number_child_nodes[0] = NR_number_child_nodes[1] = 0;
00274 NR_child_nodes = NULL;
00275
00276 NR_node_reference = -1;
00277 house_present = false;
00278 nom_res_curr[0] = nom_res_curr[1] = nom_res_curr[2] = 0.0;
00279
00280 prev_phases = 0x00;
00281
00282 mean_repair_time = 0.0;
00283
00284
00285 service_status = ND_IN_SERVICE;
00286 service_status_dbl = -1.0;
00287 last_disconnect = 0;
00288 previous_uptime = -1.0;
00289 current_uptime = -1.0;
00290
00291 full_Y = NULL;
00292 full_Y_load = NULL;
00293 full_Y_all = NULL;
00294 BusHistTerm[0] = complex(0.0,0.0);
00295 BusHistTerm[1] = complex(0.0,0.0);
00296 BusHistTerm[2] = complex(0.0,0.0);
00297 prev_delta_time = -1.0;
00298 ahrlloadstore = NULL;
00299 bhrlloadstore = NULL;
00300 chrcloadstore = NULL;
00301 LoadHistTermL = NULL;
00302 LoadHistTermC = NULL;
00303
00304 memset(voltage,0,sizeof(voltage));
00305 memset(voltaged,0,sizeof(voltaged));
00306 memset(current,0,sizeof(current));
00307 memset(pre_rotated_current,0,sizeof(pre_rotated_current));
00308 memset(power,0,sizeof(power));
00309 memset(shunt,0,sizeof(shunt));
00310
00311 deltamode_dynamic_current[0] = deltamode_dynamic_current[1] = deltamode_dynamic_current[2] = complex(0.0,0.0);
00312
00313 deltamode_PGenTotal = complex(0.0,0.0);
00314
00315 current_dy[0] = current_dy[1] = current_dy[2] = complex(0.0,0.0);
00316 current_dy[3] = current_dy[4] = current_dy[5] = complex(0.0,0.0);
00317 power_dy[0] = power_dy[1] = power_dy[2] = complex(0.0,0.0);
00318 power_dy[3] = power_dy[4] = power_dy[5] = complex(0.0,0.0);
00319 shunt_dy[0] = shunt_dy[1] = shunt_dy[2] = complex(0.0,0.0);
00320 shunt_dy[3] = shunt_dy[4] = shunt_dy[5] = complex(0.0,0.0);
00321
00322 prev_voltage_value = NULL;
00323 prev_power_value = NULL;
00324 node_type = NORMAL_NODE;
00325 current_accumulated = false;
00326 deltamode_inclusive = false;
00327 dynamic_norton = false;
00328 dynamic_generator = false;
00329
00330
00331 if (all_powerflow_freq_measure_method == FMM_SIMPLE)
00332 {
00333 fmeas_type = FM_SIMPLE;
00334 }
00335 else if (all_powerflow_freq_measure_method == FMM_PLL)
00336 {
00337 fmeas_type = FM_PLL;
00338 }
00339 else
00340 {
00341 fmeas_type = FM_NONE;
00342 }
00343
00344
00345 freq_omega_ref=0.0;
00346 freq_sfm_Tf=0.01;
00347 freq_pll_Kp=10;
00348 freq_pll_Ki=100;
00349
00350
00351 curr_freq_state.fmeas[0] = nominal_frequency;
00352 curr_freq_state.fmeas[1] = nominal_frequency;
00353 curr_freq_state.fmeas[2] = nominal_frequency;
00354 curr_freq_state.average_freq = nominal_frequency;
00355
00356
00357 GFA_enable = false;
00358 GFA_freq_low_trip = 59.5;
00359 GFA_freq_high_trip = 60.5;
00360 GFA_voltage_low_trip = 0.8;
00361 GFA_voltage_high_trip = 1.2;
00362 GFA_reconnect_time = 300.0;
00363 GFA_freq_disconnect_time = 0.2;
00364 GFA_volt_disconnect_time = 0.2;
00365 GFA_status = true;
00366 prev_time_dbl = 0.0;
00367 GFA_Update_time = 0.0;
00368 GFA_trip_method = GFA_NONE;
00369
00370
00371 VFD_attached = false;
00372 VFD_updating_function = NULL;
00373 VFD_object = NULL;
00374
00375
00376 reset_island_state = false;
00377
00378 return result;
00379 }
00380
00381 int node::init(OBJECT *parent)
00382 {
00383 OBJECT *obj = OBJECTHDR(this);
00384
00385
00386 if (has_phase(PHASE_S))
00387 {
00388
00389 if (!(gl_object_isa(obj,"triplex_node","powerflow") || gl_object_isa(obj,"triplex_meter","powerflow") || gl_object_isa(obj,"triplex_load","powerflow") || gl_object_isa(obj,"motor","powerflow")))
00390 {
00391 GL_THROW("Object:%d - %s -- has a phase S, but is not triplex!",obj->id,(obj->name ? obj->name : "Unnamed"));
00392
00393
00394
00395
00396 }
00397
00398 }
00399
00400 if (solver_method==SM_NR)
00401 {
00402 char ext_lib_file_name[1025];
00403 char extpath[1024];
00404 CALLBACKS **cbackval = NULL;
00405 bool ExtLinkFailure;
00406 STATUS status_ret_value;
00407
00408
00409 TopologicalParent = obj->parent;
00410
00411
00412 if (NR_swing_bus == NULL)
00413 {
00414
00415 NR_swing_bus = NR_master_swing_search("node",true);
00416
00417
00418 if (NR_swing_bus == NULL)
00419 {
00420 NR_swing_bus = NR_master_swing_search("substation",true);
00421 }
00422
00423
00424
00425 if (NR_swing_bus == NULL)
00426 {
00427 NR_swing_bus = NR_master_swing_search("meter",true);
00428 }
00429
00430
00431
00432 if (NR_swing_bus == NULL)
00433 {
00434 NR_swing_bus = NR_master_swing_search("elec_frequency",true);
00435 }
00436
00437
00438
00439 if (NR_swing_bus == NULL)
00440 {
00441
00442 NR_swing_bus = NR_master_swing_search("load",true);
00443 }
00444
00445
00446
00447 if (NR_swing_bus == NULL)
00448 {
00449
00450 NR_swing_bus = NR_master_swing_search("triplex_node",true);
00451 }
00452
00453
00454
00455 if (NR_swing_bus == NULL)
00456 {
00457
00458 NR_swing_bus = NR_master_swing_search("triplex_meter",true);
00459 }
00460
00461
00462
00463 if (NR_swing_bus == NULL)
00464 {
00465
00466 NR_swing_bus = NR_master_swing_search("triplex_load",true);
00467 }
00468
00469
00470
00471
00472 if (NR_swing_bus == NULL)
00473 {
00474 NR_swing_bus = NR_master_swing_search("node",false);
00475 }
00476
00477
00478 if (NR_swing_bus == NULL)
00479 {
00480 NR_swing_bus = NR_master_swing_search("substation",false);
00481 }
00482
00483
00484
00485 if (NR_swing_bus == NULL)
00486 {
00487 NR_swing_bus = NR_master_swing_search("meter",false);
00488 }
00489
00490
00491
00492 if (NR_swing_bus == NULL)
00493 {
00494 NR_swing_bus = NR_master_swing_search("elec_frequency",false);
00495 }
00496
00497
00498
00499 if (NR_swing_bus == NULL)
00500 {
00501
00502 NR_swing_bus = NR_master_swing_search("load",false);
00503 }
00504
00505
00506
00507 if (NR_swing_bus == NULL)
00508 {
00509
00510 NR_swing_bus = NR_master_swing_search("triplex_node",false);
00511 }
00512
00513
00514
00515 if (NR_swing_bus == NULL)
00516 {
00517
00518 NR_swing_bus = NR_master_swing_search("triplex_meter",false);
00519 }
00520
00521
00522
00523 if (NR_swing_bus == NULL)
00524 {
00525
00526 NR_swing_bus = NR_master_swing_search("triplex_load",false);
00527 }
00528
00529
00530
00531 if (NR_swing_bus == NULL)
00532 {
00533 GL_THROW("NR: no swing bus found");
00534
00535
00536
00537
00538 }
00539
00540
00541
00542 status_ret_value = NR_array_structure_allocate(&NR_powerflow,1);
00543
00544
00545 if (status_ret_value == FAILED)
00546 {
00547 GL_THROW("NR: Failed to allocate monolithic grid solver arrays");
00548
00549
00550
00551
00552
00553 }
00554
00555
00556 NR_islands_detected = 1;
00557 }
00558
00559
00560 if (obj->parent!=NULL)
00561 {
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 if (!(gl_object_isa(obj->parent,"load","powerflow") | gl_object_isa(obj->parent,"node","powerflow") | gl_object_isa(obj->parent,"meter","powerflow") | gl_object_isa(obj->parent,"substation","powerflow")))
00572 GL_THROW("NR: Parent is not a node, load or meter!");
00573
00574
00575
00576
00577
00578 node *parNode = OBJECTDATA(obj->parent,node);
00579
00580
00581 if ((parNode->bustype==SWING) || (parNode->bustype==SWING_PQ))
00582 {
00583 gl_warning("Node:%s is parented to a swing node and will get folded into it.",obj->name);
00584
00585
00586
00587
00588
00589 }
00590
00591
00592 set p_phase_to_check, c_phase_to_check;
00593
00594
00595 p_phase_to_check = (parNode->phases & (~(PHASE_N)));
00596 c_phase_to_check = (phases & (~(PHASE_N)));
00597
00598
00599 if ((parNode->phases!=phases) && (p_phase_to_check != c_phase_to_check))
00600 {
00601
00602 p_phase_to_check = (parNode->phases & (~(PHASE_D | PHASE_N)));
00603 c_phase_to_check = (phases & (~(PHASE_D | PHASE_N)));
00604
00605
00606 if ((p_phase_to_check & c_phase_to_check) != c_phase_to_check)
00607 {
00608 GL_THROW("NR: Parent and child node phases for nodes %s and %s do not match!",obj->parent->name,obj->name);
00609
00610 }
00611 else
00612 {
00613 if ((parNode->SubNode==CHILD) | (parNode->SubNode==DIFF_CHILD) | ((obj->parent->parent!=NR_swing_bus) && (obj->parent->parent!=NULL)))
00614 {
00615 GL_THROW("NR: Grandchildren are not supported at this time!");
00616
00617
00618
00619
00620
00621
00622 }
00623 else
00624 {
00625
00626 if (((phases & PHASE_D) == PHASE_D) || ((parNode->phases & PHASE_D) == PHASE_D))
00627 {
00628
00629 SubNode = DIFF_CHILD;
00630 SubNodeParent = obj->parent;
00631
00632 parNode->SubNode = DIFF_PARENT;
00633 parNode->SubNodeParent = obj;
00634 parNode->NR_number_child_nodes[0]++;
00635
00636
00637 NR_subnode_reference = &(parNode->NR_node_reference);
00638
00639
00640 if (parNode->Extra_Data == NULL)
00641 {
00642 parNode->Extra_Data = (complex *)gl_malloc(9*sizeof(complex));
00643 if (parNode->Extra_Data == NULL)
00644 {
00645 GL_THROW("NR: Memory allocation failure for differently connected load.");
00646
00647
00648
00649
00650
00651 }
00652 }
00653 }
00654 else
00655 {
00656
00657
00658
00659
00660
00661 SubNode = CHILD;
00662 SubNodeParent = obj->parent;
00663
00664 parNode->SubNode = PARENT;
00665 parNode->SubNodeParent = obj;
00666 parNode->NR_number_child_nodes[0]++;
00667
00668
00669 NR_subnode_reference = &(parNode->NR_node_reference);
00670
00671
00672 last_child_power[0][0] = last_child_power[0][1] = last_child_power[0][2] = complex(0,0);
00673 last_child_power[1][0] = last_child_power[1][1] = last_child_power[1][2] = complex(0,0);
00674 last_child_power[2][0] = last_child_power[2][1] = last_child_power[2][2] = complex(0,0);
00675 last_child_power[3][0] = last_child_power[3][1] = last_child_power[3][2] = complex(0,0);
00676 last_child_current12 = 0.0;
00677
00678
00679 last_child_power_dy[0][0] = last_child_power_dy[0][1] = last_child_power_dy[0][2] = complex(0.0,0.0);
00680 last_child_power_dy[1][0] = last_child_power_dy[1][1] = last_child_power_dy[1][2] = complex(0.0,0.0);
00681 last_child_power_dy[2][0] = last_child_power_dy[2][1] = last_child_power_dy[2][2] = complex(0.0,0.0);
00682 last_child_power_dy[3][0] = last_child_power_dy[3][1] = last_child_power_dy[3][2] = complex(0.0,0.0);
00683 last_child_power_dy[4][0] = last_child_power_dy[4][1] = last_child_power_dy[4][2] = complex(0.0,0.0);
00684 last_child_power_dy[5][0] = last_child_power_dy[5][1] = last_child_power_dy[5][2] = complex(0.0,0.0);
00685 }
00686 }
00687
00688
00689 NR_node_reference = -99;
00690
00691
00692
00693 gl_set_rank(obj,3);
00694
00695 }
00696 }
00697 else
00698 {
00699 if ((parNode->SubNode==CHILD) | (parNode->SubNode==DIFF_CHILD) | (obj->parent->parent!=NULL))
00700 {
00701 GL_THROW("NR: Grandchildren are not supported at this time!");
00702
00703 }
00704 else
00705 {
00706
00707 SubNode = CHILD;
00708 SubNodeParent = obj->parent;
00709
00710
00711 if (parNode->SubNode != DIFF_PARENT)
00712 {
00713 parNode->SubNode = PARENT;
00714 }
00715 parNode->SubNodeParent = obj;
00716 parNode->NR_number_child_nodes[0]++;
00717
00718
00719 NR_subnode_reference = &(parNode->NR_node_reference);
00720 }
00721
00722
00723 NR_node_reference = -99;
00724
00725
00726
00727 gl_set_rank(obj,3);
00728
00729
00730
00731 last_child_power[0][0] = last_child_power[0][1] = last_child_power[0][2] = complex(0,0);
00732 last_child_power[1][0] = last_child_power[1][1] = last_child_power[1][2] = complex(0,0);
00733 last_child_power[2][0] = last_child_power[2][1] = last_child_power[2][2] = complex(0,0);
00734 last_child_power[3][0] = last_child_power[3][1] = last_child_power[3][2] = complex(0,0);
00735 last_child_current12 = 0.0;
00736
00737
00738 last_child_power_dy[0][0] = last_child_power_dy[0][1] = last_child_power_dy[0][2] = complex(0.0,0.0);
00739 last_child_power_dy[1][0] = last_child_power_dy[1][1] = last_child_power_dy[1][2] = complex(0.0,0.0);
00740 last_child_power_dy[2][0] = last_child_power_dy[2][1] = last_child_power_dy[2][2] = complex(0.0,0.0);
00741 last_child_power_dy[3][0] = last_child_power_dy[3][1] = last_child_power_dy[3][2] = complex(0.0,0.0);
00742 last_child_power_dy[4][0] = last_child_power_dy[4][1] = last_child_power_dy[4][2] = complex(0.0,0.0);
00743 last_child_power_dy[5][0] = last_child_power_dy[5][1] = last_child_power_dy[5][2] = complex(0.0,0.0);
00744 }
00745
00746
00747 if (nominal_voltage != parNode->nominal_voltage)
00748 {
00749 gl_warning("Node:%s does not have the same nominal voltage as its parent - copying voltage from parent.",(obj->name ? obj->name : "unnamed"));
00750
00751
00752
00753
00754
00755 nominal_voltage = parNode->nominal_voltage;
00756 }
00757 }
00758 else
00759 {
00760 NR_bus_count++;
00761
00762
00763
00764 if (obj==NR_swing_bus)
00765 {
00766 gl_set_rank(obj,6);
00767 }
00768 else
00769 {
00770 gl_set_rank(obj,4);
00771 }
00772 }
00773
00774
00775
00776 if (obj == NR_swing_bus)
00777 {
00778 if (LUSolverName[0]=='\0')
00779 {
00780 matrix_solver_method=MM_SUPERLU;
00781 }
00782 else
00783 {
00784
00785 LUSolverFcns.dllLink = NULL;
00786 LUSolverFcns.ext_init = NULL;
00787 LUSolverFcns.ext_alloc = NULL;
00788 LUSolverFcns.ext_solve = NULL;
00789 LUSolverFcns.ext_destroy = NULL;
00790
00791 #ifdef WIN32
00792 snprintf(ext_lib_file_name, 1024, "solver_%s" DLEXT,LUSolverName.get_string());
00793 #else
00794 snprintf(ext_lib_file_name, 1024, "lib_solver_%s" DLEXT,LUSolverName.get_string());
00795 #endif
00796
00797 if (gl_findfile(ext_lib_file_name, NULL, 0|4, extpath,sizeof(extpath))!=NULL)
00798 {
00799
00800 LUSolverFcns.dllLink = DLLOAD(extpath);
00801
00802
00803 if (LUSolverFcns.dllLink==NULL)
00804 {
00805 gl_warning("Failure to load solver_%s as a library, defaulting to superLU",LUSolverName.get_string());
00806
00807
00808
00809
00810
00811
00812
00813 matrix_solver_method = MM_SUPERLU;
00814 }
00815 else
00816 {
00817
00818 ExtLinkFailure = false;
00819
00820
00821 cbackval = (CALLBACKS **)DLSYM(LUSolverFcns.dllLink, "callback");
00822
00823
00824 if(cbackval)
00825 *cbackval = callback;
00826
00827
00828 LUSolverFcns.ext_init = DLSYM(LUSolverFcns.dllLink,"LU_init");
00829
00830
00831 if (LUSolverFcns.ext_init == NULL)
00832 {
00833 gl_warning("LU_init of external solver solver_%s not found, defaulting to superLU",LUSolverName.get_string());
00834
00835
00836
00837
00838
00839
00840
00841 ExtLinkFailure = true;
00842 }
00843
00844
00845 LUSolverFcns.ext_alloc = DLSYM(LUSolverFcns.dllLink,"LU_alloc");
00846
00847
00848 if (LUSolverFcns.ext_alloc == NULL)
00849 {
00850 gl_warning("LU_init of external solver solver_%s not found, defaulting to superLU",LUSolverName.get_string());
00851
00852
00853
00854
00855
00856
00857
00858 ExtLinkFailure = true;
00859 }
00860
00861
00862 LUSolverFcns.ext_solve = DLSYM(LUSolverFcns.dllLink,"LU_solve");
00863
00864
00865 if (LUSolverFcns.ext_solve == NULL)
00866 {
00867 gl_warning("LU_init of external solver solver_%s not found, defaulting to superLU",LUSolverName.get_string());
00868
00869
00870
00871
00872
00873
00874
00875 ExtLinkFailure = true;
00876 }
00877
00878
00879 LUSolverFcns.ext_destroy = DLSYM(LUSolverFcns.dllLink,"LU_destroy");
00880
00881
00882 if (LUSolverFcns.ext_destroy == NULL)
00883 {
00884 gl_warning("LU_init of external solver solver_%s not found, defaulting to superLU",LUSolverName.get_string());
00885
00886
00887
00888
00889
00890
00891
00892 ExtLinkFailure = true;
00893 }
00894
00895
00896
00897 if (ExtLinkFailure)
00898 {
00899
00900 matrix_solver_method=MM_SUPERLU;
00901 }
00902 else
00903 {
00904 gl_verbose("External solver solver_%s found, utilizing for NR",LUSolverName.get_string());
00905
00906
00907
00908
00909
00910
00911 matrix_solver_method=MM_EXTERN;
00912 }
00913 }
00914 }
00915 else
00916 {
00917 gl_warning("The external solver solver_%s could not be found, defaulting to superLU",LUSolverName.get_string());
00918
00919
00920
00921
00922
00923
00924
00925 matrix_solver_method=MM_SUPERLU;
00926 }
00927 }
00928
00929 if(default_resistance <= 0.0){
00930 gl_error("INIT: The global default_resistance was less than or equal to zero. default_resistance must be greater than zero.");
00931 return 0;
00932 }
00933 }
00934
00935 if (mean_repair_time < 0.0)
00936 {
00937 gl_warning("node:%s has a negative mean_repair_time, set to 1 hour",obj->name);
00938
00939
00940
00941
00942
00943 mean_repair_time = 0.0;
00944 }
00945 }
00946 else if (solver_method==SM_GS)
00947 {
00948 GL_THROW("Gauss_Seidel is a deprecated solver and has been removed");
00949
00950
00951
00952
00953
00954
00955 }
00956 else if (solver_method == SM_FBS)
00957 {
00958
00959 TopologicalParent = obj->parent;
00960
00961 if (obj->parent != NULL)
00962 {
00963 if((gl_object_isa(obj->parent,"load","powerflow") | gl_object_isa(obj->parent,"node","powerflow") | gl_object_isa(obj->parent,"meter","powerflow") | gl_object_isa(obj->parent,"substation","powerflow")))
00964 {
00965 node *parNode = OBJECTDATA(obj->parent,node);
00966
00967
00968 set p_phase_to_check, c_phase_to_check;
00969
00970
00971 p_phase_to_check = (parNode->phases & (~(PHASE_D | PHASE_N)));
00972 c_phase_to_check = (phases & (~(PHASE_D | PHASE_N)));
00973
00974
00975 if ((p_phase_to_check & c_phase_to_check) != c_phase_to_check)
00976 {
00977 GL_THROW("Parent and child node phases are incompatible for nodes %s and %s.",obj->parent->name,obj->name);
00978
00979
00980
00981
00982 }
00983
00984
00985 if (nominal_voltage != parNode->nominal_voltage)
00986 {
00987 gl_warning("Node:%s does not have the same nominal voltage as its parent - copying voltage from parent.",(obj->name ? obj->name : "unnamed"));
00988
00989
00990 nominal_voltage = parNode->nominal_voltage;
00991 }
00992 }
00993 }
00994 }
00995 else
00996 GL_THROW("unsupported solver method");
00997
00998
00999
01000 int result = powerflow_object::init(parent);
01001
01002
01003 if (solver_method==SM_GS)
01004 {
01005 GL_THROW("Gauss_Seidel is a deprecated solver and has been removed");
01006
01007
01008
01009
01010
01011
01012 }
01013
01014
01015 if (nominal_voltage==0 && parent)
01016 {
01017 powerflow_object *pParent = OBJECTDATA(parent,powerflow_object);
01018 if (gl_object_isa(parent,"transformer"))
01019 {
01020 PROPERTY *transformer_config,*transformer_secondary_voltage;
01021 OBJECT *trans_config_obj;
01022 double *trans_secondary_voltage_value;
01023 size_t offset_val;
01024 char buffer[128];
01025
01026
01027 transformer_config = gl_get_property(parent,"configuration");
01028
01029
01030 if (transformer_config == NULL)
01031 {
01032 GL_THROW("Error mapping secondary voltage property from transformer:%d %s",parent->id,parent->name?parent->name:"unnamed");
01033
01034
01035
01036
01037
01038 }
01039
01040
01041 offset_val = gl_get_value(parent, GETADDR(parent, transformer_config), buffer, 127, transformer_config);
01042
01043
01044 if (offset_val == 0)
01045 {
01046 GL_THROW("Error mapping secondary voltage property from transformer:%d %s",parent->id,parent->name?parent->name:"unnamed");
01047
01048 }
01049
01050
01051 trans_config_obj = gl_get_object(buffer);
01052
01053 if (trans_config_obj == 0)
01054 {
01055 GL_THROW("Error mapping secondary voltage property from transformer:%d %s",parent->id,parent->name?parent->name:"unnamed");
01056
01057 }
01058
01059
01060 transformer_secondary_voltage = gl_get_property(trans_config_obj,"secondary_voltage");
01061
01062
01063 if (transformer_secondary_voltage == NULL)
01064 {
01065 GL_THROW("Error mapping secondary voltage property from transformer:%d %s",parent->id,parent->name?parent->name:"unnamed");
01066
01067 }
01068
01069
01070 trans_secondary_voltage_value = gl_get_double(trans_config_obj,transformer_secondary_voltage);
01071
01072
01073 if (trans_secondary_voltage_value == NULL)
01074 {
01075 GL_THROW("Error mapping secondary voltage property from transformer:%d %s",parent->id,parent->name?parent->name:"unnamed");
01076
01077 }
01078
01079
01080 nominal_voltage = *trans_secondary_voltage_value;
01081 }
01082 else
01083 nominal_voltage = pParent->nominal_voltage;
01084 }
01085
01086
01087 if (maximum_voltage_error<0)
01088 throw "negative maximum_voltage_error is invalid";
01089
01090
01091
01092
01093
01094
01095
01096 if (maximum_voltage_error==0.0)
01097 maximum_voltage_error = nominal_voltage * default_maximum_voltage_error;
01098
01099
01100 if (fault_Z<=0)
01101 throw "negative fault impedance is invalid";
01102
01103
01104
01105
01106
01107
01108 if (nominal_voltage<=0)
01109 throw "nominal_voltage is not set";
01110
01111
01112
01113
01114
01115
01116 if (k>1)
01117 {
01118 if (geographic_degree>0)
01119 geographic_degree = n/(1/(geographic_degree/n) + log((double)k));
01120 else
01121 geographic_degree = n/log((double)k);
01122 }
01123
01124
01125 if ((bustype==SWING) || (bustype==SWING_PQ) || (bustype==PV))
01126 busflags |= NF_HASSOURCE;
01127
01128
01129 if (has_phase(PHASE_S))
01130 {
01131 if (has_phase(PHASE_A))
01132 {
01133 if (voltage[0] == 0)
01134 {
01135 voltage[0].SetPolar(nominal_voltage,0.0);
01136 }
01137 if (voltage[1] == 0)
01138 {
01139 voltage[1].SetPolar(nominal_voltage,0.0);
01140 }
01141 }
01142 else if (has_phase(PHASE_B))
01143 {
01144 if (voltage[0] == 0)
01145 {
01146 voltage[0].SetPolar(nominal_voltage,-PI*2/3);
01147 }
01148 if (voltage[1] == 0)
01149 {
01150 voltage[1].SetPolar(nominal_voltage,-PI*2/3);
01151 }
01152 }
01153 else if (has_phase(PHASE_C))
01154 {
01155 if (voltage[0] == 0)
01156 {
01157 voltage[0].SetPolar(nominal_voltage,PI*2/3);
01158 }
01159 if (voltage[1] == 0)
01160 {
01161 voltage[1].SetPolar(nominal_voltage,PI*2/3);
01162 }
01163 }
01164 else
01165 throw("Please specify which phase (A,B,or C) the triplex node is attached to.");
01166
01167 voltage[2] = complex(0,0);
01168 }
01169 else if (has_phase(PHASE_A|PHASE_B|PHASE_C))
01170 {
01171 if (voltage[0] == 0)
01172 {
01173 voltage[0].SetPolar(nominal_voltage,0.0);
01174 }
01175 if (voltage[1] == 0)
01176 {
01177 voltage[1].SetPolar(nominal_voltage,-2*PI/3);
01178 }
01179 if (voltage[2] == 0)
01180 {
01181 voltage[2].SetPolar(nominal_voltage,2*PI/3);
01182 }
01183 }
01184 else
01185 {
01186 if (!has_phase(PHASE_A))
01187 voltage[0]=0.0;
01188 else if (voltage[0] == 0)
01189 voltage[0].SetPolar(nominal_voltage,0);
01190
01191 if (!has_phase(PHASE_B))
01192 voltage[1]=0.0;
01193 else if (voltage[1] == 0)
01194 voltage[1].SetPolar(nominal_voltage,-2*PI/3);
01195
01196 if (!has_phase(PHASE_C))
01197 voltage[2]=0.0;
01198 else if (voltage[2] == 0)
01199 voltage[2].SetPolar(nominal_voltage,2*PI/3);
01200 }
01201
01202 if (has_phase(PHASE_D) & voltageAB==0)
01203 {
01204 voltageAB = voltageA - voltageB;
01205 voltageBC = voltageB - voltageC;
01206 voltageCA = voltageC - voltageA;
01207 }
01208 else if (has_phase(PHASE_S))
01209 {
01210
01211 voltaged[0] = voltage[0] + voltage[1];
01212 voltaged[1] = voltage[1] - voltage[2];
01213 voltaged[2] = voltage[0] - voltage[2];
01214 }
01215
01216
01217 if (solver_method == SM_NR)
01218 {
01219 last_voltage[0] = voltage[0];
01220 last_voltage[1] = voltage[1];
01221 last_voltage[2] = voltage[2];
01222 }
01223
01224
01225 last_disconnect = gl_globalclock;
01226
01227
01228 if ((obj->flags & OF_DELTAMODE) == OF_DELTAMODE)
01229 {
01230
01231 deltamode_inclusive = true;
01232
01233
01234 pwr_object_count++;
01235
01236
01237 if (TopologicalParent != NULL)
01238 {
01239 if ((TopologicalParent->flags & OF_DELTAMODE) != OF_DELTAMODE)
01240 {
01241 gl_warning("Object %s (node:%d) is flagged for deltamode, but it's parent is not. This may lead to incorrect answers!",obj->name?obj->name:"Unknown",obj->id);
01242
01243
01244
01245
01246 }
01247 }
01248
01249
01250 prev_time_dbl = (double)gl_globalclock;
01251 }
01252
01253
01254 if (fmeas_type != FM_NONE)
01255 {
01256
01257 freq_omega_ref = 2.0 * PI * nominal_frequency;
01258 }
01259
01260 return result;
01261 }
01262
01263
01264
01265 TIMESTAMP node::NR_node_presync_fxn(TIMESTAMP t0_val)
01266 {
01267 TIMESTAMP tresults_val;
01268 double curr_delta_time;
01269 double curr_ts_dbl, diff_dbl;
01270
01271
01272 tresults_val = TS_NEVER;
01273
01274
01275 current_inj[0] = current_inj[1] = current_inj[2] = 0.0;
01276
01277
01278 current_accumulated = false;
01279
01280
01281 if (enable_inrush_calculations == true)
01282 {
01283 if (deltatimestep_running > 0)
01284 {
01285
01286 curr_delta_time = gl_globaldeltaclock;
01287
01288
01289 if (curr_delta_time != prev_delta_time)
01290 {
01291
01292 BusHistTerm[0] = BusHistTerm[1] = BusHistTerm[2] = complex(0.0,0.0);
01293 }
01294
01295 }
01296 else
01297 {
01298
01299 prev_delta_time = -1.0;
01300 }
01301 }
01302
01303
01304 if ((SubNode==DIFF_PARENT))
01305 {
01306
01307 Extra_Data[0] = Extra_Data[1] = Extra_Data[2] = 0.0;
01308
01309 Extra_Data[3] = Extra_Data[4] = Extra_Data[5] = 0.0;
01310
01311 Extra_Data[6] = Extra_Data[7] = Extra_Data[8] = 0.0;
01312 }
01313
01314
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325 if ((GFA_enable == true) && (deltatimestep_running < 0))
01326 {
01327
01328 curr_ts_dbl = (double)t0_val;
01329
01330
01331 if (prev_time_dbl < curr_ts_dbl)
01332 {
01333
01334 diff_dbl = curr_ts_dbl - prev_time_dbl;
01335
01336
01337 prev_time_dbl = curr_ts_dbl;
01338
01339
01340 GFA_Update_time = perform_GFA_checks(diff_dbl);
01341
01342
01343 if (GFA_Update_time > 0.0)
01344 {
01345
01346 if (deltamode_inclusive == true)
01347 {
01348 tresults_val = t0_val + (TIMESTAMP)(floor(GFA_Update_time));
01349
01350
01351
01352 schedule_deltamode_start(tresults_val);
01353 }
01354 else
01355 {
01356 tresults_val = t0_val + (TIMESTAMP)(ceil(GFA_Update_time));
01357 }
01358 }
01359 }
01360
01361 }
01362
01363
01364
01365 return tresults_val;
01366 }
01367
01368
01369 TIMESTAMP node::presync(TIMESTAMP t0)
01370 {
01371 unsigned int index_val;
01372 FILE *NRFileDump;
01373 OBJECT *obj = OBJECTHDR(this);
01374 TIMESTAMP t1 = powerflow_object::presync(t0);
01375 TIMESTAMP temp_time_value, temp_t1_value;
01376 node *temp_par_node = NULL;
01377 FUNCTIONADDR temp_funadd = NULL;
01378 gld_property *temp_complex_property;
01379 gld_wlock *test_rlock;
01380 complex temp_complex_value;
01381 complex_array temp_complex_array;
01382 int temp_idx_x, temp_idx_y;
01383
01384
01385 if (service_status_dbl>-1.0)
01386 {
01387 if (service_status_dbl == 0.0)
01388 {
01389 service_status = ND_OUT_OF_SERVICE;
01390 }
01391 else if (service_status_dbl == 1.0)
01392 {
01393 service_status = ND_IN_SERVICE;
01394 }
01395 else
01396 {
01397 GL_THROW("Invalid value for service_status_double");
01398
01399
01400
01401
01402
01403
01404 }
01405 }
01406
01407
01408 if (prev_NTime!=t0)
01409 {
01410 if (service_status == ND_IN_SERVICE)
01411 {
01412
01413 if ((last_disconnect == prev_NTime) && (current_uptime == -1.0))
01414 {
01415
01416 last_disconnect = t0;
01417 }
01418
01419
01420 temp_time_value = t0 - last_disconnect;
01421 current_uptime = ((double)(temp_time_value))/60.0;
01422 }
01423 else
01424 {
01425 if (last_disconnect != prev_NTime)
01426 {
01427 temp_time_value = t0 - last_disconnect;
01428 previous_uptime = ((double)(temp_time_value))/60.0;
01429 }
01430
01431 current_uptime = -1.0;
01432 last_disconnect = t0;
01433 }
01434 }
01435
01436
01437 if (prev_NTime==0)
01438 {
01439 set phase_to_check;
01440 phase_to_check = (phases & (~(PHASE_D | PHASE_N)));
01441
01442
01443 if (((phase_to_check & busphasesIn) != phase_to_check) && (busphasesIn != 0) && (solver_method != SM_NR))
01444 {
01445 GL_THROW("node:%d (%s) has more phases leaving than entering",obj->id,obj->name);
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 }
01456
01457 if (((phase_to_check & (busphasesIn | busphasesOut) != phase_to_check) && (busphasesIn != 0 && busphasesOut != 0) && (solver_method == SM_NR)))
01458 {
01459 gl_error("node:%d (%s) has more phases leaving than entering",obj->id,obj->name);
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470 return TS_INVALID;
01471 }
01472
01473
01474 if (enable_subsecond_models == true)
01475 {
01476 if (solver_method != SM_NR)
01477 {
01478 GL_THROW("deltamode simulations only support powerflow in Newton-Raphson (NR) mode at this time");
01479
01480
01481
01482
01483 }
01484 }
01485
01486
01487 if ((solver_method==SM_FBS) && (FBS_swing_set==false))
01488 {
01489
01490 bustype=SWING;
01491
01492
01493 FBS_swing_set=true;
01494 }
01495 }
01496
01497 if (solver_method==SM_NR)
01498 {
01499 if (prev_NTime==0)
01500 {
01501
01502 if (NR_swing_bus==NULL)
01503 {
01504 GL_THROW("NR: no swing bus found or specified");
01505
01506
01507
01508
01509
01510 }
01511
01512 if (((SubNode == CHILD) || (SubNode == DIFF_CHILD)) && (NR_connected_links[0] > 0))
01513 {
01514 node *parNode = OBJECTDATA(SubNodeParent,node);
01515
01516 WRITELOCK_OBJECT(SubNodeParent);
01517
01518 parNode->NR_connected_links[0] += NR_connected_links[0];
01519
01520
01521 NR_connected_links[0] = 0;
01522
01523 WRITEUNLOCK_OBJECT(SubNodeParent);
01524 }
01525
01526
01527 if (NR_number_child_nodes[0] > 0)
01528 {
01529 NR_child_nodes = (node**)gl_malloc(NR_number_child_nodes[0] * sizeof(node*));
01530
01531
01532 if (NR_child_nodes == NULL)
01533 {
01534 GL_THROW("NR: Failed to allocate child node pointing space");
01535
01536
01537
01538
01539
01540 }
01541
01542
01543 NR_number_child_nodes[1] = 0;
01544 }
01545
01546
01547 if ((SubNode == CHILD) || (SubNode == DIFF_CHILD))
01548 {
01549
01550 node *parNode = OBJECTDATA(SubNodeParent,node);
01551
01552 WRITELOCK_OBJECT(SubNodeParent);
01553
01554
01555 if (house_present==true)
01556 {
01557 parNode->house_present=true;
01558 }
01559
01560
01561 if (parNode->NR_number_child_nodes[1]>=parNode->NR_number_child_nodes[0])
01562 {
01563 gl_error("NR: %s tried to parent to a node that has too many children already",obj->name);
01564
01565
01566
01567
01568
01569 WRITEUNLOCK_OBJECT(SubNodeParent);
01570
01571 return TS_INVALID;
01572 }
01573 else
01574 {
01575
01576 parNode->NR_child_nodes[parNode->NR_number_child_nodes[1]] = OBJECTDATA(obj,node);
01577
01578
01579 parNode->NR_number_child_nodes[1]++;
01580 }
01581
01582 WRITEUNLOCK_OBJECT(SubNodeParent);
01583 }
01584 }
01585
01586 if (NR_busdata==NULL || NR_branchdata==NULL)
01587 {
01588 if ( NR_swing_bus!=obj) WRITELOCK_OBJECT(NR_swing_bus);
01589
01590 NR_busdata = (BUSDATA *)gl_malloc(NR_bus_count * sizeof(BUSDATA));
01591 if (NR_busdata==NULL)
01592 {
01593 gl_error("NR: memory allocation failure for bus table");
01594
01595
01596
01597
01598
01599
01600 if ( NR_swing_bus!=obj) WRITEUNLOCK_OBJECT(NR_swing_bus);
01601
01602 return TS_INVALID;
01603 }
01604 NR_curr_bus = 0;
01605
01606
01607 for (index_val=0; index_val<NR_bus_count; index_val++)
01608 NR_busdata[index_val].type = -1;
01609
01610 NR_branchdata = (BRANCHDATA *)gl_malloc(NR_branch_count * sizeof(BRANCHDATA));
01611 if (NR_branchdata==NULL)
01612 {
01613 gl_error("NR: memory allocation failure for branch table");
01614
01615
01616
01617
01618
01619
01620 if ( NR_swing_bus!=obj) WRITEUNLOCK_OBJECT(NR_swing_bus);
01621
01622 return TS_INVALID;
01623 }
01624 NR_curr_branch = 0;
01625
01626
01627 for (index_val=0; index_val<NR_branch_count; index_val++)
01628 NR_branchdata[index_val].from = -1;
01629
01630
01631 if (enable_subsecond_models==true)
01632 {
01633
01634 if ((pwr_object_current == -1) || (delta_objects==NULL))
01635 {
01636
01637 delta_objects = (OBJECT**)gl_malloc(pwr_object_count*sizeof(OBJECT*));
01638
01639
01640 if (delta_objects == NULL)
01641 {
01642 GL_THROW("Failed to allocate deltamode objects array for powerflow module!");
01643
01644
01645
01646
01647
01648 }
01649
01650
01651 delta_functions = (FUNCTIONADDR*)gl_malloc(pwr_object_count*sizeof(FUNCTIONADDR));
01652
01653
01654 if (delta_functions == NULL)
01655 {
01656 GL_THROW("Failed to allocate deltamode objects function array for powerflow module!");
01657
01658
01659
01660
01661
01662 }
01663
01664
01665 post_delta_functions = (FUNCTIONADDR*)gl_malloc(pwr_object_count*sizeof(FUNCTIONADDR));
01666
01667
01668 if (post_delta_functions == NULL)
01669 {
01670 GL_THROW("Failed to allocate deltamode objects function array for powerflow module!");
01671
01672 }
01673
01674
01675 pwr_object_current = 0;
01676 }
01677
01678
01679 if ((obj == NR_swing_bus) && (deltamode_inclusive == false))
01680 {
01681 gl_warning("SWING bus:%s is not flagged for deltamode",obj->name);
01682
01683
01684
01685
01686
01687
01688 }
01689 }
01690
01691
01692 if (NRMatDumpMethod != MD_NONE)
01693 {
01694
01695 if (MDFileName[0] == '\0')
01696 {
01697 gl_warning("NR: A matrix dump was requested, but no filename was specified. No dump will occur");
01698
01699
01700
01701
01702
01703
01704 NRMatDumpMethod = MD_NONE;
01705 }
01706 else
01707 {
01708
01709 NRFileDump = fopen(MDFileName,"wt");
01710
01711
01712 fprintf(NRFileDump,"Note: All indices are zero-referenced.\n\n");
01713
01714
01715 fclose(NRFileDump);
01716 }
01717 }
01718
01719
01720
01721 if ( NR_swing_bus!=obj) WRITEUNLOCK_OBJECT(NR_swing_bus);
01722
01723 if (obj == NR_swing_bus)
01724 {
01725 NR_populate();
01726 NR_admit_change = true;
01727 NR_swing_bus_reference = NR_node_reference;
01728 }
01729 else
01730 {
01731 GL_THROW("NR: An order requirement has been violated");
01732
01733
01734
01735
01736
01737
01738 }
01739 }
01740
01741
01742
01743 if ((SubNode==PARENT) && (house_present==true))
01744 {
01745 nom_res_curr[0] = nom_res_curr[1] = nom_res_curr[2] = 0.0;
01746 }
01747
01748
01749 if ((deltamode_inclusive==true) && (enable_subsecond_models == true) && (prev_NTime==0))
01750 {
01751 int temp_pwr_object_current;
01752
01753
01754 if (pwr_object_current>=pwr_object_count)
01755 {
01756 GL_THROW("Too many objects tried to populate deltamode objects array in the powerflow module!");
01757
01758
01759
01760
01761
01762 }
01763
01764
01765 if ( NR_swing_bus!=obj) WRITELOCK_OBJECT(NR_swing_bus);
01766
01767
01768 temp_pwr_object_current = pwr_object_current;
01769
01770
01771 pwr_object_current++;
01772
01773
01774 if ( NR_swing_bus!=obj) WRITEUNLOCK_OBJECT(NR_swing_bus);
01775
01776
01777 delta_objects[temp_pwr_object_current] = obj;
01778
01779
01780 delta_functions[temp_pwr_object_current] = (FUNCTIONADDR)(gl_get_function(obj,"interupdate_pwr_object"));
01781
01782
01783 if (delta_functions[temp_pwr_object_current] == NULL)
01784 {
01785 gl_warning("Failure to map deltamode function for device:%s",obj->name);
01786
01787
01788
01789
01790
01791
01792 }
01793
01794
01795 post_delta_functions[temp_pwr_object_current] = (FUNCTIONADDR)(gl_get_function(obj,"postupdate_pwr_object"));
01796
01797
01798
01799
01800 if (((SubNode==CHILD) || (SubNode==DIFF_CHILD)) && ((dynamic_norton==true) || (dynamic_generator==true)))
01801 {
01802
01803 temp_par_node = OBJECTDATA(SubNodeParent,node);
01804
01805
01806 if (temp_par_node == NULL)
01807 {
01808 GL_THROW("node:%s - failed to map parent object for childed node",obj->name);
01809
01810
01811
01812
01813 }
01814
01815
01816 LOCK_OBJECT(SubNodeParent);
01817
01818
01819 if (dynamic_norton==true)
01820 {
01821
01822 temp_par_node->dynamic_norton = true;
01823
01824
01825 if (full_Y_matrix.is_valid(0,0) == true)
01826 {
01827
01828 if ((full_Y_matrix.get_rows() == 3) && (full_Y_matrix.get_cols() == 3))
01829 {
01830
01831 full_Y = (complex *)gl_malloc(9*sizeof(complex));
01832
01833
01834 if (full_Y==NULL)
01835 {
01836 GL_THROW("Node:%s failed to allocate space for the a deltamode variable",(obj->name?obj->name:"Unnamed"));
01837
01838
01839
01840
01841
01842 }
01843
01844
01845 temp_complex_property = new gld_property(SubNodeParent,"deltamode_full_Y_matrix");
01846
01847
01848 if ((temp_complex_property->is_valid() != true) || (temp_complex_property->is_complex_array() != true))
01849 {
01850 GL_THROW("Node:%d - %s - parent deltamode matrix property is not valid!",obj->id,(obj->name ? obj->name : "Unnamed"));
01851
01852
01853
01854
01855 }
01856
01857
01858 temp_complex_property->getp<complex_array>(temp_complex_array,*test_rlock);
01859
01860
01861 if (temp_complex_array.is_valid(0,0) != true)
01862 {
01863
01864 temp_complex_array.grow_to(3,3);
01865
01866
01867 for (temp_idx_x=0; temp_idx_x<3; temp_idx_x++)
01868 {
01869 for (temp_idx_y=0; temp_idx_y<3; temp_idx_y++)
01870 {
01871 temp_complex_array.set_at(temp_idx_x,temp_idx_y,complex(0.0,0.0));
01872 }
01873 }
01874 }
01875 else
01876 {
01877 if ((temp_complex_array.get_rows() != 3) && (temp_complex_array.get_cols() != 3))
01878 {
01879 GL_THROW("node:%s exposed Norton-equivalent matrix is the wrong size!",obj->name?obj->name:"unnamed");
01880
01881
01882
01883
01884 }
01885
01886 }
01887
01888
01889 temp_complex_array += full_Y_matrix;
01890
01891
01892 temp_complex_property->setp<complex_array>(temp_complex_array,*test_rlock);
01893
01894
01895 full_Y[0] = full_Y_matrix.get_at(0,0);
01896 full_Y[1] = full_Y_matrix.get_at(0,1);
01897 full_Y[2] = full_Y_matrix.get_at(0,2);
01898
01899 full_Y[3] = full_Y_matrix.get_at(1,0);
01900 full_Y[4] = full_Y_matrix.get_at(1,1);
01901 full_Y[5] = full_Y_matrix.get_at(1,2);
01902
01903 full_Y[6] = full_Y_matrix.get_at(2,0);
01904 full_Y[7] = full_Y_matrix.get_at(2,1);
01905 full_Y[8] = full_Y_matrix.get_at(2,2);
01906 }
01907 else
01908 {
01909 GL_THROW("Node:%d - %s - Invalid deltamode matrix size!",obj->id,(obj->name ? obj->name : "Unnamed"));
01910
01911
01912
01913
01914 }
01915 }
01916
01917
01918 full_Y_all = NULL;
01919
01920
01921 if (full_Y_all_matrix.is_valid(0,0) == true)
01922 {
01923
01924 if ((full_Y_all_matrix.get_rows() != 3) && (full_Y_all_matrix.get_cols() != 3))
01925 {
01926 GL_THROW("node:%s exposed Norton-equivalent matrix is the wrong size!",obj->name?obj->name:"unnamed");
01927
01928 }
01929 }
01930 else
01931 {
01932 full_Y_all_matrix.grow_to(3,3);
01933 }
01934
01935
01936 for (temp_idx_x=0; temp_idx_x<3; temp_idx_x++)
01937 {
01938 for (temp_idx_y=0; temp_idx_y<3; temp_idx_y++)
01939 {
01940 full_Y_all_matrix.set_at(temp_idx_x,temp_idx_y,complex(0.0,0.0));
01941 }
01942 }
01943 }
01944
01945
01946 if (dynamic_generator==true)
01947 {
01948
01949 temp_par_node->dynamic_generator = true;
01950 }
01951
01952
01953 UNLOCK_OBJECT(SubNodeParent);
01954
01955
01956 if (dynamic_norton!=true)
01957 {
01958 full_Y = NULL;
01959 full_Y_all = NULL;
01960 }
01961
01962
01963 }
01964 }
01965
01966
01967 temp_time_value = NR_node_presync_fxn(t0);
01968
01969
01970 temp_t1_value = t1;
01971
01972
01973 if ((temp_t1_value != TS_NEVER) && (temp_time_value != TS_NEVER))
01974 {
01975
01976 if (temp_t1_value < 0)
01977 {
01978 if (-temp_t1_value < temp_time_value)
01979 {
01980 t1 = temp_t1_value;
01981 }
01982 else
01983 {
01984 t1 = -temp_time_value;
01985 }
01986 }
01987 else
01988 {
01989 if (temp_t1_value < temp_time_value)
01990 {
01991 t1 = -temp_t1_value;
01992 }
01993 else
01994 {
01995 t1 = -temp_time_value;
01996 }
01997 }
01998 }
01999 else if (temp_t1_value != TS_NEVER)
02000 {
02001 t1 = temp_t1_value;
02002 }
02003 else if (temp_time_value != TS_NEVER)
02004 {
02005 t1 = -temp_time_value;
02006 }
02007 else
02008 {
02009 t1 = TS_NEVER;
02010 }
02011 }
02012 else if (solver_method==SM_FBS)
02013 {
02014 #ifdef SUPPORT_OUTAGES
02015 if (condition!=OC_NORMAL)
02016 {
02017 voltage[0] = voltage[1] = voltage[2] = 0.0;
02018 condition = OC_NORMAL;
02019 }
02020 #endif
02021
02022 current_inj[0] = current_inj[1] = current_inj[2] = complex(0,0);
02023
02024
02025 last_voltage[0] = voltage[0];
02026 last_voltage[1] = voltage[1];
02027 last_voltage[2] = voltage[2];
02028
02029
02030 if (reference_bus!=NULL)
02031 {
02032 node *pRef = OBJECTDATA(reference_bus,node);
02033 frequency = pRef->frequency;
02034 }
02035 }
02036
02037 return t1;
02038 }
02039
02040
02041
02042 void node::NR_node_sync_fxn(OBJECT *obj)
02043 {
02044 int loop_index_var;
02045 STATUS fxn_ret_value;
02046
02047
02048 unsigned char phase_checks_var;
02049
02050
02051 if (NR_node_reference!=-1)
02052 {
02053
02054 if ((reset_island_state == true) && (NR_island_fail_method == true))
02055 {
02056
02057 fxn_ret_value = reset_node_island_condition();
02058 }
02059
02060
02061
02062 if ((SubNode!=CHILD) && (SubNode!=DIFF_CHILD))
02063 {
02064
02065 phase_checks_var = ((NR_busdata[NR_node_reference].phases ^ prev_phases) & 0x8F);
02066
02067 if (phase_checks_var != 0x00)
02068 {
02069
02070 if ((NR_busdata[NR_node_reference].origphases & 0x80) == 0x80)
02071 {
02072
02073 if ((NR_busdata[NR_node_reference].phases & 0x80) == 0x00)
02074 {
02075
02076 last_voltage[0] = voltage[0];
02077 last_voltage[1] = voltage[1];
02078 last_voltage[2] = voltage[2];
02079
02080
02081 voltage[0] = 0.0;
02082 voltage[1] = 0.0;
02083 voltage[2] = 0.0;
02084 }
02085 else
02086 {
02087
02088 if (enable_inrush_calculations == false)
02089 {
02090 voltage[0] = last_voltage[0];
02091 voltage[1] = last_voltage[1];
02092 voltage[2] = last_voltage[2];
02093 }
02094 else
02095 {
02096 voltage[0] = last_voltage[0] * MULTTERM;
02097 voltage[1] = last_voltage[1] * MULTTERM;
02098 voltage[2] = last_voltage[2] * MULTTERM;
02099 }
02100
02101
02102 }
02103
02104
02105 voltaged[0] = voltage[0] + voltage[1];
02106 voltaged[1] = voltage[1] - voltage[2];
02107 voltaged[2] = voltage[0] - voltage[2];
02108
02109 }
02110 else
02111 {
02112
02113 if ((phase_checks_var & 0x04) == 0x04)
02114 {
02115
02116 if ((prev_phases & 0x04) == 0x04)
02117 {
02118 last_voltage[0] = voltage[0];
02119 voltage[0] = 0.0;
02120 }
02121 else
02122 {
02123 if (enable_inrush_calculations == false)
02124 {
02125 voltage[0] = last_voltage[0];
02126 }
02127 else
02128 {
02129 voltage[0] = last_voltage[0] * MULTTERM;
02130 }
02131
02132
02133 }
02134 }
02135
02136
02137 if ((phase_checks_var & 0x02) == 0x02)
02138 {
02139
02140 if ((prev_phases & 0x02) == 0x02)
02141 {
02142 last_voltage[1] = voltage[1];
02143 voltage[1] = 0.0;
02144 }
02145 else
02146 {
02147 if (enable_inrush_calculations == false)
02148 {
02149 voltage[1] = last_voltage[1];
02150 }
02151 else
02152 {
02153 voltage[1] = last_voltage[1] * MULTTERM;
02154 }
02155
02156
02157 }
02158 }
02159
02160
02161 if ((phase_checks_var & 0x01) == 0x01)
02162 {
02163
02164 if ((prev_phases & 0x01) == 0x01)
02165 {
02166 last_voltage[2] = voltage[2];
02167 voltage[2] = 0.0;
02168 }
02169 else
02170 {
02171 if (enable_inrush_calculations == false)
02172 {
02173 voltage[2] = last_voltage[2];
02174 }
02175 else
02176 {
02177 voltage[2] = last_voltage[2] * MULTTERM;
02178 }
02179
02180
02181 }
02182 }
02183
02184
02185 voltaged[0] = voltage[0] - voltage[1];
02186 voltaged[1] = voltage[1] - voltage[2];
02187 voltaged[2] = voltage[2] - voltage[0];
02188 }
02189
02190
02191 prev_phases = NR_busdata[NR_node_reference].phases;
02192 }
02193 }
02194
02195 if (SubNode==CHILD)
02196 {
02197
02198 node *ParToLoad = OBJECTDATA(SubNodeParent,node);
02199
02200 if (gl_object_isa(SubNodeParent,"load","powerflow"))
02201 {
02202
02203 LOCK_OBJECT(SubNodeParent);
02204
02205
02206 ParToLoad->power[0]+=power[0];
02207 ParToLoad->power[1]+=power[1];
02208 ParToLoad->power[2]+=power[2];
02209
02210 ParToLoad->shunt[0]+=shunt[0];
02211 ParToLoad->shunt[1]+=shunt[1];
02212 ParToLoad->shunt[2]+=shunt[2];
02213
02214 ParToLoad->current[0]+=current[0];
02215 ParToLoad->current[1]+=current[1];
02216 ParToLoad->current[2]+=current[2];
02217
02218
02219 ParToLoad->pre_rotated_current[0] += pre_rotated_current[0];
02220 ParToLoad->pre_rotated_current[1] += pre_rotated_current[1];
02221 ParToLoad->pre_rotated_current[2] += pre_rotated_current[2];
02222
02223
02224 if (deltamode_inclusive == true)
02225 {
02226
02227
02228 deltamode_dynamic_current[0] = ParToLoad->deltamode_dynamic_current[0];
02229 deltamode_dynamic_current[1] = ParToLoad->deltamode_dynamic_current[1];
02230 deltamode_dynamic_current[2] = ParToLoad->deltamode_dynamic_current[2];
02231 }
02232
02233
02234 for (loop_index_var=0; loop_index_var<6; loop_index_var++)
02235 {
02236 ParToLoad->power_dy[loop_index_var] += power_dy[loop_index_var];
02237 ParToLoad->shunt_dy[loop_index_var] += shunt_dy[loop_index_var];
02238 ParToLoad->current_dy[loop_index_var] += current_dy[loop_index_var];
02239 }
02240
02241
02242 UNLOCK_OBJECT(SubNodeParent);
02243 }
02244 else if (gl_object_isa(SubNodeParent,"node","powerflow"))
02245 {
02246
02247 LOCK_OBJECT(SubNodeParent);
02248
02249
02250 ParToLoad->power[0]+=power[0]-last_child_power[0][0];
02251 ParToLoad->power[1]+=power[1]-last_child_power[0][1];
02252 ParToLoad->power[2]+=power[2]-last_child_power[0][2];
02253
02254 ParToLoad->shunt[0]+=shunt[0]-last_child_power[1][0];
02255 ParToLoad->shunt[1]+=shunt[1]-last_child_power[1][1];
02256 ParToLoad->shunt[2]+=shunt[2]-last_child_power[1][2];
02257
02258 ParToLoad->current[0]+=current[0]-last_child_power[2][0];
02259 ParToLoad->current[1]+=current[1]-last_child_power[2][1];
02260 ParToLoad->current[2]+=current[2]-last_child_power[2][2];
02261
02262 ParToLoad->pre_rotated_current[0] += pre_rotated_current[0]-last_child_power[3][0];
02263 ParToLoad->pre_rotated_current[1] += pre_rotated_current[1]-last_child_power[3][1];
02264 ParToLoad->pre_rotated_current[2] += pre_rotated_current[2]-last_child_power[3][2];
02265
02266
02267 if (deltamode_inclusive == true)
02268 {
02269
02270
02271 deltamode_dynamic_current[0] = ParToLoad->deltamode_dynamic_current[0];
02272 deltamode_dynamic_current[1] = ParToLoad->deltamode_dynamic_current[1];
02273 deltamode_dynamic_current[2] = ParToLoad->deltamode_dynamic_current[2];
02274 }
02275
02276
02277 for (loop_index_var=0; loop_index_var<6; loop_index_var++)
02278 {
02279 ParToLoad->power_dy[loop_index_var] += power_dy[loop_index_var] - last_child_power_dy[loop_index_var][0];
02280 ParToLoad->shunt_dy[loop_index_var] += shunt_dy[loop_index_var] - last_child_power_dy[loop_index_var][1];
02281 ParToLoad->current_dy[loop_index_var] += current_dy[loop_index_var] - last_child_power_dy[loop_index_var][2];
02282 }
02283
02284 if (has_phase(PHASE_S))
02285 {
02286 ParToLoad->current12 +=current12-last_child_current12;
02287 }
02288
02289
02290 if (house_present==true)
02291 {
02292 ParToLoad->nom_res_curr[0] += nom_res_curr[0];
02293 ParToLoad->nom_res_curr[1] += nom_res_curr[1];
02294 ParToLoad->nom_res_curr[2] += nom_res_curr[2];
02295 }
02296
02297
02298 UNLOCK_OBJECT(SubNodeParent);
02299 }
02300 else
02301 {
02302 GL_THROW("NR: Object %d is a child of something that it shouldn't be!",obj->id);
02303
02304
02305
02306
02307 }
02308
02309
02310 last_child_power[0][0] = power[0];
02311 last_child_power[0][1] = power[1];
02312 last_child_power[0][2] = power[2];
02313
02314 last_child_power[1][0] = shunt[0];
02315 last_child_power[1][1] = shunt[1];
02316 last_child_power[1][2] = shunt[2];
02317
02318 last_child_power[2][0] = current[0];
02319 last_child_power[2][1] = current[1];
02320 last_child_power[2][2] = current[2];
02321
02322 last_child_power[3][0] = pre_rotated_current[0];
02323 last_child_power[3][1] = pre_rotated_current[1];
02324 last_child_power[3][2] = pre_rotated_current[2];
02325
02326
02327 for (loop_index_var=0; loop_index_var<6; loop_index_var++)
02328 {
02329 last_child_power_dy[loop_index_var][0] = power_dy[loop_index_var];
02330 last_child_power_dy[loop_index_var][1] = shunt_dy[loop_index_var];
02331 last_child_power_dy[loop_index_var][2] = current_dy[loop_index_var];
02332 }
02333
02334 if (has_phase(PHASE_S))
02335 last_child_current12 = current12;
02336 }
02337
02338
02339 if (SubNode==DIFF_CHILD)
02340 {
02341
02342 node *ParToLoad = OBJECTDATA(SubNodeParent,node);
02343
02344
02345 LOCK_OBJECT(SubNodeParent);
02346
02347
02348 ParToLoad->Extra_Data[0] += power[0];
02349 ParToLoad->Extra_Data[1] += power[1];
02350 ParToLoad->Extra_Data[2] += power[2];
02351
02352 ParToLoad->Extra_Data[3] += shunt[0];
02353 ParToLoad->Extra_Data[4] += shunt[1];
02354 ParToLoad->Extra_Data[5] += shunt[2];
02355
02356 ParToLoad->Extra_Data[6] += current[0];
02357 ParToLoad->Extra_Data[7] += current[1];
02358 ParToLoad->Extra_Data[8] += current[2];
02359
02360
02361 ParToLoad->pre_rotated_current[0] += pre_rotated_current[0];
02362 ParToLoad->pre_rotated_current[1] += pre_rotated_current[1];
02363 ParToLoad->pre_rotated_current[2] += pre_rotated_current[2];
02364
02365
02366 if (deltamode_inclusive == true)
02367 {
02368
02369
02370 deltamode_dynamic_current[0] = ParToLoad->deltamode_dynamic_current[0];
02371 deltamode_dynamic_current[1] = ParToLoad->deltamode_dynamic_current[1];
02372 deltamode_dynamic_current[2] = ParToLoad->deltamode_dynamic_current[2];
02373 }
02374
02375
02376 for (loop_index_var=0; loop_index_var<6; loop_index_var++)
02377 {
02378 ParToLoad->power_dy[loop_index_var] += power_dy[loop_index_var];
02379 ParToLoad->shunt_dy[loop_index_var] += shunt_dy[loop_index_var];
02380 ParToLoad->current_dy[loop_index_var] += current_dy[loop_index_var];
02381 }
02382
02383
02384 UNLOCK_OBJECT(SubNodeParent);
02385
02386
02387 for (loop_index_var=0; loop_index_var<6; loop_index_var++)
02388 {
02389 last_child_power_dy[loop_index_var][0] = power_dy[loop_index_var];
02390 last_child_power_dy[loop_index_var][1] = shunt_dy[loop_index_var];
02391 last_child_power_dy[loop_index_var][2] = current_dy[loop_index_var];
02392 }
02393
02394
02395 last_child_power[3][0] = pre_rotated_current[0];
02396 last_child_power[3][1] = pre_rotated_current[1];
02397 last_child_power[3][2] = pre_rotated_current[2];
02398 }
02399
02400
02401
02402 if (VFD_attached == true)
02403 {
02404
02405 fxn_ret_value = ((STATUS (*)(OBJECT *))(*VFD_updating_function))(VFD_object);
02406
02407
02408 if (fxn_ret_value == FAILED)
02409 {
02410 GL_THROW("node:%d - %s -- Failed VFD updating function",obj->id,(obj->name ? obj->name : "Unnamed"));
02411
02412
02413
02414
02415 }
02416 }
02417 }
02418 }
02419
02420 TIMESTAMP node::sync(TIMESTAMP t0)
02421 {
02422 TIMESTAMP t1 = powerflow_object::sync(t0);
02423 OBJECT *obj = OBJECTHDR(this);
02424 complex delta_current[3];
02425 complex power_current[3];
02426 complex delta_shunt[3];
02427 complex delta_shunt_curr[3];
02428 complex dy_curr_accum[3];
02429 complex temp_current_val[3];
02430
02431
02432 if (t0!=prev_NTime)
02433 {
02434
02435 prev_NTime=t0;
02436 }
02437
02438 switch (solver_method)
02439 {
02440 case SM_FBS:
02441 {
02442 if (phases&PHASE_S)
02443 {
02444 complex temp_inj[2];
02445 complex adjusted_curr[3];
02446 complex temp_curr_val[3];
02447
02448 if (house_present)
02449 {
02450
02451 adjusted_curr[0].SetPolar(1.0,voltage[0].Arg());
02452 adjusted_curr[1].SetPolar(1.0,voltage[1].Arg());
02453 adjusted_curr[2].SetPolar(1.0,voltaged[0].Arg());
02454
02455
02456 temp_curr_val[0] = nom_res_curr[0]/(~adjusted_curr[0]);
02457 temp_curr_val[1] = nom_res_curr[1]/(~adjusted_curr[1]);
02458 temp_curr_val[2] = nom_res_curr[2]/(~adjusted_curr[2]);
02459 }
02460 else
02461 {
02462 temp_curr_val[0] = temp_curr_val[1] = temp_curr_val[2] = 0.0;
02463 }
02464
02465 #ifdef SUPPORT_OUTAGES
02466 if (voltage[0]!=0.0)
02467 {
02468 #endif
02469 complex d1 = (voltage1.IsZero() || (power1.IsZero() && shunt1.IsZero())) ? (current1 + temp_curr_val[0]) : (current1 + ~(power1/voltage1) + voltage1*shunt1 + temp_curr_val[0]);
02470 complex d2 = ((voltage1+voltage2).IsZero() || (power12.IsZero() && shunt12.IsZero())) ? (current12 + temp_curr_val[2]) : (current12 + ~(power12/(voltage1+voltage2)) + (voltage1+voltage2)*shunt12 + temp_curr_val[2]);
02471
02472 current_inj[0] += d1;
02473 temp_inj[0] = current_inj[0];
02474 current_inj[0] += d2;
02475
02476 #ifdef SUPPORT_OUTAGES
02477 }
02478 else
02479 {
02480 temp_inj[0] = 0.0;
02481
02482 current_inj[0]=0.0;
02483
02484 }
02485
02486 if (voltage[1]!=0)
02487 {
02488 #endif
02489 d1 = (voltage2.IsZero() || (power2.IsZero() && shunt2.IsZero())) ? (-current2 - temp_curr_val[1]) : (-current2 - ~(power2/voltage2) - voltage2*shunt2 - temp_curr_val[1]);
02490 d2 = ((voltage1+voltage2).IsZero() || (power12.IsZero() && shunt12.IsZero())) ? (-current12 - temp_curr_val[2]) : (-current12 - ~(power12/(voltage1+voltage2)) - (voltage1+voltage2)*shunt12 - temp_curr_val[2]);
02491
02492 current_inj[1] += d1;
02493 temp_inj[1] = current_inj[1];
02494 current_inj[1] += d2;
02495
02496 #ifdef SUPPORT_OUTAGES
02497 }
02498 else
02499 {
02500 temp_inj[0] = 0.0;
02501
02502 current_inj[1] = 0.0;
02503
02504 }
02505 #endif
02506
02507 if (obj->parent!=NULL && gl_object_isa(obj->parent,"triplex_line","powerflow")) {
02508 link_object *plink = OBJECTDATA(obj->parent,link_object);
02509 complex d = plink->tn[0]*current_inj[0] + plink->tn[1]*current_inj[1];
02510 current_inj[2] += d;
02511 }
02512 else {
02513 complex d = ((voltage1.IsZero() || (power1.IsZero() && shunt1.IsZero())) ||
02514 (voltage2.IsZero() || (power2.IsZero() && shunt2.IsZero())))
02515 ? currentN : -(temp_inj[0] + temp_inj[1]);
02516 current_inj[2] += d;
02517 }
02518 }
02519 else if (has_phase(PHASE_D))
02520 {
02521
02522
02523 delta_current[0]= (voltaged[0].IsZero()) ? 0 : ~(power[0]/voltaged[0]);
02524 delta_current[1]= (voltaged[1].IsZero()) ? 0 : ~(power[1]/voltaged[1]);
02525 delta_current[2]= (voltaged[2].IsZero()) ? 0 : ~(power[2]/voltaged[2]);
02526
02527 power_current[0]=delta_current[0]-delta_current[2];
02528 power_current[1]=delta_current[1]-delta_current[0];
02529 power_current[2]=delta_current[2]-delta_current[1];
02530
02531
02532 delta_shunt[0] = voltaged[0]*shunt[0];
02533 delta_shunt[1] = voltaged[1]*shunt[1];
02534 delta_shunt[2] = voltaged[2]*shunt[2];
02535
02536 delta_shunt_curr[0] = delta_shunt[0]-delta_shunt[2];
02537 delta_shunt_curr[1] = delta_shunt[1]-delta_shunt[0];
02538 delta_shunt_curr[2] = delta_shunt[2]-delta_shunt[1];
02539
02540
02541 delta_current[0]=current[0]-current[2];
02542 delta_current[1]=current[1]-current[0];
02543 delta_current[2]=current[2]-current[1];
02544
02545 #ifdef SUPPORT_OUTAGES
02546 for (char kphase=0;kphase<3;kphase++)
02547 {
02548 if (voltaged[kphase]==0.0)
02549 {
02550
02551 current_inj[kphase] = 0.0;
02552
02553 }
02554 else
02555 {
02556
02557 current_inj[kphase] += delta_current[kphase] + power_current[kphase] + delta_shunt_curr[kphase];
02558
02559 }
02560 }
02561 #else
02562 temp_current_val[0] = delta_current[0] + power_current[0] + delta_shunt_curr[0];
02563 temp_current_val[1] = delta_current[1] + power_current[1] + delta_shunt_curr[1];
02564 temp_current_val[2] = delta_current[2] + power_current[2] + delta_shunt_curr[2];
02565
02566 current_inj[0] += temp_current_val[0];
02567 current_inj[1] += temp_current_val[1];
02568 current_inj[2] += temp_current_val[2];
02569 #endif
02570 }
02571 else
02572 {
02573
02574 #ifdef SUPPORT_OUTAGES
02575 for (char kphase=0;kphase<3;kphase++)
02576 {
02577 if (voltage[kphase]==0.0)
02578 {
02579
02580 current_inj[kphase] = 0.0;
02581
02582 }
02583 else
02584 {
02585 complex d = ((voltage[kphase]==0.0) || ((power[kphase] == 0) && shunt[kphase].IsZero())) ? current[kphase] : current[kphase] + ~(power[kphase]/voltage[kphase]) + voltage[kphase]*shunt[kphase];
02586
02587 current_inj[kphase] += d;
02588
02589 }
02590 }
02591 #else
02592
02593 temp_current_val[0] = (voltage[0].IsZero() || (power[0].IsZero() && shunt[0].IsZero())) ? current[0] : current[0] + ~(power[0]/voltage[0]) + voltage[0]*shunt[0];
02594 temp_current_val[1] = (voltage[1].IsZero() || (power[1].IsZero() && shunt[1].IsZero())) ? current[1] : current[1] + ~(power[1]/voltage[1]) + voltage[1]*shunt[1];
02595 temp_current_val[2] = (voltage[2].IsZero() || (power[2].IsZero() && shunt[2].IsZero())) ? current[2] : current[2] + ~(power[2]/voltage[2]) + voltage[2]*shunt[2];
02596
02597 current_inj[0] += temp_current_val[0];
02598 current_inj[1] += temp_current_val[1];
02599 current_inj[2] += temp_current_val[2];
02600 #endif
02601 }
02602
02603
02604 if (!(has_phase(PHASE_S)))
02605 {
02606
02607 delta_current[0]= (voltageAB.IsZero()) ? 0 : ~(power_dy[0]/voltageAB);
02608 delta_current[1]= (voltageBC.IsZero()) ? 0 : ~(power_dy[1]/voltageBC);
02609 delta_current[2]= (voltageCA.IsZero()) ? 0 : ~(power_dy[2]/voltageCA);
02610
02611 power_current[0]=delta_current[0]-delta_current[2];
02612 power_current[1]=delta_current[1]-delta_current[0];
02613 power_current[2]=delta_current[2]-delta_current[1];
02614
02615
02616 delta_shunt[0] = voltageAB*shunt_dy[0];
02617 delta_shunt[1] = voltageBC*shunt_dy[1];
02618 delta_shunt[2] = voltageCA*shunt_dy[2];
02619
02620 delta_shunt_curr[0] = delta_shunt[0]-delta_shunt[2];
02621 delta_shunt_curr[1] = delta_shunt[1]-delta_shunt[0];
02622 delta_shunt_curr[2] = delta_shunt[2]-delta_shunt[1];
02623
02624
02625 delta_current[0]=current_dy[0]-current_dy[2];
02626 delta_current[1]=current_dy[1]-current_dy[0];
02627 delta_current[2]=current_dy[2]-current_dy[1];
02628
02629
02630 dy_curr_accum[0] = delta_current[0] + power_current[0] + delta_shunt_curr[0];
02631 dy_curr_accum[1] = delta_current[1] + power_current[1] + delta_shunt_curr[1];
02632 dy_curr_accum[2] = delta_current[2] + power_current[2] + delta_shunt_curr[2];
02633
02634
02635 dy_curr_accum[0] += (voltageA.IsZero() || (power_dy[3].IsZero() && shunt_dy[3].IsZero())) ? current_dy[3] : current_dy[3] + ~(power_dy[3]/voltageA) + voltageA*shunt_dy[3];
02636 dy_curr_accum[1] += (voltageB.IsZero() || (power_dy[4].IsZero() && shunt_dy[4].IsZero())) ? current_dy[4] : current_dy[4] + ~(power_dy[4]/voltageB) + voltageB*shunt_dy[4];
02637 dy_curr_accum[2] += (voltageC.IsZero() || (power_dy[5].IsZero() && shunt_dy[5].IsZero())) ? current_dy[5] : current_dy[5] + ~(power_dy[5]/voltageC) + voltageC*shunt_dy[5];
02638
02639
02640 current_inj[0] += dy_curr_accum[0];
02641 current_inj[1] += dy_curr_accum[1];
02642 current_inj[2] += dy_curr_accum[2];
02643
02644 }
02645
02646 #ifdef SUPPORT_OUTAGES
02647 if (is_open_any())
02648 throw "unable to handle node open phase condition";
02649
02650 if (is_contact_any())
02651 {
02652
02653 if (is_contact(PHASE_A|PHASE_B|PHASE_C))
02654 voltageA = voltageB = voltageC = (voltageA + voltageB + voltageC)/3;
02655 else if (is_contact(PHASE_A|PHASE_B))
02656 voltageA = voltageB = (voltageA + voltageB)/2;
02657 else if (is_contact(PHASE_B|PHASE_C))
02658 voltageB = voltageC = (voltageB + voltageC)/2;
02659 else if (is_contact(PHASE_A|PHASE_C))
02660 voltageA = voltageC = (voltageA + voltageC)/2;
02661
02662
02663 if (is_contact(PHASE_A|PHASE_N) || is_contact(PHASE_A|GROUND))
02664 voltageA /= 2;
02665 if (is_contact(PHASE_B|PHASE_N) || is_contact(PHASE_B|GROUND))
02666 voltageB /= 2;
02667 if (is_contact(PHASE_C|PHASE_N) || is_contact(PHASE_C|GROUND))
02668 voltageC /= 2;
02669 }
02670 #endif
02671
02672
02673 if (obj->parent!=NULL && gl_object_isa(obj->parent,"node","powerflow"))
02674 {
02675 node *pNode = OBJECTDATA(obj->parent,node);
02676
02677
02678 if (((pNode->phases & phases) & (!(PHASE_D | PHASE_N))) == (phases & (!(PHASE_D | PHASE_N))))
02679 {
02680
02681 WRITELOCK_OBJECT(obj->parent);
02682 pNode->current_inj[0] += current_inj[0];
02683 pNode->current_inj[1] += current_inj[1];
02684 pNode->current_inj[2] += current_inj[2];
02685 WRITEUNLOCK_OBJECT(obj->parent);
02686 }
02687 else
02688 GL_THROW("Node:%d's parent does not have the proper phase connection to be a parent.",obj->id);
02689
02690
02691
02692
02693 }
02694
02695 break;
02696 }
02697 case SM_NR:
02698 {
02699
02700 NR_node_sync_fxn(obj);
02701
02702 if ((NR_curr_bus==NR_bus_count) && (obj==NR_swing_bus))
02703 {
02704 bool bad_computation=false;
02705 NRSOLVERMODE powerflow_type;
02706
02707
02708 if (fault_check_override_mode == true)
02709 {
02710
02711 return t0;
02712 }
02713
02714
02715 if (deltamode_inclusive)
02716 {
02717 if (NR_dyn_first_run==true)
02718 {
02719 powerflow_type = PF_DYNINIT;
02720 NR_dyn_first_run = false;
02721 }
02722 else
02723 {
02724 powerflow_type = PF_DYNCALC;
02725 }
02726 }
02727 else
02728 {
02729 powerflow_type = PF_NORMAL;
02730 }
02731
02732 int64 result = solver_nr(NR_bus_count, NR_busdata, NR_branch_count, NR_branchdata, &NR_powerflow, powerflow_type, NULL, &bad_computation);
02733
02734
02735 NR_admit_change = false;
02736
02737 if (bad_computation==true)
02738 {
02739 GL_THROW("Newton-Raphson method is unable to converge to a solution at this operation point");
02740
02741
02742
02743
02744
02745 }
02746 else if (result<0)
02747 {
02748 gl_verbose("Newton-Raphson failed to converge, sticking at same iteration.");
02749
02750
02751
02752
02753 NR_retval=t0;
02754 }
02755 else
02756 NR_retval=t1;
02757
02758
02759 return NR_retval;
02760 }
02761 else if (NR_curr_bus==NR_bus_count)
02762 return t1;
02763 else
02764 {
02765 if (obj == NR_swing_bus)
02766 {
02767 GL_THROW("All nodes were not properly populated");
02768
02769
02770
02771
02772
02773 }
02774 else
02775 {
02776
02777 if (NR_node_reference == -1)
02778 {
02779
02780 gl_error("Unconnected node - %s id:%d",obj->name?obj->name:"Unknown",obj->id);
02781
02782
02783
02784
02785
02786 }
02787
02788 return t0;
02789 }
02790 }
02791 break;
02792 }
02793 default:
02794 GL_THROW("unsupported solver method");
02795
02796
02797
02798
02799 break;
02800 }
02801 return t1;
02802 }
02803
02804
02805
02806 void node::BOTH_node_postsync_fxn(OBJECT *obj)
02807 {
02808 double curr_delta_time;
02809 complex_array temp_complex_array;
02810 int index_x_val, index_y_val;
02811 gld_property *temp_property;
02812 gld_wlock *test_rlock;
02813
02814
02815 if ((deltamode_inclusive == true) && (dynamic_norton==true))
02816 {
02817
02818 if ((SubNode==CHILD) || (SubNode==DIFF_CHILD))
02819 {
02820
02821 temp_property = new gld_property(SubNodeParent,"deltamode_full_Y_all_matrix");
02822
02823
02824 if ((temp_property->is_valid() != true) || (temp_property->is_complex_array() != true))
02825 {
02826 GL_THROW("Node:%d - %s - Failed to map deltamode matrix to parent",obj->id,(obj->name ? obj->name : "Unnamed"));
02827
02828
02829
02830
02831 }
02832
02833
02834 temp_property->getp<complex_array>(temp_complex_array,*test_rlock);
02835
02836
02837 if ((temp_complex_array.get_rows() == 3) && (temp_complex_array.get_cols() == 3))
02838 {
02839
02840 full_Y_all_matrix = temp_complex_array;
02841 }
02842
02843
02844
02845 delete temp_property;
02846 }
02847 else
02848 {
02849
02850 if (full_Y_all_matrix.is_valid(0,0) == true)
02851 {
02852
02853 if ((full_Y_all_matrix.get_rows() != 3) || (full_Y_matrix.get_cols() != 3))
02854 {
02855
02856 full_Y_all_matrix.grow_to(3,3);
02857 }
02858 }
02859 else
02860 {
02861 full_Y_all_matrix.grow_to(3,3);
02862 }
02863
02864
02865 if (full_Y_all != NULL)
02866 {
02867
02868 for (index_x_val=0; index_x_val<3; index_x_val++)
02869 {
02870 for (index_y_val=0; index_y_val<3; index_y_val++)
02871 {
02872 full_Y_all_matrix.set_at(index_x_val,index_y_val,full_Y_all[index_x_val*3+index_y_val]);
02873 }
02874 }
02875 }
02876 else
02877 {
02878 GL_THROW("Node:%d - %s - Node tried to update a deltamode matrix that does not exist!",obj->id,(obj->name ? obj->name : "Unnamed"));
02879
02880
02881
02882
02883 }
02884 }
02885 }
02886
02887
02888
02889 if ((deltatimestep_running > 0) && (enable_inrush_calculations == true))
02890 {
02891
02892 curr_delta_time = gl_globaldeltaclock;
02893
02894
02895 if (curr_delta_time != prev_delta_time)
02896 {
02897
02898 prev_delta_time = curr_delta_time;
02899 }
02900 }
02901
02902
02903
02904 if (require_voltage_control==TRUE)
02905 {
02906
02907 if ((busflags&NF_HASSOURCE)==0 && bustype==PQ)
02908 voltage[0] = voltage[1] = voltage[2] = complex(0,0);
02909 }
02910
02911
02912 if (has_phase(PHASE_S))
02913 {
02914 voltaged[0] = voltage[0] + voltage[1];
02915 voltaged[1] = voltage[1] - voltage[2];
02916 voltaged[2] = voltage[0] - voltage[2];
02917 }
02918 else
02919 {
02920 voltaged[0] = voltage[0] - voltage[1];
02921 voltaged[1] = voltage[1] - voltage[2];
02922 voltaged[2] = voltage[2] - voltage[0];
02923 }
02924
02925
02926 if (solver_method == SM_NR)
02927 {
02928 int result = NR_current_update(false);
02929
02930
02931 if (result != 1)
02932 {
02933 GL_THROW("Attempt to update current/power on node:%s failed!",obj->name);
02934
02935 }
02936 }
02937 }
02938
02939 TIMESTAMP node::postsync(TIMESTAMP t0)
02940 {
02941 TIMESTAMP t1 = powerflow_object::postsync(t0);
02942 TIMESTAMP RetValue=t1;
02943 OBJECT *obj = OBJECTHDR(this);
02944
02945 #ifdef SUPPORT_OUTAGES
02946 if (condition!=OC_NORMAL)
02947 {
02948 voltage[0] = voltage[1] = voltage[2] = 0.0;
02949 }
02950
02951 if (is_contact_any())
02952 {
02953 complex dVAB = voltageA - voltageB;
02954 complex dVBC = voltageB - voltageC;
02955 complex dVCA = voltageC - voltageA;
02956
02957
02958
02959 if (is_contact(PHASE_A|PHASE_B|PHASE_C))
02961 throw "three-way contact not supported yet";
02962 else if (is_contact(PHASE_A|PHASE_B))
02963 current_inj[0] = - current_inj[1] = dVAB/fault_Z;
02964 else if (is_contact(PHASE_B|PHASE_C))
02965 current_inj[1] = - current_inj[2] = dVBC/fault_Z;
02966 else if (is_contact(PHASE_A|PHASE_C))
02967 current_inj[2] = - current_inj[0] = dVCA/fault_Z;
02968
02969
02970 if (is_contact(PHASE_A|PHASE_N) || is_contact(PHASE_A|GROUND))
02971 current_inj[0] = voltageA / fault_Z;
02972 if (is_contact(PHASE_B|PHASE_N) || is_contact(PHASE_B|GROUND))
02973 current_inj[1] = voltageB / fault_Z;
02974 if (is_contact(PHASE_C|PHASE_N) || is_contact(PHASE_C|GROUND))
02975 current_inj[2] = voltageC / fault_Z;
02976
02977 }
02978
02979
02980
02981
02982 #endif
02983
02984 BOTH_node_postsync_fxn(obj);
02985
02986 if (solver_method==SM_FBS)
02987 {
02988
02989 if (obj->parent!=NULL && (gl_object_isa(obj->parent,"node","powerflow")))
02990 {
02991
02992 node *pNode = OBJECTDATA(obj->parent,node);
02993 voltage[0] = pNode->voltage[0];
02994 voltage[1] = pNode->voltage[1];
02995 voltage[2] = pNode->voltage[2];
02996
02997
02998
02999 if (phases&PHASE_S)
03000 {
03001 voltage12 = voltage1 + voltage2;
03002 voltage1N = voltage1 - voltageN;
03003 voltage2N = voltage2 - voltageN;
03004 }
03005 else
03006 {
03007 voltageAB = voltageA - voltageB;
03008 voltageBC = voltageB - voltageC;
03009 voltageCA = voltageC - voltageA;
03010 }
03011 }
03012 }
03013
03014 #ifdef SUPPORT_OUTAGES
03015
03016 if (phases&PHASE_S)
03017 {
03018 double V1pu = voltage1.Mag()/nominal_voltage;
03019 double V2pu = voltage2.Mag()/nominal_voltage;
03020 if (V1pu<0.8 || V2pu<0.8)
03021 status=UNDERVOLT;
03022 else if (V1pu>1.2 || V2pu>1.2)
03023 status=OVERVOLT;
03024 else
03025 status=NOMINAL;
03026 }
03027 else
03028 {
03029 double VApu = voltageA.Mag()/nominal_voltage;
03030 double VBpu = voltageB.Mag()/nominal_voltage;
03031 double VCpu = voltageC.Mag()/nominal_voltage;
03032 if (VApu<0.8 || VBpu<0.8 || VCpu<0.8)
03033 status=UNDERVOLT;
03034 else if (VApu>1.2 || VBpu>1.2 || VCpu>1.2)
03035 status=OVERVOLT;
03036 else
03037 status=NOMINAL;
03038 }
03039 #endif
03040 if (solver_method==SM_FBS)
03041 {
03042
03043 double sync_V = (last_voltage[0]-voltage[0]).Mag() + (last_voltage[1]-voltage[1]).Mag() + (last_voltage[2]-voltage[2]).Mag();
03044
03045
03046 if (sync_V > maximum_voltage_error){
03047
03048
03049 RetValue=t0;
03050 }
03051 }
03052
03053
03054 return RetValue;
03055 }
03056
03057 int node::kmlinit(int (*stream)(const char*,...))
03058 {
03059 gld_global host("hostname");
03060 gld_global port("server_portnum");
03061 #define STYLE(X) stream("<Style id=\"" #X "_g\"><IconStyle><Icon><href>http://%s:%u/rt/" #X "_g.png</href></Icon></IconStyle></Style>\n", (const char*)host.get_string(), port.get_int32());\
03062 stream("<Style id=\"" #X "_r\"><IconStyle><Icon><href>http://%s:%u/rt/" #X "_r.png</href></Icon></IconStyle></Style>\n", (const char*)host.get_string(), port.get_int32());\
03063 stream("<Style id=\"" #X "_b\"><IconStyle><Icon><href>http://%s:%u/rt/" #X "_b.png</href></Icon></IconStyle></Style>\n", (const char*)host.get_string(), port.get_int32());\
03064 stream("<Style id=\"" #X "_k\"><IconStyle><Icon><href>http://%s:%u/rt/" #X "_k.png</href></Icon></IconStyle></Style>\n", (const char*)host.get_string(), port.get_int32());
03065 STYLE(node);
03066 STYLE(capacitor);
03067 STYLE(load);
03068 STYLE(triplex_meter);
03069
03070 return 0;
03071 }
03072 int node::kmldump(int (*stream)(const char*,...))
03073 {
03074 OBJECT *obj = OBJECTHDR(this);
03075 if (isnan(get_latitude()) || isnan(get_longitude()))
03076 return 0;
03077 stream("<Placemark>\n");
03078 stream("<name>%s</name>\n", get_name() );
03079 stream("<description>\n");
03080 stream("<![CDATA[\n");
03081 stream("<TABLE>\n");
03082
03083 char status_code[]="kbgr";
03084 int status = 2;
03085 if ( gl_object_isa(my(),"triplex_meter") )
03086 {
03087
03088 status = ((triplex_meter*)this)->kmldata(stream);
03089 }
03090 else
03091 {
03092 stream("<CAPTION>%s #%d</CAPTION>\n<TR><TH WIDTH=\"25%\" ALIGN=CENTER>Property<HR></TH>"
03093 "<TH WIDTH=\"25%\" COLSPAN=2 ALIGN=CENTER><NOBR>Phase A</NOBR><HR></TH>"
03094 "<TH WIDTH=\"25%\" COLSPAN=2 ALIGN=CENTER><NOBR>Phase B</NOBR><HR></TH>"
03095 "<TH WIDTH=\"25%\" COLSPAN=2 ALIGN=CENTER><NOBR>Phase C</NOBR><HR></TH></TR>\n", get_oclass()->get_name(), get_id());
03096
03097 int phase[3] = {has_phase(PHASE_A),has_phase(PHASE_B),has_phase(PHASE_C)};
03098 double basis[3] = {0,240,120};
03099
03100
03101 stream("<TR><TH ALIGN=LEFT>Voltage</TH>");
03102 for ( int i = 0 ; i<sizeof(phase)/sizeof(phase[0]) ; i++ )
03103 {
03104 if ( phase[i] )
03105 {
03106 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR></TD><TD ALIGN=LEFT>kV</TD>", voltage[i].Mag()/1000);
03107 if ( status>0 && voltage[i].Mag() <= 0.5*nominal_voltage ) status = 0;
03108 else if ( status==2 && voltage[i].Mag() < 0.95*nominal_voltage ) status = 1;
03109 else if ( status==2 && voltage[i].Mag() > 1.05*nominal_voltage ) status = 3;
03110 }
03111 else
03112 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\">—</TD><TD> </TD>");
03113 }
03114 stream("</TR>\n");
03115 stream("<TR><TH ALIGN=LEFT> </TH>");
03116 for ( int i = 0 ; i<sizeof(phase)/sizeof(phase[0]) ; i++ )
03117 {
03118 if ( phase[i] )
03119 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR></TD><TD ALIGN=LEFT>°</TD>", voltage[i].Arg()*180/3.1416 - basis[i]);
03120 else
03121 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\">—</TD><TD> </TD>");
03122 }
03123 stream("</TR>\n");
03124
03125 #define HANDLE_EX(X,Y)if ( gl_object_isa(my(),Y) ) ((X*)this)->kmldata(stream); else
03126 #define HANDLE(X) HANDLE_EX(X,#X)
03127 HANDLE(load)
03128 HANDLE(capacitor)
03129 {
03130
03131 stream("<TR><TH ALIGN=LEFT>Power</TH>");
03132 for ( int i = 0 ; i<sizeof(phase)/sizeof(phase[0]) ; i++ )
03133 {
03134 if ( phase[i] )
03135 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR></TD><TD ALIGN=LEFT>kW</TD>", power[i].Re()/1000);
03136 else
03137 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\">—</TD><TD> </TD>");
03138 }
03139 stream("</TR>\n");
03140 stream("<TR><TH ALIGN=LEFT> </TH>");
03141 for ( int i = 0 ; i<sizeof(phase)/sizeof(phase[0]) ; i++ )
03142 {
03143 if ( phase[i] )
03144 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR></TD><TD ALIGN=LEFT>kVAR</TD>", power[i].Im()/1000);
03145 else
03146 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\">—</TD><TD> </TD>");
03147 }
03148 stream("</TR>\n");
03149 }
03150 }
03151 stream("</TABLE>\n");
03152 stream("]]>\n");
03153 stream("</description>\n");
03154 stream("<styleUrl>#%s_%c</styleUrl>\n",obj->oclass->name, status_code[status]);
03155 stream("<Point>\n");
03156 stream("<coordinates>%f,%f</coordinates>\n",get_longitude(),get_latitude());
03157 stream("</Point>\n");
03158 stream("</Placemark>\n");
03159 return 0;
03160 }
03161
03162
03163
03164
03165 int node::notify(int update_mode, PROPERTY *prop, char *value)
03166 {
03167 complex diff_val;
03168
03169 if (solver_method == SM_NR)
03170 {
03171
03172 if (prev_voltage_value != NULL)
03173 {
03174
03175 if (strcmp(prop->name,"voltage_A")==0)
03176 {
03177 if (update_mode==NM_PREUPDATE)
03178 {
03179
03180 prev_voltage_value[0] = voltage[0];
03181 }
03182 else if (update_mode==NM_POSTUPDATE)
03183 {
03184
03185
03186 diff_val = voltage[0] - prev_voltage_value[0];
03187
03188 if (diff_val.Mag() >= maximum_voltage_error)
03189 {
03190 NR_retval = gl_globalclock;
03191 }
03192 }
03193 }
03194
03195
03196 if (strcmp(prop->name,"voltage_B")==0)
03197 {
03198 if (update_mode==NM_PREUPDATE)
03199 {
03200
03201 prev_voltage_value[1] = voltage[1];
03202 }
03203 else if (update_mode==NM_POSTUPDATE)
03204 {
03205
03206
03207 diff_val = voltage[1] - prev_voltage_value[1];
03208
03209 if (diff_val.Mag() >= maximum_voltage_error)
03210 {
03211 NR_retval = gl_globalclock;
03212 }
03213 }
03214 }
03215
03216
03217 if (strcmp(prop->name,"voltage_C")==0)
03218 {
03219 if (update_mode==NM_PREUPDATE)
03220 {
03221
03222 prev_voltage_value[2] = voltage[2];
03223 }
03224 else if (update_mode==NM_POSTUPDATE)
03225 {
03226
03227
03228 diff_val = voltage[2] - prev_voltage_value[2];
03229
03230 if (diff_val.Mag() >= maximum_voltage_error)
03231 {
03232 NR_retval = gl_globalclock;
03233 }
03234 }
03235 }
03236 }
03237 }
03238
03239
03240 return 1;
03241 }
03242
03244
03246
03254 EXPORT int create_node(OBJECT **obj, OBJECT *parent)
03255 {
03256 try
03257 {
03258 *obj = gl_create_object(node::oclass);
03259 if (*obj!=NULL)
03260 {
03261 node *my = OBJECTDATA(*obj,node);
03262 gl_set_parent(*obj,parent);
03263 return my->create();
03264 }
03265 else
03266 return 0;
03267 }
03268 CREATE_CATCHALL(node);
03269 }
03270
03271
03272 EXPORT TIMESTAMP commit_node(OBJECT *obj, TIMESTAMP t1, TIMESTAMP t2)
03273 {
03274 node *pNode = OBJECTDATA(obj,node);
03275 try {
03276
03277 if (solver_method==SM_FBS)
03278 {
03279 if (pNode->has_phase(PHASE_A)) {
03280
03281 }
03282 else
03283 pNode->voltage[0] = complex(0,0);
03284
03285 if (pNode->has_phase(PHASE_B)) {
03286
03287 }
03288 else
03289 pNode->voltage[1] = complex(0,0);
03290
03291 if (pNode->has_phase(PHASE_C)) {
03292
03293 }
03294 else
03295 pNode->voltage[2] = complex(0,0);
03296
03297 }
03298 return TS_NEVER;
03299 }
03300 catch (char *msg)
03301 {
03302 gl_error("%s (node:%d): %s", pNode->get_name(), pNode->get_id(), msg);
03303 return 0;
03304 }
03305
03306 }
03307
03314 EXPORT int init_node(OBJECT *obj)
03315 {
03316 try {
03317 node *my = OBJECTDATA(obj,node);
03318 return my->init(obj->parent);
03319 }
03320 INIT_CATCHALL(node);
03321 }
03322
03331 EXPORT TIMESTAMP sync_node(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
03332 {
03333 try {
03334 node *pObj = OBJECTDATA(obj,node);
03335 TIMESTAMP t1 = TS_NEVER;
03336 switch (pass) {
03337 case PC_PRETOPDOWN:
03338 return pObj->presync(t0);
03339 case PC_BOTTOMUP:
03340 return pObj->sync(t0);
03341 case PC_POSTTOPDOWN:
03342 t1 = pObj->postsync(t0);
03343 obj->clock = t0;
03344 return t1;
03345 default:
03346 throw "invalid pass request";
03347 }
03348 }
03349 SYNC_CATCHALL(node);
03350 }
03351
03358 OBJECT *node::NR_master_swing_search(char *node_type_value,bool main_swing)
03359 {
03360 OBJECT *return_val = NULL;
03361 OBJECT *temp_obj = NULL;
03362 node *list_node;
03363 FINDLIST *bus_list = gl_find_objects(FL_NEW,FT_CLASS,SAME,node_type_value,FT_END);
03364
03365
03366 while(temp_obj=gl_find_next(bus_list,temp_obj))
03367 {
03368 list_node = OBJECTDATA(temp_obj,node);
03369
03370
03371 if (main_swing == true)
03372 {
03373 if (list_node->bustype==SWING)
03374 {
03375 return_val=temp_obj;
03376 break;
03377 }
03378 }
03379 else
03380 {
03381 if (list_node->bustype==SWING_PQ)
03382 {
03383 return_val=temp_obj;
03384 break;
03385 }
03386 }
03387 }
03388
03389
03390 gl_free(bus_list);
03391
03392
03393 return return_val;
03394 }
03395
03402 int node::NR_populate(void)
03403 {
03404
03405 OBJECT *me = OBJECTHDR(this);
03406 node *temp_par_node = NULL;
03407
03408
03409 if ( NR_swing_bus!=me ) LOCK_OBJECT(NR_swing_bus);
03410
03411 NR_node_reference = NR_curr_bus;
03412 NR_curr_bus++;
03413 if ( NR_swing_bus!=me ) UNLOCK_OBJECT(NR_swing_bus);
03414
03415
03416 if (NR_node_reference == -1)
03417 {
03418 GL_THROW("NR: bus:%s failed to grab a unique bus index value!",me->name);
03419
03420
03421
03422
03423
03424 }
03425
03426
03427 NR_busdata[NR_node_reference].type = (int)bustype;
03428
03429
03430 NR_busdata[NR_node_reference].island_number = 0;
03431
03432
03433 if (NR_busdata[NR_node_reference].type==1)
03434 {
03435 GL_THROW("NR: bus:%s is a PV bus - these are not yet supported.",me->name);
03436
03437
03438
03439 }
03440
03441
03442 if ((bustype == SWING) || (bustype == SWING_PQ))
03443 {
03444 NR_busdata[NR_node_reference].swing_functions_enabled = true;
03445 }
03446 else
03447 {
03448 NR_busdata[NR_node_reference].swing_functions_enabled = false;
03449 }
03450
03451
03452 NR_busdata[NR_node_reference].phases = 128*has_phase(PHASE_S) + 8*has_phase(PHASE_D) + 4*has_phase(PHASE_A) + 2*has_phase(PHASE_B) + has_phase(PHASE_C);
03453
03454
03455 NR_busdata[NR_node_reference].name = me->name;
03456
03457
03458 NR_busdata[NR_node_reference].obj = me;
03459
03460
03461 NR_busdata[NR_node_reference].max_volt_error = maximum_voltage_error;
03462
03463
03464 NR_busdata[NR_node_reference].busflag = &busflags;
03465
03466
03467 NR_busdata[NR_node_reference].V = &voltage[0];
03468
03469
03470 NR_busdata[NR_node_reference].S = &power[0];
03471
03472
03473 NR_busdata[NR_node_reference].Y = &shunt[0];
03474
03475
03476 NR_busdata[NR_node_reference].I = ¤t[0];
03477
03478
03479 NR_busdata[NR_node_reference].prerot_I = &pre_rotated_current[0];
03480
03481
03482 NR_busdata[NR_node_reference].S_dy = &power_dy[0];
03483
03484
03485 NR_busdata[NR_node_reference].Y_dy = &shunt_dy[0];
03486
03487
03488 NR_busdata[NR_node_reference].I_dy = ¤t_dy[0];
03489
03490
03491 NR_busdata[NR_node_reference].Link_Table = (int *)gl_malloc(NR_connected_links[0]*sizeof(int));
03492
03493 if (NR_busdata[NR_node_reference].Link_Table == NULL)
03494 {
03495 GL_THROW("NR: Failed to allocate link table for node:%d",me->id);
03496
03497
03498
03499
03500
03501 }
03502
03503
03504 NR_busdata[NR_node_reference].Link_Table_Size = NR_connected_links[0];
03505
03506
03507 if (has_phase(PHASE_S))
03508 {
03509 if (house_present)
03510 {
03511 NR_busdata[NR_node_reference].house_var = &nom_res_curr[0];
03512 NR_busdata[NR_node_reference].phases |= 0x40;
03513 }
03514
03515 NR_busdata[NR_node_reference].extra_var = ¤t12;
03516 }
03517 else if (SubNode==DIFF_PARENT)
03518 {
03519 NR_busdata[NR_node_reference].extra_var = Extra_Data;
03520 NR_busdata[NR_node_reference].phases |= 0x10;
03521 }
03522
03523
03524 NR_busdata[NR_node_reference].volt_base = nominal_voltage;
03525 NR_busdata[NR_node_reference].mva_base = -1.0;
03526
03527
03528 NR_busdata[NR_node_reference].Matrix_Loc = -1;
03529
03530
03531 NR_busdata[NR_node_reference].origphases = NR_busdata[NR_node_reference].phases;
03532
03533
03534 prev_phases = NR_busdata[NR_node_reference].phases;
03535
03536
03537 NR_busdata[NR_node_reference].dynamics_enabled = &deltamode_inclusive;
03538
03539
03540 if ((deltamode_inclusive==true) && (enable_inrush_calculations==true))
03541 {
03542
03543 NR_busdata[NR_node_reference].BusHistTerm = BusHistTerm;
03544
03545
03546
03547 NR_busdata[NR_node_reference].full_Y_load = full_Y_load;
03548 }
03549 else
03550 {
03551
03552 NR_busdata[NR_node_reference].BusHistTerm = NULL;
03553 NR_busdata[NR_node_reference].full_Y_load = NULL;
03554 }
03555
03556
03557 NR_busdata[NR_node_reference].BusSatTerm = NULL;
03558
03559
03560 NR_busdata[NR_node_reference].ExtraCurrentInjFunc = NULL;
03561 NR_busdata[NR_node_reference].ExtraCurrentInjFuncObject = NULL;
03562
03563
03564 if ((deltamode_inclusive==true) && ((dynamic_norton==true) || (dynamic_generator==true)))
03565 {
03566
03567 if ((SubNode!=CHILD) && (SubNode!=DIFF_CHILD))
03568 {
03569
03570 if (dynamic_norton==true)
03571 {
03572
03573 if (full_Y == NULL)
03574 {
03575
03576 full_Y = (complex *)gl_malloc(9*sizeof(complex));
03577
03578
03579 if (full_Y==NULL)
03580 {
03581 GL_THROW("Node:%s failed to allocate space for the a deltamode variable",me->name);
03582
03583
03584
03585
03586
03587 }
03588
03589
03590 if ((full_Y_matrix.get_rows() == 3) && (full_Y_matrix.get_cols() == 3))
03591 {
03592 full_Y[0] = full_Y_matrix.get_at(0,0);
03593 full_Y[1] = full_Y_matrix.get_at(0,1);
03594 full_Y[2] = full_Y_matrix.get_at(0,2);
03595
03596 full_Y[3] = full_Y_matrix.get_at(1,0);
03597 full_Y[4] = full_Y_matrix.get_at(1,1);
03598 full_Y[5] = full_Y_matrix.get_at(1,2);
03599
03600 full_Y[6] = full_Y_matrix.get_at(2,0);
03601 full_Y[7] = full_Y_matrix.get_at(2,1);
03602 full_Y[8] = full_Y_matrix.get_at(2,2);
03603 }
03604 else
03605 {
03606
03607 full_Y[0] = full_Y[1] = full_Y[2] = complex(0.0,0.0);
03608 full_Y[3] = full_Y[4] = full_Y[5] = complex(0.0,0.0);
03609 full_Y[6] = full_Y[7] = full_Y[8] = complex(0.0,0.0);
03610 }
03611
03612
03613 full_Y_all = (complex *)gl_malloc(9*sizeof(complex));
03614
03615
03616 if (full_Y_all==NULL)
03617 {
03618 GL_THROW("Node:%s failed to allocate space for the a deltamode variable",me->name);
03619
03620 }
03621
03622
03623 if ((full_Y_all_matrix.get_rows() == 3) && (full_Y_all_matrix.get_cols() == 3))
03624 {
03625 full_Y_all[0] = full_Y_all_matrix.get_at(0,0);
03626 full_Y_all[1] = full_Y_all_matrix.get_at(0,1);
03627 full_Y_all[2] = full_Y_all_matrix.get_at(0,2);
03628
03629 full_Y_all[3] = full_Y_all_matrix.get_at(1,0);
03630 full_Y_all[4] = full_Y_all_matrix.get_at(1,1);
03631 full_Y_all[5] = full_Y_all_matrix.get_at(1,2);
03632
03633 full_Y_all[6] = full_Y_all_matrix.get_at(2,0);
03634 full_Y_all[7] = full_Y_all_matrix.get_at(2,1);
03635 full_Y_all[8] = full_Y_all_matrix.get_at(2,2);
03636 }
03637 else
03638 {
03639
03640 full_Y_all_matrix.grow_to(3,3);
03641
03642
03643 full_Y_all[0] = full_Y_all[1] = full_Y_all[2] = complex(0.0,0.0);
03644 full_Y_all[3] = full_Y_all[4] = full_Y_all[5] = complex(0.0,0.0);
03645 full_Y_all[6] = full_Y_all[7] = full_Y_all[8] = complex(0.0,0.0);
03646 }
03647 }
03648 else
03649 {
03650 full_Y_all = NULL;
03651 }
03652 }
03653 else
03654 {
03655
03656 full_Y = NULL;
03657
03658
03659 full_Y_all = NULL;
03660 }
03661 }
03662
03663
03664 NR_busdata[NR_node_reference].full_Y = full_Y;
03665 NR_busdata[NR_node_reference].full_Y_all = full_Y_all;
03666 NR_busdata[NR_node_reference].DynCurrent = &deltamode_dynamic_current[0];
03667 NR_busdata[NR_node_reference].PGenTotal = &deltamode_PGenTotal;
03668 }
03669 else
03670 {
03671 NR_busdata[NR_node_reference].full_Y = NULL;
03672 NR_busdata[NR_node_reference].full_Y_all = NULL;
03673 NR_busdata[NR_node_reference].DynCurrent = NULL;
03674 NR_busdata[NR_node_reference].PGenTotal = NULL;
03675 }
03676
03677 return 0;
03678 }
03679
03680
03681
03682 int node::NR_current_update(bool parentcall)
03683 {
03684 unsigned int table_index;
03685 link_object *temp_link;
03686 int temp_result, loop_index;
03687 OBJECT *obj = OBJECTHDR(this);
03688 complex temp_current_inj[3];
03689 complex temp_current_val[3];
03690 complex adjusted_current_val[3];
03691 complex delta_shunt[3];
03692 complex delta_current[3];
03693 complex assumed_nominal_voltage[6];
03694 double nominal_voltage_dval;
03695 complex house_pres_current[3];
03696
03697
03698 if (current_accumulated==false)
03699 {
03700 if (SubNode==CHILD)
03701 {
03702 node *ParToLoad = OBJECTDATA(SubNodeParent,node);
03703
03704 if (!parentcall)
03705 {
03706
03707 LOCK_OBJECT(SubNodeParent);
03708 }
03709
03710
03711 ParToLoad->power[0]-=last_child_power[0][0];
03712 ParToLoad->power[1]-=last_child_power[0][1];
03713 ParToLoad->power[2]-=last_child_power[0][2];
03714
03715 ParToLoad->shunt[0]-=last_child_power[1][0];
03716 ParToLoad->shunt[1]-=last_child_power[1][1];
03717 ParToLoad->shunt[2]-=last_child_power[1][2];
03718
03719 ParToLoad->current[0]-=last_child_power[2][0];
03720 ParToLoad->current[1]-=last_child_power[2][1];
03721 ParToLoad->current[2]-=last_child_power[2][2];
03722
03723 if (has_phase(PHASE_S))
03724 ParToLoad->current12-=last_child_current12;
03725
03726
03727 ParToLoad->pre_rotated_current[0] -= last_child_power[3][0];
03728 ParToLoad->pre_rotated_current[1] -= last_child_power[3][1];
03729 ParToLoad->pre_rotated_current[2] -= last_child_power[3][2];
03730
03731
03732 if (deltamode_inclusive == true)
03733 {
03734
03735
03736 deltamode_dynamic_current[0] = ParToLoad->deltamode_dynamic_current[0];
03737 deltamode_dynamic_current[1] = ParToLoad->deltamode_dynamic_current[1];
03738 deltamode_dynamic_current[2] = ParToLoad->deltamode_dynamic_current[2];
03739 }
03740
03741
03742 for (loop_index=0; loop_index<6; loop_index++)
03743 {
03744 ParToLoad->power_dy[loop_index] -= last_child_power_dy[loop_index][0];
03745 ParToLoad->shunt_dy[loop_index] -= last_child_power_dy[loop_index][1];
03746 ParToLoad->current_dy[loop_index] -= last_child_power_dy[loop_index][2];
03747 }
03748
03749 if (!parentcall)
03750 {
03751
03752 UNLOCK_OBJECT(SubNodeParent);
03753 }
03754
03755
03756
03757 last_child_power[0][0] = last_child_power[0][1] = last_child_power[0][2] = 0.0;
03758
03759
03760 last_child_power[1][0] = last_child_power[1][1] = last_child_power[1][2] = 0.0;
03761
03762
03763 last_child_power[2][0] = last_child_power[2][1] = last_child_power[2][2] = 0.0;
03764
03765
03766 for (loop_index=0; loop_index<6; loop_index++)
03767 {
03768 last_child_power_dy[loop_index][0] = complex(0.0);
03769 last_child_power_dy[loop_index][1] = complex(0.0);
03770 last_child_power_dy[loop_index][2] = complex(0.0);
03771 }
03772
03773
03774 if (has_phase(PHASE_S))
03775 last_child_current12 = 0.0;
03776
03777
03778 last_child_power[3][0] = last_child_power[3][1] = last_child_power[3][2] = complex(0.0,0.0);
03779 }
03780 else if (SubNode==DIFF_CHILD)
03781 {
03782 node *ParToLoad = OBJECTDATA(SubNodeParent,node);
03783
03784 if (!parentcall)
03785 {
03786
03787 LOCK_OBJECT(SubNodeParent);
03788 }
03789
03790
03791 for (loop_index=0; loop_index<6; loop_index++)
03792 {
03793 ParToLoad->power_dy[loop_index] -= last_child_power_dy[loop_index][0];
03794 ParToLoad->shunt_dy[loop_index] -= last_child_power_dy[loop_index][1];
03795 ParToLoad->current_dy[loop_index] -= last_child_power_dy[loop_index][2];
03796 }
03797
03798
03799 ParToLoad->pre_rotated_current[0] -= last_child_power[3][0];
03800 ParToLoad->pre_rotated_current[1] -= last_child_power[3][1];
03801 ParToLoad->pre_rotated_current[2] -= last_child_power[3][2];
03802
03803 if (!parentcall)
03804 {
03805
03806 UNLOCK_OBJECT(SubNodeParent);
03807 }
03808
03809
03810 for (loop_index=0; loop_index<6; loop_index++)
03811 {
03812 last_child_power_dy[loop_index][0] = complex(0.0);
03813 last_child_power_dy[loop_index][1] = complex(0.0);
03814 last_child_power_dy[loop_index][2] = complex(0.0);
03815 }
03816
03817
03818 last_child_power[3][0] = last_child_power[3][1] = last_child_power[3][2] = complex(0.0,0.0);
03819 }
03820
03821 if ((SubNode==CHILD) || (SubNode==DIFF_CHILD))
03822 {
03823 node *ParStealLoad = OBJECTDATA(SubNodeParent,node);
03824
03825
03826
03827 voltage[0] = ParStealLoad->voltage[0];
03828 voltage[1] = ParStealLoad->voltage[1];
03829 voltage[2] = ParStealLoad->voltage[2];
03830
03831
03832 if (has_phase(PHASE_S))
03833 {
03834
03835 voltaged[0] = voltage[0] + voltage[1];
03836 voltaged[1] = voltage[1] - voltage[2];
03837 voltaged[2] = voltage[0] - voltage[2];
03838 }
03839 else
03840 {
03841
03842 voltaged[0] = voltage[0] - voltage[1];
03843 voltaged[1] = voltage[1] - voltage[2];
03844 voltaged[2] = voltage[2] - voltage[0];
03845 }
03846 }
03847
03848
03849 if (NR_number_child_nodes[0]>0)
03850 {
03851 for (table_index=0; table_index<NR_number_child_nodes[0]; table_index++)
03852 {
03853
03854 temp_result = NR_child_nodes[table_index]->NR_current_update(true);
03855
03856
03857 if (temp_result != 1)
03858 {
03859 GL_THROW("Attempt to update current on child of node:%s failed!",obj->name);
03860
03861
03862
03863
03864 }
03865 }
03866 }
03867
03868
03869 temp_current_inj[0] = temp_current_inj[1] = temp_current_inj[2] = complex(0.0,0.0);
03870
03871
03872 if (deltamode_inclusive == true)
03873 {
03874
03875 if (has_phase(PHASE_S))
03876 {
03877 assumed_nominal_voltage[0].SetPolar(nominal_voltage,0.0);
03878 assumed_nominal_voltage[1].SetPolar(nominal_voltage,0.0);
03879 assumed_nominal_voltage[2] = assumed_nominal_voltage[0] + assumed_nominal_voltage[1];
03880 assumed_nominal_voltage[3] = complex(0.0,0.0);
03881 assumed_nominal_voltage[4] = complex(0.0,0.0);
03882 assumed_nominal_voltage[5] = complex(0.0,0.0);
03883
03884
03885 nominal_voltage_dval = 2.0 * nominal_voltage;
03886 }
03887 else
03888 {
03889 assumed_nominal_voltage[0].SetPolar(nominal_voltage,0.0);
03890 assumed_nominal_voltage[1].SetPolar(nominal_voltage,(-2.0*PI/3.0));
03891 assumed_nominal_voltage[2].SetPolar(nominal_voltage,(2.0*PI/3.0));
03892 assumed_nominal_voltage[3] = assumed_nominal_voltage[0] - assumed_nominal_voltage[1];
03893 assumed_nominal_voltage[4] = assumed_nominal_voltage[1] - assumed_nominal_voltage[2];
03894 assumed_nominal_voltage[5] = assumed_nominal_voltage[2] - assumed_nominal_voltage[0];
03895
03896
03897 nominal_voltage_dval = assumed_nominal_voltage[3].Mag();
03898 }
03899 }
03900
03901
03902 if (has_phase(PHASE_D))
03903 {
03904
03905 delta_shunt[0] = voltaged[0]*shunt[0];
03906 delta_shunt[1] = voltaged[1]*shunt[1];
03907 delta_shunt[2] = voltaged[2]*shunt[2];
03908
03909
03910 delta_current[0]= (voltaged[0]==0) ? complex(0,0) : ~(power[0]/voltaged[0]);
03911 delta_current[1]= (voltaged[1]==0) ? complex(0,0) : ~(power[1]/voltaged[1]);
03912 delta_current[2]= (voltaged[2]==0) ? complex(0,0) : ~(power[2]/voltaged[2]);
03913
03914
03915 if (deltamode_inclusive == true)
03916 {
03917
03918 for (loop_index=0; loop_index<3; loop_index++)
03919 {
03920
03921 if (voltaged[loop_index] != 0.0)
03922 {
03923 adjusted_current_val[loop_index] = ~((assumed_nominal_voltage[loop_index+3]*~current[loop_index]*voltaged[loop_index].Mag())/(voltaged[loop_index]*nominal_voltage_dval));
03924 }
03925 else
03926 {
03927 adjusted_current_val[loop_index] = complex(0.0,0.0);
03928 }
03929 }
03930 }
03931 else
03932 {
03933
03934 adjusted_current_val[0] = current[0];
03935 adjusted_current_val[1] = current[1];
03936 adjusted_current_val[2] = current[2];
03937 }
03938
03939
03940 temp_current_val[0] = delta_shunt[0]-delta_shunt[2] + delta_current[0]-delta_current[2] + adjusted_current_val[0]-adjusted_current_val[2];
03941 temp_current_val[1] = delta_shunt[1]-delta_shunt[0] + delta_current[1]-delta_current[0] + adjusted_current_val[1]-adjusted_current_val[0];
03942 temp_current_val[2] = delta_shunt[2]-delta_shunt[1] + delta_current[2]-delta_current[1] + adjusted_current_val[2]-adjusted_current_val[1];
03943
03944 temp_current_inj[0] = temp_current_val[0];
03945 temp_current_inj[1] = temp_current_val[1];
03946 temp_current_inj[2] = temp_current_val[2];
03947 }
03948 else if (has_phase(PHASE_S))
03949 {
03950 complex vdel;
03951 complex temp_current[3];
03952 complex temp_store[3];
03953 complex temp_val[3];
03954
03955
03956 vdel=voltage[0] + voltage[1];
03957
03958
03959
03960 if (deltamode_inclusive == true)
03961 {
03962
03963
03964 if (voltage[0] != 0.0)
03965 {
03966 adjusted_current_val[0] = ~((assumed_nominal_voltage[0]*~current[0]*voltage[0].Mag())/(voltage[0]*nominal_voltage));
03967 }
03968 else
03969 {
03970 adjusted_current_val[0] = complex(0.0,0.0);
03971 }
03972
03973
03974 if (voltage[1] != 0.0)
03975 {
03976 adjusted_current_val[1] = ~((assumed_nominal_voltage[1]*~current[1]*voltage[1].Mag())/(voltage[1]*nominal_voltage));
03977 }
03978 else
03979 {
03980 adjusted_current_val[1] = complex(0.0,0.0);
03981 }
03982
03983
03984 if (vdel != 0.0)
03985 {
03986 adjusted_current_val[2] = ~((assumed_nominal_voltage[2]*~current12*vdel.Mag())/(vdel*nominal_voltage_dval));
03987 }
03988 else
03989 {
03990 adjusted_current_val[2] = complex(0.0,0.0);
03991 }
03992 }
03993 else
03994 {
03995
03996 adjusted_current_val[0] = current[0];
03997 adjusted_current_val[1] = current[1];
03998 adjusted_current_val[2] = current12;
03999 }
04000
04001
04002 temp_current[0] = adjusted_current_val[0];
04003 temp_current[1] = adjusted_current_val[1];
04004 temp_current[2] = adjusted_current_val[2];
04005
04006
04007 if (deltamode_inclusive == true)
04008 {
04009 temp_current[0] += pre_rotated_current[0];
04010 temp_current[1] += pre_rotated_current[1];
04011 temp_current[2] += pre_rotated_current[2];
04012 }
04013
04014
04015 temp_current[0] += voltage[0] == 0.0 ? 0.0 : ~(power[0]/voltage[0]);
04016 temp_current[1] += voltage[1] == 0.0 ? 0.0 : ~(power[1]/voltage[1]);
04017 temp_current[2] += vdel == 0.0 ? 0.0 : ~(power[2]/vdel);
04018
04019 if (house_present)
04020 {
04021
04022 temp_store[0].SetPolar(1.0,voltage[0].Arg());
04023 temp_store[1].SetPolar(1.0,voltage[1].Arg());
04024 temp_store[2].SetPolar(1.0,vdel.Arg());
04025
04026
04027 house_pres_current[0] = nom_res_curr[0]/(~temp_store[0]);
04028 house_pres_current[1] = nom_res_curr[1]/(~temp_store[1]);
04029 house_pres_current[2] = nom_res_curr[2]/(~temp_store[2]);
04030
04031
04032 temp_current[0] += house_pres_current[0];
04033 temp_current[1] += house_pres_current[1];
04034 temp_current[2] += house_pres_current[2];
04035 }
04036
04037
04038 temp_current[0] += shunt[0]*voltage[0];
04039 temp_current[1] += shunt[1]*voltage[1];
04040 temp_current[2] += shunt[2]*vdel;
04041
04042
04043 temp_current_val[0] = temp_current[0] + temp_current[2];
04044 temp_current_val[1] = -temp_current[1] - temp_current[2];
04045
04046 temp_current_inj[0] = temp_current_val[0];
04047 temp_current_inj[1] = temp_current_val[1];
04048
04049
04050 if ((Triplex_Data != NULL) && ((Triplex_Data[0] != 0.0) || (Triplex_Data[1] != 0.0)))
04051 {
04052
04053 temp_current_inj[2] = Triplex_Data[0]*temp_current_inj[0] + Triplex_Data[1]*temp_current_inj[1];
04054 }
04055 else
04056 {
04057
04058 temp_current_inj[2] = ((voltage1.IsZero() || (power1.IsZero() && shunt1.IsZero())) ||
04059 (voltage2.IsZero() || (power2.IsZero() && shunt2.IsZero())))
04060 ? currentN : -((temp_current_inj[0]-temp_current[2])+(temp_current_inj[1]-temp_current[2]));
04061 }
04062 }
04063 else
04064 {
04065
04066 if (deltamode_inclusive == true)
04067 {
04068
04069 for (loop_index=0; loop_index<3; loop_index++)
04070 {
04071
04072 if (voltage[loop_index] != 0.0)
04073 {
04074 adjusted_current_val[loop_index] = ~((assumed_nominal_voltage[loop_index]*~current[loop_index]*voltage[loop_index].Mag())/(voltage[loop_index]*nominal_voltage));
04075 }
04076 else
04077 {
04078 adjusted_current_val[loop_index] = complex(0.0,0.0);
04079 }
04080 }
04081 }
04082 else
04083 {
04084
04085 adjusted_current_val[0] = current[0];
04086 adjusted_current_val[1] = current[1];
04087 adjusted_current_val[2] = current[2];
04088 }
04089
04090
04091
04092
04093 temp_current_val[0] = ((voltage[0]==0) ? complex(0,0) : ~(power[0]/voltage[0])) + voltage[0]*shunt[0] + adjusted_current_val[0] + pre_rotated_current[0];
04094 temp_current_val[1] = ((voltage[1]==0) ? complex(0,0) : ~(power[1]/voltage[1])) + voltage[1]*shunt[1] + adjusted_current_val[1] + pre_rotated_current[1];
04095 temp_current_val[2] = ((voltage[2]==0) ? complex(0,0) : ~(power[2]/voltage[2])) + voltage[2]*shunt[2] + adjusted_current_val[2] + pre_rotated_current[2];
04096
04097 temp_current_inj[0] = temp_current_val[0];
04098 temp_current_inj[1] = temp_current_val[1];
04099 temp_current_inj[2] = temp_current_val[2];
04100 }
04101
04102
04103 if (!(has_phase(PHASE_S)))
04104 {
04105
04106
04107
04108 delta_shunt[0] = voltaged[0]*shunt_dy[0];
04109 delta_shunt[1] = voltaged[1]*shunt_dy[1];
04110 delta_shunt[2] = voltaged[2]*shunt_dy[2];
04111
04112
04113 delta_current[0]= (voltaged[0]==0) ? complex(0,0) : ~(power_dy[0]/voltaged[0]);
04114 delta_current[1]= (voltaged[1]==0) ? complex(0,0) : ~(power_dy[1]/voltaged[1]);
04115 delta_current[2]= (voltaged[2]==0) ? complex(0,0) : ~(power_dy[2]/voltaged[2]);
04116
04117
04118 if (deltamode_inclusive == true)
04119 {
04120
04121 for (loop_index=0; loop_index<3; loop_index++)
04122 {
04123
04124 if (voltaged[loop_index] != 0.0)
04125 {
04126 adjusted_current_val[loop_index] = ~((assumed_nominal_voltage[loop_index+3]*~current_dy[loop_index]*voltaged[loop_index].Mag())/(voltaged[loop_index]*nominal_voltage_dval));
04127 }
04128 else
04129 {
04130 adjusted_current_val[loop_index] = complex(0.0,0.0);
04131 }
04132 }
04133 }
04134 else
04135 {
04136
04137 adjusted_current_val[0] = current_dy[0];
04138 adjusted_current_val[1] = current_dy[1];
04139 adjusted_current_val[2] = current_dy[2];
04140 }
04141
04142
04143
04144 temp_current_inj[0] += delta_shunt[0]-delta_shunt[2] + delta_current[0]-delta_current[2] + adjusted_current_val[0]-adjusted_current_val[2];
04145 temp_current_inj[1] += delta_shunt[1]-delta_shunt[0] + delta_current[1]-delta_current[0] + adjusted_current_val[1]-adjusted_current_val[0];
04146 temp_current_inj[2] += delta_shunt[2]-delta_shunt[1] + delta_current[2]-delta_current[1] + adjusted_current_val[2]-adjusted_current_val[1];
04147
04148
04149 if (deltamode_inclusive == true)
04150 {
04151
04152 for (loop_index=0; loop_index<3; loop_index++)
04153 {
04154 if (voltage[loop_index] != 0.0)
04155 {
04156 adjusted_current_val[loop_index] = ~((assumed_nominal_voltage[loop_index]*~current_dy[loop_index+3]*voltage[loop_index].Mag())/(voltage[loop_index]*nominal_voltage));
04157 }
04158 else
04159 {
04160 adjusted_current_val[loop_index] = complex(0.0,0.0);
04161 }
04162 }
04163 }
04164 else
04165 {
04166
04167 adjusted_current_val[0] = current_dy[3];
04168 adjusted_current_val[1] = current_dy[4];
04169 adjusted_current_val[2] = current_dy[5];
04170 }
04171
04172
04173 temp_current_inj[0] += ((voltage[0]==0) ? complex(0,0) : ~(power_dy[3]/voltage[0])) + voltage[0]*shunt_dy[3] + adjusted_current_val[0];
04174 temp_current_inj[1] += ((voltage[1]==0) ? complex(0,0) : ~(power_dy[4]/voltage[1])) + voltage[1]*shunt_dy[4] + adjusted_current_val[1];
04175 temp_current_inj[2] += ((voltage[2]==0) ? complex(0,0) : ~(power_dy[5]/voltage[2])) + voltage[2]*shunt_dy[5] + adjusted_current_val[2];
04176 }
04177
04178
04179 if ((SubNode==CHILD) || (SubNode==DIFF_CHILD))
04180 {
04181 node *ParLoadObj=OBJECTDATA(SubNodeParent,node);
04182
04183 if (ParLoadObj->current_accumulated==false)
04184 {
04185 ParLoadObj->current_inj[0] += temp_current_inj[0];
04186 ParLoadObj->current_inj[1] += temp_current_inj[1];
04187 ParLoadObj->current_inj[2] += temp_current_inj[2];
04188
04189
04190 if (house_present)
04191 {
04192
04193 ParLoadObj->current_inj[0] -= house_pres_current[0] + house_pres_current[2];
04194 ParLoadObj->current_inj[1] -= -house_pres_current[1] - house_pres_current[2];
04195 }
04196 }
04197
04198
04199 current_inj[0] += temp_current_inj[0];
04200 current_inj[1] += temp_current_inj[1];
04201 current_inj[2] += temp_current_inj[2];
04202 }
04203 else
04204 {
04205 current_inj[0] += temp_current_inj[0];
04206 current_inj[1] += temp_current_inj[1];
04207 current_inj[2] += temp_current_inj[2];
04208 }
04209
04210
04211
04212
04213 if ((deltamode_inclusive == true) && (dynamic_norton == true))
04214 {
04215
04216 current_inj[0] -= deltamode_dynamic_current[0];
04217 current_inj[1] -= deltamode_dynamic_current[1];
04218 current_inj[2] -= deltamode_dynamic_current[2];
04219
04220
04221 if (full_Y != NULL)
04222 {
04223
04224 current_inj[0] += full_Y[0]*voltage[0] + full_Y[1]*voltage[1] + full_Y[2]*voltage[2];
04225 current_inj[1] += full_Y[3]*voltage[0] + full_Y[4]*voltage[1] + full_Y[5]*voltage[2];
04226 current_inj[2] += full_Y[6]*voltage[0] + full_Y[7]*voltage[1] + full_Y[8]*voltage[2];
04227 }
04228 }
04229
04230
04231 if ((SubNode!=CHILD) && (SubNode!=DIFF_CHILD))
04232 {
04233 for (table_index=0; table_index<NR_busdata[NR_node_reference].Link_Table_Size; table_index++)
04234 {
04235
04236 temp_link = OBJECTDATA(NR_branchdata[NR_busdata[NR_node_reference].Link_Table[table_index]].obj,link_object);
04237
04238
04239 if (temp_link == NULL)
04240 {
04241 GL_THROW("Attemped to update current for object:%s, which is not a link!",NR_branchdata[NR_busdata[NR_node_reference].Link_Table[table_index]].name);
04242
04243
04244
04245
04246
04247 }
04248
04249
04250 WRITELOCK_OBJECT(NR_branchdata[NR_busdata[NR_node_reference].Link_Table[table_index]].obj);
04251
04252
04253 temp_result = temp_link->CurrentCalculation(NR_node_reference,false);
04254
04255
04256 WRITEUNLOCK_OBJECT(NR_branchdata[NR_busdata[NR_node_reference].Link_Table[table_index]].obj);
04257
04258
04259 if (temp_result != 1)
04260 {
04261 GL_THROW("Attempt to update current on link:%s failed!",NR_branchdata[NR_busdata[NR_node_reference].Link_Table[table_index]].name);
04262
04263
04264
04265
04266 }
04267 }
04268 }
04269
04270
04271 current_accumulated = true;
04272 }
04273
04274 return 1;
04275 }
04276
04278
04280
04281 SIMULATIONMODE node::inter_deltaupdate_node(unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val,bool interupdate_pos)
04282 {
04283
04284 double deltat, deltatimedbl;
04285 OBJECT *hdr = OBJECTHDR(this);
04286 STATUS return_status_val;
04287
04289
04290
04291
04292 deltat = (double)dt/(double)DT_SECOND;
04293
04294
04295 if ((iteration_count_val==0) && (interupdate_pos == false))
04296 {
04297
04298 deltatimedbl = (double)delta_time/(double)DT_SECOND;
04299
04300
04301 prev_time_dbl = (double)gl_globalclock + deltatimedbl;
04302
04303
04304 if (fmeas_type != FM_NONE)
04305 {
04306
04307 memcpy(&prev_freq_state,&curr_freq_state,sizeof(FREQM_STATES));
04308 }
04309 }
04310
04311
04312 if ((delta_time==0) && (iteration_count_val==0) && (interupdate_pos == false) && (fmeas_type != FM_NONE))
04313 {
04314
04315 init_freq_dynamics();
04316 }
04317
04318
04319 if ((GFA_enable == true) && (iteration_count_val == 0) && (interupdate_pos == false))
04320 {
04321
04322 GFA_Update_time = perform_GFA_checks(deltat);
04323 }
04324
04325
04326 if (interupdate_pos == false)
04327 {
04328
04329 NR_node_presync_fxn(0);
04330
04331
04332 NR_node_sync_fxn(hdr);
04333
04334 return SM_DELTA;
04335
04336 }
04337 else
04338 {
04339
04340 BOTH_node_postsync_fxn(hdr);
04341
04342
04343 if (fmeas_type != FM_NONE)
04344 {
04345 return_status_val = calc_freq_dynamics(deltat);
04346
04347
04348 if (return_status_val == FAILED)
04349 {
04350 return SM_ERROR;
04351 }
04352 }
04353
04354
04355
04356 if (GFA_enable == true)
04357 {
04358
04359 if ((GFA_Update_time > 0.0) && (GFA_Update_time < 1.7))
04360 {
04361
04362 return SM_DELTA;
04363 }
04364 else
04365 {
04366 return SM_EVENT;
04367 }
04368 }
04369 else
04370 {
04371 return SM_EVENT;
04372 }
04373
04374
04375
04376
04377
04379
04380
04381
04382
04383
04384
04385
04386
04387
04388
04389
04390
04391
04392
04393
04394
04395
04396
04397
04398
04399
04400
04401 }
04402 }
04403
04404
04405
04406 STATUS node::calc_freq_dynamics(double deltat)
04407 {
04408 unsigned char phase_conf, phase_mask;
04409 unsigned int indexval;
04410 double dfmeasdt, errorval, deltaom, dxdt, fbus, adiffval;
04411 STATUS return_status;
04412 bool is_triplex_node;
04413
04414
04415 return_status = SUCCESS;
04416
04417
04418 if ((SubNode!=CHILD) && (SubNode!=DIFF_CHILD))
04419 {
04420 if ((NR_busdata[NR_node_reference].phases & 0x80) == 0x80)
04421 {
04422 phase_conf = 0x80;
04423 is_triplex_node = true;
04424 }
04425 else
04426 {
04427 phase_conf=NR_busdata[NR_node_reference].phases & 0x07;
04428 is_triplex_node = false;
04429 }
04430 }
04431 else
04432 {
04433 if ((NR_busdata[*NR_subnode_reference].phases & 0x80) == 0x80)
04434 {
04435 phase_conf = 0x80;
04436 is_triplex_node = true;
04437 }
04438 else
04439 {
04440 phase_conf=NR_busdata[*NR_subnode_reference].phases & 0x07;
04441 is_triplex_node = false;
04442 }
04443 }
04444
04445
04446 for (indexval=0; indexval<3; indexval++)
04447 {
04448 if (is_triplex_node == true)
04449 {
04450 phase_mask = 0x80;
04451 }
04452 else
04453 {
04454
04455 phase_mask = (1 << (2 - indexval));
04456 }
04457
04458
04459 if ((phase_conf & phase_mask) == phase_mask)
04460 {
04461
04462 if ((SubNode!=CHILD) && (SubNode!=DIFF_CHILD))
04463 {
04464 if (is_triplex_node == true)
04465 {
04466 if (indexval < 2)
04467 {
04468 curr_freq_state.voltage_val[indexval]=NR_busdata[NR_node_reference].V[indexval];
04469 }
04470 else
04471 {
04472 curr_freq_state.voltage_val[indexval]=NR_busdata[NR_node_reference].V[0] + NR_busdata[NR_node_reference].V[1];
04473 }
04474 }
04475 else
04476 {
04477 curr_freq_state.voltage_val[indexval]=NR_busdata[NR_node_reference].V[indexval];
04478 }
04479 }
04480 else
04481 {
04482 if (is_triplex_node == true)
04483 {
04484 curr_freq_state.voltage_val[indexval]=NR_busdata[*NR_subnode_reference].V[indexval];
04485 }
04486 else
04487 {
04488 curr_freq_state.voltage_val[indexval]=NR_busdata[*NR_subnode_reference].V[0] + NR_busdata[*NR_subnode_reference].V[1];
04489 }
04490 }
04491
04492
04493 curr_freq_state.anglemeas[indexval] = atan2(curr_freq_state.voltage_val[indexval].Im(),curr_freq_state.voltage_val[indexval].Re());
04494
04495
04496 if (fmeas_type == FM_SIMPLE)
04497 {
04498
04499 adiffval = compute_angle_diff(curr_freq_state.anglemeas[indexval],prev_freq_state.anglemeas[indexval]);
04500
04501 fbus = (adiffval/deltat + freq_omega_ref) / (2.0 * PI);
04502 dfmeasdt = (fbus - prev_freq_state.fmeas[indexval]) / freq_sfm_Tf;
04503 curr_freq_state.fmeas[indexval] = prev_freq_state.fmeas[indexval] + dfmeasdt*deltat;
04504 }
04505 else if (fmeas_type == FM_PLL)
04506 {
04507
04508 if (prev_freq_state.voltage_val[indexval].Mag() > 0.0)
04509 {
04510 errorval = prev_freq_state.voltage_val[indexval].Re()*prev_freq_state.sinangmeas[indexval];
04511 errorval -= prev_freq_state.voltage_val[indexval].Im()*prev_freq_state.cosangmeas[indexval];
04512 errorval /= prev_freq_state.voltage_val[indexval].Mag();
04513 errorval *= -1.0;
04514 }
04515 else
04516 {
04517 errorval = 0.0;
04518 }
04519
04520 deltaom = freq_pll_Kp * errorval + prev_freq_state.x[indexval];
04521 dxdt = freq_pll_Ki * errorval;
04522
04523
04524 curr_freq_state.fmeas[indexval] = (freq_omega_ref + deltaom) / (2.0 * PI);
04525 curr_freq_state.x[indexval] = prev_freq_state.x[indexval] + dxdt*deltat;
04526 curr_freq_state.anglemeas[indexval] = prev_freq_state.anglemeas[indexval] + deltaom*deltat;
04527
04528
04529 curr_freq_state.sinangmeas[indexval] = sin(curr_freq_state.anglemeas[indexval]);
04530 curr_freq_state.cosangmeas[indexval] = cos(curr_freq_state.anglemeas[indexval]);
04531 }
04532
04533 }
04534 else
04535 {
04536 curr_freq_state.fmeas[indexval] = 0.0;
04537 }
04538 }
04539
04540
04541 switch(phase_conf) {
04542 case 0x00:
04543 {
04544 curr_freq_state.average_freq = 0.0;
04545 break;
04546 }
04547 case 0x01:
04548 {
04549 curr_freq_state.average_freq = curr_freq_state.fmeas[2];
04550 break;
04551 }
04552 case 0x02:
04553 {
04554 curr_freq_state.average_freq = curr_freq_state.fmeas[1];
04555 break;
04556 }
04557 case 0x03:
04558 {
04559 curr_freq_state.average_freq = (curr_freq_state.fmeas[1] + curr_freq_state.fmeas[2]) / 2.0;
04560 break;
04561 }
04562 case 0x04:
04563 {
04564 curr_freq_state.average_freq = curr_freq_state.fmeas[0];
04565 break;
04566 }
04567 case 0x05:
04568 {
04569 curr_freq_state.average_freq = (curr_freq_state.fmeas[0] + curr_freq_state.fmeas[2]) / 2.0;
04570 break;
04571 }
04572 case 0x06:
04573 {
04574 curr_freq_state.average_freq = (curr_freq_state.fmeas[0] + curr_freq_state.fmeas[1]) / 2.0;
04575 break;
04576 }
04577 case 0x07:
04578 {
04579 curr_freq_state.average_freq = (curr_freq_state.fmeas[0] + curr_freq_state.fmeas[1] + curr_freq_state.fmeas[2]) / 3.0;
04580 break;
04581 }
04582 case 0x80:
04583 {
04584 curr_freq_state.average_freq = curr_freq_state.fmeas[2];
04585 break;
04586 }
04587 default:
04588 {
04589 gl_error("Node frequency update: unknown state encountered");
04590
04591
04592
04593
04594
04595 return_status = FAILED;
04596
04597 break;
04598 }
04599 }
04600
04601 return return_status;
04602 }
04603
04604
04605
04606
04607 void node::init_freq_dynamics(void)
04608 {
04609 unsigned char phase_conf, phase_mask;
04610 int indexval;
04611 bool is_triplex_node;
04612
04613
04614 if ((SubNode!=CHILD) && (SubNode!=DIFF_CHILD))
04615 {
04616 if ((NR_busdata[NR_node_reference].phases & 0x80) == 0x80)
04617 {
04618 phase_conf = 0x80;
04619 is_triplex_node = true;
04620 }
04621 else
04622 {
04623 phase_conf=NR_busdata[NR_node_reference].phases & 0x07;
04624 is_triplex_node = false;
04625 }
04626 }
04627 else
04628 {
04629 if ((NR_busdata[*NR_subnode_reference].phases & 0x80) == 0x80)
04630 {
04631 phase_conf = 0x80;
04632 is_triplex_node = true;
04633 }
04634 else
04635 {
04636 phase_conf=NR_busdata[*NR_subnode_reference].phases & 0x07;
04637 is_triplex_node = false;
04638 }
04639 }
04640
04641
04642 for (indexval=0; indexval<3; indexval++)
04643 {
04644 if (is_triplex_node == true)
04645 {
04646 phase_mask = 0x80;
04647 }
04648 else
04649 {
04650
04651 phase_mask = (1 << (2 - indexval));
04652 }
04653
04654
04655 if ((phase_conf & phase_mask) == phase_mask)
04656 {
04657
04658 if ((SubNode!=CHILD) && (SubNode!=DIFF_CHILD))
04659 {
04660 if (is_triplex_node == true)
04661 {
04662 if (indexval < 2)
04663 {
04664 prev_freq_state.voltage_val[indexval]=NR_busdata[NR_node_reference].V[indexval];
04665 }
04666 else
04667 {
04668 prev_freq_state.voltage_val[indexval]=NR_busdata[NR_node_reference].V[0] + NR_busdata[NR_node_reference].V[1];
04669 }
04670 }
04671 else
04672 {
04673 prev_freq_state.voltage_val[indexval]=NR_busdata[NR_node_reference].V[indexval];
04674 }
04675 }
04676 else
04677 {
04678 if (is_triplex_node == true)
04679 {
04680 prev_freq_state.voltage_val[indexval]=NR_busdata[*NR_subnode_reference].V[indexval];
04681 }
04682 else
04683 {
04684 prev_freq_state.voltage_val[indexval]=NR_busdata[*NR_subnode_reference].V[0] + NR_busdata[*NR_subnode_reference].V[1];
04685 }
04686 }
04687
04688
04689 prev_freq_state.anglemeas[indexval] = atan2(prev_freq_state.voltage_val[indexval].Im(),prev_freq_state.voltage_val[indexval].Re());
04690
04691
04692 prev_freq_state.fmeas[indexval] = current_frequency;
04693
04694
04695 if (fmeas_type == FM_PLL)
04696 {
04697 prev_freq_state.sinangmeas[indexval] = sin(prev_freq_state.anglemeas[indexval]);
04698 prev_freq_state.cosangmeas[indexval] = cos(prev_freq_state.anglemeas[indexval]);
04699 }
04700 }
04701 else
04702 {
04703 prev_freq_state.voltage_val[indexval] = complex(0.0,0.0);
04704 prev_freq_state.x[indexval] = 0.0;
04705 prev_freq_state.anglemeas[indexval] = 0.0;
04706 prev_freq_state.fmeas[indexval] = 0.0;
04707 prev_freq_state.average_freq = current_frequency;
04708 prev_freq_state.sinangmeas[indexval] = 0.0;
04709 prev_freq_state.cosangmeas[indexval] = 0.0;
04710 }
04711 }
04712
04713
04714 memcpy(&curr_freq_state,&prev_freq_state,sizeof(FREQM_STATES));
04715 }
04716
04717
04718 double node::perform_GFA_checks(double timestepvalue)
04719 {
04720 bool voltage_violation, frequency_violation, trigger_disconnect, check_phase;
04721 double temp_pu_voltage;
04722 double return_time_freq, return_time_volt, return_value;
04723 char indexval;
04724 unsigned char phasevals;
04725 OBJECT *hdr = OBJECTHDR(this);
04726
04727
04728 return_time_freq = -1.0;
04729 return_time_volt = -1.0;
04730 return_value = -1.0;
04731
04732
04733 if ((SubNode!=CHILD) && (SubNode!=DIFF_CHILD))
04734 {
04735 phasevals = NR_busdata[NR_node_reference].phases & 0x87;
04736 }
04737 else
04738 {
04739 phasevals = NR_busdata[*NR_subnode_reference].phases & 0x87;
04740 }
04741
04742
04743 if ((curr_freq_state.average_freq > GFA_freq_high_trip) || (curr_freq_state.average_freq < GFA_freq_low_trip))
04744 {
04745
04746 frequency_violation = true;
04747
04748
04749 freq_violation_time_total += timestepvalue;
04750
04751
04752 out_of_violation_time_total = 0.0;
04753
04754
04755 if (curr_freq_state.average_freq > GFA_freq_high_trip)
04756 {
04757 if (freq_violation_time_total >= GFA_freq_disconnect_time)
04758 {
04759 trigger_disconnect = true;
04760 return_time_freq = GFA_reconnect_time;
04761
04762
04763 GFA_trip_method = GFA_OF;
04764 }
04765 else
04766 {
04767 trigger_disconnect = false;
04768 return_time_freq = GFA_freq_disconnect_time - freq_violation_time_total;
04769 }
04770 }
04771 else if (curr_freq_state.average_freq < GFA_freq_low_trip)
04772 {
04773 if (freq_violation_time_total >= GFA_freq_disconnect_time)
04774 {
04775 trigger_disconnect = true;
04776 return_time_freq = GFA_reconnect_time;
04777
04778
04779 GFA_trip_method = GFA_UF;
04780 }
04781 else
04782 {
04783 trigger_disconnect = false;
04784 return_time_freq = GFA_freq_disconnect_time - freq_violation_time_total;
04785 }
04786 }
04787 else
04788 {
04789 gl_error("Node%d %s GFA checks failed- invalid state!",hdr->id,hdr->name ? hdr->name : "Unnamed");
04790
04791
04792
04793
04794 }
04795 }
04796 else
04797 {
04798
04799 frequency_violation = false;
04800 trigger_disconnect = false;
04801
04802
04803 freq_violation_time_total = 0.0;
04804
04805
04806 return_time_freq = -1.0;
04807 }
04808
04809
04810 voltage_violation = false;
04811
04812
04813
04814 for (indexval = 0; indexval < 3; indexval++)
04815 {
04816
04817 if ((phasevals & 0x80) == 0x80)
04818 {
04819
04820 if (indexval < 2)
04821 {
04822 check_phase = true;
04823 }
04824 else
04825 {
04826 check_phase = false;
04827 }
04828 }
04829 else if ((indexval == 0) && ((phasevals & 0x04) == 0x04))
04830 {
04831 check_phase = true;
04832 }
04833 else if ((indexval == 1) && ((phasevals & 0x02) == 0x02))
04834 {
04835 check_phase = true;
04836 }
04837 else if ((indexval == 2) && ((phasevals & 0x01) == 0x01))
04838 {
04839 check_phase = true;
04840 }
04841 else
04842 {
04843 check_phase = false;
04844 }
04845
04846
04847 if (check_phase == true)
04848 {
04849
04850 temp_pu_voltage = voltage[indexval].Mag()/nominal_voltage;
04851
04852
04853 if ((temp_pu_voltage < GFA_voltage_low_trip) || (temp_pu_voltage > GFA_voltage_high_trip))
04854 {
04855
04856 voltage_violation = true;
04857
04858
04859 volt_violation_time_total += timestepvalue;
04860
04861
04862 out_of_violation_time_total = 0.0;
04863
04864
04865 if (temp_pu_voltage < GFA_voltage_low_trip)
04866 {
04867 if (volt_violation_time_total >= GFA_volt_disconnect_time)
04868 {
04869 trigger_disconnect = true;
04870 return_time_volt = GFA_reconnect_time;
04871
04872
04873 GFA_trip_method = GFA_UV;
04874 }
04875 else
04876 {
04877 trigger_disconnect = false;
04878 return_time_volt = GFA_volt_disconnect_time - volt_violation_time_total;
04879 }
04880 }
04881 else if (temp_pu_voltage >= GFA_voltage_high_trip)
04882 {
04883 if (volt_violation_time_total >= GFA_volt_disconnect_time)
04884 {
04885 trigger_disconnect = true;
04886 return_time_volt = GFA_reconnect_time;
04887
04888
04889 GFA_trip_method = GFA_OV;
04890 }
04891 else
04892 {
04893 trigger_disconnect = false;
04894 return_time_volt = GFA_volt_disconnect_time - volt_violation_time_total;
04895 }
04896 }
04897 else
04898 {
04899 gl_error("Node%d %s GFA checks failed- invalid state!",hdr->id,hdr->name ? hdr->name : "Unnamed");
04900
04901 }
04902
04903
04904 break;
04905 }
04906
04907 }
04908
04909 }
04910
04911
04912 if (voltage_violation == false)
04913 {
04914 volt_violation_time_total = 0.0;
04915 return_time_volt = -1.0;
04916 }
04917
04918
04919 if ((return_time_volt > 0.0) && (return_time_freq > 0.0))
04920 {
04921
04922 if (return_time_volt < return_time_freq)
04923 {
04924 return_value = return_time_volt;
04925 }
04926 else
04927 {
04928 return_value = return_time_freq;
04929 }
04930 }
04931 else if ((return_time_volt > 0.0) && (return_time_freq < 0.0))
04932 {
04933 return_value = return_time_volt;
04934 }
04935 else if ((return_time_volt < 0.0) && (return_time_freq > 0.0))
04936 {
04937 return_value = return_time_freq;
04938 }
04939 else
04940 {
04941 return_value = -1.0;
04942 }
04943
04944
04945 if ((frequency_violation == true) || (voltage_violation == true))
04946 {
04947
04948 out_of_violation_time_total = 0.0;
04949 }
04950 else
04951 {
04952
04953 out_of_violation_time_total += timestepvalue;
04954 }
04955
04956
04957 if (GFA_status == false)
04958 {
04959 if (out_of_violation_time_total >= GFA_reconnect_time)
04960 {
04961
04962 GFA_status = true;
04963
04964
04965 GFA_trip_method = GFA_NONE;
04966
04967
04968 return -1.0;
04969 }
04970 else
04971 {
04972 GFA_status = false;
04973
04974
04975 return_value = GFA_reconnect_time - out_of_violation_time_total;
04976
04977
04978 return return_value;
04979 }
04980 }
04981 else
04982 {
04983 if (trigger_disconnect == true)
04984 {
04985 GFA_status = false;
04986
04987
04988 return return_value;
04989 }
04990 else
04991 {
04992
04993 GFA_trip_method = GFA_NONE;
04994
04995
04996 return return_value;
04997 }
04998 }
04999 }
05000
05001
05002 STATUS node::NR_swap_swing_status(bool desired_status)
05003 {
05004 OBJECT *hdr = OBJECTHDR(this);
05005
05006
05007 if ((SubNode!=CHILD) && (SubNode!=DIFF_CHILD))
05008 {
05009
05010 if (NR_busdata[NR_node_reference].type > 1)
05011 {
05012
05013 NR_busdata[NR_node_reference].swing_functions_enabled = desired_status;
05014 }
05015 else
05016 {
05017 gl_warning("node:%s - Not a SWING-capable bus, so no swing status swap changed",(hdr->name ? hdr->name : "unnamed"));
05018
05019
05020
05021
05022 }
05023 }
05024 else
05025 {
05026
05027 if (NR_busdata[*NR_subnode_reference].type > 1)
05028 {
05029
05030 NR_busdata[*NR_subnode_reference].swing_functions_enabled = desired_status;
05031 }
05032 else
05033 {
05034 gl_warning("node:%s - Not a SWING-capable bus, so no swing status swap changed",(hdr->name ? hdr->name : "unnamed"));
05035
05036 }
05037 }
05038
05039
05040 return SUCCESS;
05041 }
05042
05043
05044 STATUS node::reset_node_island_condition(void)
05045 {
05046 OBJECT *obj = OBJECTHDR(this);
05047 STATUS temp_status;
05048 FUNCTIONADDR temp_fxn_val;
05049 int node_calling_reference;
05050
05051
05052 reset_island_state = false;
05053
05054
05055 if ((SubNode != CHILD) && (SubNode!=DIFF_CHILD))
05056 {
05057
05058 if (NR_busdata[NR_node_reference].island_number != -1)
05059 {
05060 gl_warning("node:%d - %s - Tried to re-enable a node that wasn't disabled!",obj->id,(obj->name ? obj->name : "Unnamed"));
05061
05062
05063
05064
05065
05066 return FAILED;
05067 }
05068 else
05069 {
05070
05071 NR_busdata[NR_node_reference].phases = NR_busdata[NR_node_reference].origphases;
05072 }
05073 }
05074 else
05075 {
05076 if (NR_busdata[*NR_subnode_reference].island_number != -1)
05077 {
05078 gl_warning("node:%d - %s - Tried to re-enable a node that wasn't disabled!",obj->id,(obj->name ? obj->name : "Unnamed"));
05079
05080
05081
05082 return FAILED;
05083 }
05084 else
05085 {
05086
05087 NR_busdata[*NR_subnode_reference].phases = NR_busdata[*NR_subnode_reference].origphases;
05088 }
05089 }
05090
05091
05092
05093 if (fault_check_object == NULL)
05094 {
05095
05096 GL_THROW("node:%d - %s -- Island condition reset failed - no fault_check object mapped!",obj->id,(obj->name ? obj->name : "Unnamed"));
05097
05098
05099
05100
05101
05102 }
05103
05104
05105 temp_fxn_val = (FUNCTIONADDR)(gl_get_function(fault_check_object,"rescan_topology"));
05106
05107
05108 if (temp_fxn_val == NULL)
05109 {
05110
05111 GL_THROW("node:%d - %s -- Island condition reset failed - reset function mapping failed!",obj->id,(obj->name ? obj->name : "Unnamed"));
05112
05113
05114
05115
05116 }
05117
05118
05119 node_calling_reference = -99;
05120
05121
05122 temp_status = ((STATUS (*)(OBJECT *,int))(temp_fxn_val))(fault_check_object,node_calling_reference);
05123
05124
05125 return temp_status;
05126 }
05127
05128
05129
05130 STATUS node::NR_map_current_update_function(OBJECT *callObj)
05131 {
05132 OBJECT *hdr = OBJECTHDR(this);
05133 OBJECT *phdr = NULL;
05134
05135
05136 if (solver_method == SM_NR)
05137 {
05138
05139 if ((SubNode!=CHILD) && (SubNode!=DIFF_CHILD))
05140 {
05141
05142 if (NR_busdata[NR_node_reference].ExtraCurrentInjFunc == NULL)
05143 {
05144
05145 NR_busdata[NR_node_reference].ExtraCurrentInjFunc = (FUNCTIONADDR)(gl_get_function(callObj,"current_injection_update"));
05146
05147
05148 if (NR_busdata[NR_node_reference].ExtraCurrentInjFunc == NULL)
05149 {
05150 gl_error("node:%d - %s - Failed to map current_injection_update from calling object:%d - %s",hdr->id,(hdr->name ? hdr->name : "Unnamed"),callObj->id,(callObj->name ? callObj->name : "Unnamed"));
05151
05152
05153
05154
05155
05156 return FAILED;
05157 }
05158
05159
05160
05161 NR_busdata[NR_node_reference].ExtraCurrentInjFuncObject = callObj;
05162 }
05163 else
05164 {
05165 gl_error("node:%d - %s - Already has an extra current injection function mapped",hdr->id,(hdr->name ? hdr->name : "Unnamed"));
05166
05167
05168
05169
05170
05171 return FAILED;
05172 }
05173 }
05174 else
05175 {
05176
05177 phdr = NR_busdata[*NR_subnode_reference].obj;
05178
05179
05180 if (NR_busdata[*NR_subnode_reference].ExtraCurrentInjFunc == NULL)
05181 {
05182
05183 NR_busdata[*NR_subnode_reference].ExtraCurrentInjFunc = (FUNCTIONADDR)(gl_get_function(callObj,"current_injection_update"));
05184
05185
05186 if (NR_busdata[*NR_subnode_reference].ExtraCurrentInjFunc == NULL)
05187 {
05188 gl_error("node:%d - %s - Failed to map current_injection_update from calling object:%d - %s",hdr->id,(hdr->name ? hdr->name : "Unnamed"),callObj->id,(callObj->name ? callObj->name : "Unnamed"));
05189
05190
05191 return FAILED;
05192 }
05193
05194
05195
05196 NR_busdata[*NR_subnode_reference].ExtraCurrentInjFuncObject = callObj;
05197 }
05198 else
05199 {
05200 gl_error("node:%d - %s - Parent node:%d - %s - Already has an extra current injection function mapped",hdr->id,(hdr->name ? hdr->name : "Unnamed"),phdr->id,(phdr->name ? phdr->name : "Unnamed"));
05201
05202
05203
05204
05205
05206 return FAILED;
05207 }
05208 }
05209 }
05210 else
05211 {
05212 gl_warning("node:%d - %s - Attempted to map an NR-based function, but is not using an NR solver",hdr->id,(hdr->name ? hdr->name : "Unnamed"));
05213
05214
05215
05216
05217
05218
05219 return SUCCESS;
05220 }
05221
05222
05223 return SUCCESS;
05224 }
05225
05226
05227 STATUS node::link_VFD_functions(OBJECT *linkVFD)
05228 {
05229 OBJECT *obj = OBJECTHDR(this);
05230
05231
05232 VFD_object = linkVFD;
05233
05234
05235 VFD_updating_function = (FUNCTIONADDR)(gl_get_function(linkVFD,"vfd_current_injection_update"));
05236
05237
05238 if (VFD_updating_function == NULL)
05239 {
05240 gl_warning("Failure to map VFD current injection update for device:%s",(obj->name ? obj->name : "Unnamed"));
05241
05242
05243
05244
05245
05246
05247 return FAILED;
05248 }
05249
05250
05251 VFD_attached = true;
05252
05253
05254 return SUCCESS;
05255 }
05256
05257
05258
05259
05260
05261
05262 double node::compute_angle_diff(double angle_B, double angle_A)
05263 {
05264 double diff_val, two_PI;
05265
05266
05267 two_PI = 2.0 * PI;
05268
05269
05270 diff_val = fmod((angle_B - angle_A + PI), two_PI);
05271
05272
05273 if (diff_val < 0.0)
05274 {
05275 diff_val += two_PI;
05276 }
05277
05278
05279 return (diff_val - PI);
05280 }
05281
05283
05285 EXPORT int isa_node(OBJECT *obj, char *classname)
05286 {
05287 if(obj != 0 && classname != 0){
05288 return OBJECTDATA(obj,node)->isa(classname);
05289 } else {
05290 return 0;
05291 }
05292 }
05293
05294 EXPORT int notify_node(OBJECT *obj, int update_mode, PROPERTY *prop, char *value){
05295 node *n = OBJECTDATA(obj, node);
05296 int rv = 1;
05297
05298 rv = n->notify(update_mode, prop, value);
05299
05300 return rv;
05301 }
05302
05303
05304 EXPORT STATUS attach_vfd_to_node(OBJECT *obj,OBJECT *calledVFD)
05305 {
05306 node *nodeObj = OBJECTDATA(obj,node);
05307
05308
05309 return nodeObj->link_VFD_functions(calledVFD);
05310 }
05311
05312
05313 EXPORT SIMULATIONMODE interupdate_node(OBJECT *obj, unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val, bool interupdate_pos)
05314 {
05315 node *my = OBJECTDATA(obj,node);
05316 SIMULATIONMODE status = SM_ERROR;
05317 try
05318 {
05319 status = my->inter_deltaupdate_node(delta_time,dt,iteration_count_val,interupdate_pos);
05320 return status;
05321 }
05322 catch (char *msg)
05323 {
05324 gl_error("interupdate_node(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
05325 return status;
05326 }
05327 }
05328
05329
05330 EXPORT STATUS swap_node_swing_status(OBJECT *obj, bool desired_status)
05331 {
05332 STATUS temp_status;
05333
05334
05335 node *my = OBJECTDATA(obj,node);
05336
05337
05338 temp_status = my->NR_swap_swing_status(desired_status);
05339
05340
05341 return temp_status;
05342 }
05343
05344
05345
05346 EXPORT STATUS node_map_current_update_function(OBJECT *nodeObj, OBJECT *callObj)
05347 {
05348 STATUS temp_status;
05349
05350
05351 node *my = OBJECTDATA(nodeObj,node);
05352
05353
05354 temp_status = my->NR_map_current_update_function(callObj);
05355
05356
05357 return temp_status;
05358 }
05359
05360
05361 EXPORT STATUS node_reset_disabled_status(OBJECT *nodeObj)
05362 {
05363 STATUS temp_status;
05364
05365
05366 node *my = OBJECTDATA(nodeObj,node);
05367
05368
05369 temp_status = my->reset_node_island_condition();
05370
05371
05372 return temp_status;
05373 }