00001
00002
00003
00004 #include <stdlib.h>
00005 #include <stdio.h>
00006 #include <errno.h>
00007 #include <math.h>
00008
00009 #include <iostream>
00010
00011 #include "motor.h"
00012
00014
00016 CLASS* motor::oclass = NULL;
00017 CLASS* motor::pclass = NULL;
00018
00026 static PASSCONFIG passconfig = PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN;
00027 static PASSCONFIG clockpass = PC_BOTTOMUP;
00028
00029
00030 motor::motor(MODULE *mod):node(mod)
00031 {
00032 if(oclass == NULL)
00033 {
00034 pclass = node::oclass;
00035
00036 oclass = gl_register_class(mod,"motor",sizeof(motor),passconfig|PC_UNSAFE_OVERRIDE_OMIT|PC_AUTOLOCK);
00037 if (oclass==NULL)
00038 throw "unable to register class motor";
00039 else
00040 oclass->trl = TRL_PRINCIPLE;
00041
00042 if(gl_publish_variable(oclass,
00043 PT_INHERIT, "node",
00044 PT_double, "base_power[W]", PADDR(Pbase),PT_DESCRIPTION,"base power",
00045 PT_double, "n", PADDR(n),PT_DESCRIPTION,"ratio of stator auxiliary windings to stator main windings",
00046 PT_double, "Rds[ohm]", PADDR(Rds),PT_DESCRIPTION,"d-axis resistance - single-phase model",
00047 PT_double, "Rqs[ohm]", PADDR(Rqs),PT_DESCRIPTION,"q-asis resistance - single-phase model",
00048 PT_double, "Rs[ohm]", PADDR(Rs),PT_DESCRIPTION,"stator resistance - three-phase model",
00049 PT_double, "Rr[ohm]", PADDR(Rr),PT_DESCRIPTION,"rotor resistance",
00050 PT_double, "Xm[ohm]", PADDR(Xm),PT_DESCRIPTION,"magnetizing reactance",
00051 PT_double, "Xr[ohm]", PADDR(Xr),PT_DESCRIPTION,"rotor reactance",
00052 PT_double, "Xs[ohm]", PADDR(Xs),PT_DESCRIPTION,"stator leakage reactance - three-phase model",
00053 PT_double, "Xc_run[ohm]", PADDR(Xc1),PT_DESCRIPTION,"running capacitor reactance - single-phase model",
00054 PT_double, "Xc_start[ohm]", PADDR(Xc2),PT_DESCRIPTION,"starting capacitor reactance - single-phase model",
00055 PT_double, "Xd_prime[ohm]", PADDR(Xd_prime),PT_DESCRIPTION,"d-axis reactance - single-phase model",
00056 PT_double, "Xq_prime[ohm]", PADDR(Xq_prime),PT_DESCRIPTION,"q-axis reactance - single-phase model",
00057 PT_double, "A_sat", PADDR(Asat),PT_DESCRIPTION,"flux saturation parameter, A - single-phase model",
00058 PT_double, "b_sat", PADDR(bsat),PT_DESCRIPTION,"flux saturation parameter, b - single-phase model",
00059 PT_double, "H[s]", PADDR(H),PT_DESCRIPTION,"inertia constant",
00060 PT_double, "J[kg*m^2]", PADDR(Jm),PT_DESCRIPTION,"moment of inertia",
00061 PT_double, "number_of_poles", PADDR(pf),PT_DESCRIPTION,"number of poles",
00062 PT_double, "To_prime[s]", PADDR(To_prime),PT_DESCRIPTION,"rotor time constant",
00063 PT_double, "capacitor_speed[%]", PADDR(cap_run_speed_percentage),PT_DESCRIPTION,"percentage speed of nominal when starting capacitor kicks in",
00064 PT_double, "trip_time[s]", PADDR(trip_time),PT_DESCRIPTION,"time motor can stay stalled before tripping off ",
00065 PT_enumeration,"uv_relay_install",PADDR(uv_relay_install),PT_DESCRIPTION,"is under-voltage relay protection installed on this motor",
00066 PT_KEYWORD,"INSTALLED",(enumeration)uv_relay_INSTALLED,
00067 PT_KEYWORD,"UNINSTALLED",(enumeration)uv_relay_UNINSTALLED,
00068 PT_double, "uv_relay_trip_time[s]", PADDR(uv_relay_trip_time),PT_DESCRIPTION,"time low-voltage condition must exist for under-voltage protection to trip ",
00069 PT_double, "uv_relay_trip_V[pu]", PADDR(uv_relay_trip_V),PT_DESCRIPTION,"pu minimum voltage before under-voltage relay trips",
00070 PT_enumeration,"contactor_state",PADDR(contactor_state),PT_DESCRIPTION,"the current status of the motor",
00071 PT_KEYWORD,"OPEN",(enumeration)contactorOPEN,
00072 PT_KEYWORD,"CLOSED",(enumeration)contactorCLOSED,
00073 PT_double, "contactor_open_Vmin[pu]", PADDR(contactor_open_Vmin),PT_DESCRIPTION,"pu voltage at which motor contactor opens",
00074 PT_double, "contactor_close_Vmax[pu]", PADDR(contactor_close_Vmax),PT_DESCRIPTION,"pu voltage at which motor contactor recloses",
00075 PT_double, "reconnect_time[s]", PADDR(reconnect_time),PT_DESCRIPTION,"time before tripped motor reconnects",
00076
00077
00078 PT_double, "mechanical_torque[pu]", PADDR(Tmech),PT_DESCRIPTION,"mechanical torque applied to the motor",
00079 PT_double, "mechanical_torque_state_var[pu]", PADDR(Tmech_eff),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"Internal state variable torque - three-phase model",
00080 PT_int32, "iteration_count", PADDR(iteration_count),PT_DESCRIPTION,"maximum number of iterations for steady state model",
00081 PT_double, "delta_mode_voltage_trigger[%]", PADDR(DM_volt_trig_per),PT_DESCRIPTION,"percentage voltage of nominal when delta mode is triggered",
00082 PT_double, "delta_mode_rotor_speed_trigger[%]", PADDR(DM_speed_trig_per),PT_DESCRIPTION,"percentage speed of nominal when delta mode is triggered",
00083 PT_double, "delta_mode_voltage_exit[%]", PADDR(DM_volt_exit_per),PT_DESCRIPTION,"percentage voltage of nominal to exit delta mode",
00084 PT_double, "delta_mode_rotor_speed_exit[%]", PADDR(DM_speed_exit_per),PT_DESCRIPTION,"percentage speed of nominal to exit delta mode",
00085 PT_double, "maximum_speed_error", PADDR(speed_error),PT_DESCRIPTION,"maximum speed error for transitioning modes",
00086 PT_double, "rotor_speed[rad/s]", PADDR(wr),PT_DESCRIPTION,"rotor speed",
00087 PT_enumeration,"motor_status",PADDR(motor_status),PT_DESCRIPTION,"the current status of the motor",
00088 PT_KEYWORD,"RUNNING",(enumeration)statusRUNNING,
00089 PT_KEYWORD,"STALLED",(enumeration)statusSTALLED,
00090 PT_KEYWORD,"TRIPPED",(enumeration)statusTRIPPED,
00091 PT_KEYWORD,"OFF",(enumeration)statusOFF,
00092 PT_int32,"motor_status_number",PADDR(motor_status),PT_DESCRIPTION,"the current status of the motor as an integer",
00093 PT_enumeration,"desired_motor_state",PADDR(motor_override),PT_DESCRIPTION,"Should the motor be on or off",
00094 PT_KEYWORD,"ON",(enumeration)overrideON,
00095 PT_KEYWORD,"OFF",(enumeration)overrideOFF,
00096 PT_enumeration,"motor_operation_type",PADDR(motor_op_mode),PT_DESCRIPTION,"current operation type of the motor - deltamode related",
00097 PT_KEYWORD,"SINGLE-PHASE",(enumeration)modeSPIM,
00098 PT_KEYWORD,"THREE-PHASE",(enumeration)modeTPIM,
00099 PT_enumeration,"triplex_connection_type",PADDR(triplex_connection_type),PT_DESCRIPTION,"Describes how the motor will connect to the triplex devices",
00100 PT_KEYWORD,"TRIPLEX_1N",(enumeration)TPNconnected1N,
00101 PT_KEYWORD,"TRIPLEX_2N",(enumeration)TPNconnected2N,
00102 PT_KEYWORD,"TRIPLEX_12",(enumeration)TPNconnected12,
00103
00104
00105 PT_double, "wb[rad/s]", PADDR(wbase),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"base speed",
00106 PT_double, "ws[rad/s]", PADDR(ws),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"system speed",
00107 PT_complex, "psi_b", PADDR(psi_b),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"backward rotating flux",
00108 PT_complex, "psi_f", PADDR(psi_f),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"forward rotating flux",
00109 PT_complex, "psi_dr", PADDR(psi_dr),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"Rotor d axis flux",
00110 PT_complex, "psi_qr", PADDR(psi_qr),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"Rotor q axis flux",
00111 PT_complex, "Ids", PADDR(Ids),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"time before tripped motor reconnects",
00112 PT_complex, "Iqs", PADDR(Iqs),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"time before tripped motor reconnects",
00113 PT_complex, "If", PADDR(If),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"forward current",
00114 PT_complex, "Ib", PADDR(Ib),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"backward current",
00115 PT_complex, "Is", PADDR(Is),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"motor current",
00116 PT_complex, "electrical_power[VA]", PADDR(motor_elec_power),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"motor power",
00117 PT_double, "electrical_torque[pu]", PADDR(Telec),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"electrical torque",
00118 PT_complex, "Vs", PADDR(Vs),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"motor voltage",
00119 PT_bool, "motor_trip", PADDR(motor_trip),PT_DESCRIPTION,"boolean variable to check if motor is tripped",
00120 PT_double, "trip", PADDR(trip),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"current time in tripped state",
00121 PT_double, "reconnect", PADDR(reconnect),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"current time since motor was tripped",
00122
00123
00124
00125 PT_complex, "phips", PADDR(phips),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"positive sequence stator flux",
00126 PT_complex, "phins_cj", PADDR(phins_cj),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"conjugate of negative sequence stator flux",
00127 PT_complex, "phipr", PADDR(phipr),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"positive sequence rotor flux",
00128 PT_complex, "phinr_cj", PADDR(phinr_cj),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"conjugate of negative sequence rotor flux",
00129 PT_double, "per_unit_rotor_speed[pu]", PADDR(wr_pu),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"rotor speed in per-unit",
00130 PT_complex, "Ias[pu]", PADDR(Ias),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"motor phase-a stator current",
00131 PT_complex, "Ibs[pu]", PADDR(Ibs),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"motor phase-b stator current",
00132 PT_complex, "Ics[pu]", PADDR(Ics),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"motor phase-c stator current",
00133 PT_complex, "Vas[pu]", PADDR(Vas),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"motor phase-a stator-to-ground voltage",
00134 PT_complex, "Vbs[pu]", PADDR(Vbs),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"motor phase-b stator-to-ground voltage",
00135 PT_complex, "Vcs[pu]", PADDR(Vcs),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"motor phase-c stator-to-ground voltage",
00136 PT_complex, "Ips", PADDR(Ips),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"positive sequence stator current",
00137 PT_complex, "Ipr", PADDR(Ipr),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"positive sequence rotor current",
00138 PT_complex, "Ins_cj", PADDR(Ins_cj),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"conjugate of negative sequence stator current",
00139 PT_complex, "Inr_cj", PADDR(Inr_cj),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"conjugate of negative sequence rotor current",
00140 PT_double, "Ls", PADDR(Ls),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"stator synchronous reactance",
00141 PT_double, "Lr", PADDR(Lr),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"rotor synchronous reactance",
00142 PT_double, "sigma1", PADDR(sigma1),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"intermediate variable 1 associated with synch. react.",
00143 PT_double, "sigma2", PADDR(sigma2),PT_ACCESS,PA_HIDDEN,PT_DESCRIPTION,"intermediate variable 2 associated with synch. react.",
00144
00145 NULL) < 1) GL_THROW("unable to publish properties in %s",__FILE__);
00146
00147
00148 if (gl_publish_function(oclass, "interupdate_pwr_object", (FUNCTIONADDR)interupdate_motor)==NULL)
00149 GL_THROW("Unable to publish motor deltamode function");
00150 if (gl_publish_function(oclass, "pwr_object_swing_swapper", (FUNCTIONADDR)swap_node_swing_status)==NULL)
00151 GL_THROW("Unable to publish motor swing-swapping function");
00152 if (gl_publish_function(oclass, "attach_vfd_to_pwr_object", (FUNCTIONADDR)attach_vfd_to_node)==NULL)
00153 GL_THROW("Unable to publish motor VFD attachment function");
00154 }
00155 }
00156
00157 int motor::create()
00158 {
00159 int result = node::create();
00160 last_cycle = 0;
00161
00162
00163 Tmech = -1.0;
00164 Tmech_eff = 0.0;
00165
00166
00167 motor_override = overrideON;
00168 motor_trip = 0;
00169 Pbase = -999;
00170 n = 1.22;
00171 Rds =0.0365;
00172 Rqs = 0.0729;
00173 Rr =-999;
00174 Xm=-999;
00175 Xr=-999;
00176 Xc1 = -2.779;
00177 Xc2 = -0.7;
00178 Xd_prime = 0.1033;
00179 Xq_prime =0.1489;
00180 bsat = 0.7212;
00181 Asat = 5.6;
00182 H=-999;
00183 Jm=-999;
00184 To_prime =0.1212;
00185 trip_time = 10;
00186 reconnect_time = 300;
00187 iteration_count = 1000;
00188 cap_run_speed_percentage = 50;
00189 DM_volt_trig_per = 80;
00190 DM_speed_trig_per = 80;
00191 DM_volt_exit_per = 95;
00192 DM_speed_exit_per = 95;
00193 speed_error = 1e-10;
00194
00195 wbase=2.0*PI*nominal_frequency;
00196
00197
00198 trip = 0;
00199 reconnect = 0;
00200 psi_b = complex(0.0,0.0);
00201 psi_f = complex(0.0,0.0);
00202 psi_dr = complex(0.0,0.0);
00203 psi_qr = complex(0.0,0.0);
00204 Ids = complex(0.0,0.0);
00205 Iqs = complex(0.0,0.0);
00206 If = complex(0.0,0.0);
00207 Ib = complex(0.0,0.0);
00208 Is = complex(0.0,0.0);
00209 motor_elec_power = complex(0.0,0.0);
00210 Telec = 0;
00211 wr = 0;
00212
00213
00214
00215
00216 uv_relay_install = uv_relay_UNINSTALLED;
00217 uv_relay_time = 0;
00218 uv_relay_trip_time = 0.02;
00219 uv_relay_trip_V = 0.0;
00220 uv_lockout = 0;
00221
00222 contactor_open_Vmin = 0.0;
00223 contactor_close_Vmax = 0.01;
00224 contactor_state = contactorCLOSED;
00225
00226
00227 motor_op_mode = modeSPIM;
00228
00229
00230 pf = 4;
00231 Rs= 0.262;
00232 Xs= 1.206;
00233 rs_pu = -999;
00234 lls = -999;
00235 lm = -999;
00236 rr_pu = -999;
00237 llr = -999;
00238
00239
00240 Kfric = 0.0;
00241 phips = complex(0.0,0.0);
00242 phins_cj = complex(0.0,0.0);
00243 phipr = complex(0.0,0.0);
00244 phinr_cj = complex(0.0,0.0);
00245 wr_pu = 0.97;
00246 Ias = complex(0.0,0.0);
00247 Ibs = complex(0.0,0.0);
00248 Ics = complex(0.0,0.0);
00249 Vas = complex(0.0,0.0);
00250 Vbs = complex(0.0,0.0);
00251 Vcs = complex(0.0,0.0);
00252 Ips = complex(0.0,0.0);
00253 Ipr = complex(0.0,0.0);
00254 Ins_cj = complex(0.0,0.0);
00255 Inr_cj = complex(0.0,0.0);
00256 Ls = 0.0;
00257 Lr = 0.0;
00258 sigma1 = 0.0;
00259 sigma2 = 0.0;
00260 ws_pu = 1.0;
00261
00262 triplex_connected = false;
00263 triplex_connection_type = TPNconnected12;
00264
00265 return result;
00266 }
00267
00268 int motor::init(OBJECT *parent)
00269 {
00270
00271 OBJECT *obj = OBJECTHDR(this);
00272 int result = node::init(parent);
00273
00274
00275 int num_phases = 0;
00276 if (has_phase(PHASE_A)==true)
00277 num_phases++;
00278
00279 if (has_phase(PHASE_B)==true)
00280 num_phases++;
00281
00282 if (has_phase(PHASE_C)==true)
00283 num_phases++;
00284
00285
00286 if (num_phases == 1)
00287 {
00288 motor_op_mode = modeSPIM;
00289 }
00290 else if (num_phases == 3)
00291 {
00292 motor_op_mode = modeTPIM;
00293 }
00294 else
00295 {
00296 GL_THROW("motor:%s -- only single-phase or three-phase motors are supported",(obj->name ? obj->name : "Unnamed"));
00297
00298
00299
00300 }
00301
00302
00303 if (Tmech == -1.0)
00304 {
00305
00306 if (motor_op_mode == modeSPIM)
00307 {
00308 Tmech = 1.0448;
00309 }
00310 else
00311 {
00312 Tmech = 0.95;
00313
00314
00315 if (motor_status != statusOFF)
00316 {
00317 Tmech_eff = Tmech;
00318 }
00319 }
00320 }
00321
00322
00323
00324
00325 if (Pbase == -999)
00326 {
00327
00328 if (motor_op_mode == modeSPIM)
00329 {
00330 Pbase = 3500;
00331 }
00332 else
00333 {
00334 Pbase = 372876;
00335 }
00336 }
00337
00338
00339
00340 if (Xm == -999)
00341 {
00342
00343 if (motor_op_mode == modeSPIM)
00344 {
00345 Xm = 2.28;
00346 }
00347 else
00348 {
00349 Xm = 56.02;
00350 }
00351 }
00352
00353
00354
00355 if (Xr == -999)
00356 {
00357
00358 if (motor_op_mode == modeSPIM)
00359 {
00360 Xr = 2.33;
00361 }
00362 else
00363 {
00364 Xr = 1.206;
00365 }
00366 }
00367
00368
00369
00370 if (Rr == -999)
00371 {
00372
00373 if (motor_op_mode == modeSPIM)
00374 {
00375 Rr = 0.0486;
00376 }
00377 else
00378 {
00379 Rr = 0.187;
00380 }
00381 }
00382
00383
00384
00385 if ((Jm == -999) && (H == -999))
00386 {
00387
00388 if (motor_op_mode == modeSPIM)
00389 {
00390 Jm = 0.0019701;
00391 H = 0.04;
00392 }
00393 else
00394 {
00395 Jm = 11.06;
00396 H = 0.52694;
00397 }
00398 }
00399 else if ((Jm != -999) && (H == -999))
00400 {
00401 H = 1/2*pow(2/pf,2)*Jm*pow(wbase,2)/Pbase;
00402 }
00403 else if ((Jm == -999) && (H != -999))
00404 {
00405 Jm = H /(1/2*pow(2/pf,2)*pow(wbase,2)/Pbase);
00406 }
00407 else if ((Jm != -999) && (H != -999))
00408 {
00409 gl_warning("motor:%s -- both H and J were specified, H will be used, J is ignored",(obj->name ? obj->name : "Unnamed"));
00410
00411
00412
00413 }
00414
00415
00416 Zbase = 3*pow(nominal_voltage,2)/Pbase;
00417 rs_pu = Rs/Zbase;
00418 lls = Xs/Zbase;
00419 rr_pu = Rr/Zbase;
00420 llr = Xr/Zbase;
00421 lm = Xm/Zbase;
00422
00423
00424
00425 if (motor_op_mode == modeSPIM)
00426 {
00427 if (has_phase(PHASE_S))
00428 {
00429 connected_phase = -1;
00430 triplex_connected = true;
00431 }
00432 else
00433 {
00434
00435 triplex_connected = false;
00436
00437 if (has_phase(PHASE_A)) {
00438 connected_phase = 0;
00439 }
00440 else if (has_phase(PHASE_B)) {
00441 connected_phase = 1;
00442 }
00443 else {
00444 connected_phase = 2;
00445 }
00446 }
00447 }
00448
00449
00450
00451 if (motor_op_mode == modeSPIM)
00452 {
00453 if ((triplex_connected == true) && (triplex_connection_type == TPNconnected12))
00454 {
00455 Ibase = Pbase/(2.0*nominal_voltage);
00456 }
00457 else
00458 {
00459 Ibase = Pbase/nominal_voltage;
00460 }
00461 }
00462 else
00463 {
00464 Ibase = Pbase/nominal_voltage/3.0;
00465 }
00466
00467
00468 cap_run_speed = (cap_run_speed_percentage*wbase)/100;
00469 DM_volt_trig = (DM_volt_trig_per)/100;
00470 DM_speed_trig = (DM_speed_trig_per*wbase)/100;
00471 DM_volt_exit = (DM_volt_exit_per)/100;
00472 DM_speed_exit = (DM_speed_exit_per*wbase)/100;
00473
00474
00475 Ls = lls + lm;
00476 Lr = llr + lm;
00477 sigma1 = Ls - lm * lm / Lr;
00478 sigma2 = Lr - lm * lm / Ls;
00479
00480 if ((motor_op_mode == modeTPIM) && (motor_status != statusRUNNING)){
00481 wr_pu = 0.0;
00482 wr = 0.0;
00483 }
00484 else if ((motor_op_mode == modeTPIM) && (motor_status == statusRUNNING)){
00485 wr_pu = 1.0;
00486 wr = wbase;
00487 }
00488
00489 wr_pu_prev = wr_pu;
00490
00491
00492 if (contactor_open_Vmin > contactor_close_Vmax){
00493 GL_THROW("motor:%s -- contactor_open_Vmin must be less or equal to than contactor_close_Vmax",(obj->name ? obj->name : "Unnamed"));
00494 }
00495
00496
00497
00498 if (uv_relay_trip_time < 0 ){
00499 GL_THROW("motor:%s -- uv_relay_trip_time must be greater than or equal to 0",(obj->name ? obj->name : "Unnamed"));
00500 }
00501 if (uv_relay_trip_V < 0 || uv_relay_trip_V > 1){
00502 GL_THROW("motor:%s -- uv_relay_trip_V must be greater than or equal to 0 and less than or equal to 1",(obj->name ? obj->name : "Unnamed"));
00503 }
00504
00505 return result;
00506 }
00507
00508 int motor::isa(char *classname)
00509 {
00510 return strcmp(classname,"motor")==0 || node::isa(classname);
00511 }
00512
00513 TIMESTAMP motor::presync(TIMESTAMP t0, TIMESTAMP t1)
00514 {
00515
00516 if (last_cycle == 0) {
00517 last_cycle = t1;
00518 }
00519 else if ((double)t1 > last_cycle) {
00520 delta_cycle = (double)t1-last_cycle;
00521 }
00522
00523
00524 TIMESTAMP result = node::presync(t1);
00525 return result;
00526 }
00527
00528 TIMESTAMP motor::sync(TIMESTAMP t0, TIMESTAMP t1)
00529 {
00530
00531 updateFreqVolt();
00532
00533 if (motor_op_mode == modeSPIM)
00534 {
00535 if((double)t1 == last_cycle) {
00536 SPIMreinitializeVars();
00537 }
00538 else if((double)t1 > last_cycle){
00539 SPIMupdateVars();
00540 }
00541 else {
00542 gl_error("current time is less than previous time");
00543 }
00544
00545
00546 SPIMUpdateProtection(delta_cycle);
00547
00548 if (motor_override == overrideON && ws > 1 && Vs.Mag() > 0.1 && motor_trip == 0) {
00549
00550 SPIMSteadyState(t1);
00551
00552
00553 if (triplex_connected==true)
00554 {
00555
00556 if (triplex_connection_type == TPNconnected1N)
00557 {
00558 pre_rotated_current[0] = Is*Ibase;
00559 }
00560 else if (triplex_connection_type == TPNconnected2N)
00561 {
00562 pre_rotated_current[1] = Is*Ibase;
00563 }
00564 else
00565 {
00566 pre_rotated_current[2] = Is*Ibase;
00567 }
00568 }
00569 else
00570 {
00571 pre_rotated_current[connected_phase] = Is*Ibase;
00572 }
00573 }
00574 else {
00575 if (triplex_connected==true)
00576 {
00577
00578 if (triplex_connection_type == TPNconnected1N)
00579 {
00580 pre_rotated_current[0] = complex(0.0,0.0);
00581 }
00582 else if (triplex_connection_type == TPNconnected2N)
00583 {
00584 pre_rotated_current[1] = complex(0.0,0.0);
00585 }
00586 else
00587 {
00588 pre_rotated_current[2] = complex(0.0,0.0);
00589 }
00590
00591
00592 SPIMStateOFF();
00593 }
00594 else
00595 {
00596 pre_rotated_current[connected_phase] = 0;
00597 SPIMStateOFF();
00598 }
00599 }
00600
00601
00602 SPIMUpdateMotorStatus();
00603 }
00604 else
00605 {
00606
00607 if((double)t1 == last_cycle) {
00608 TPIMreinitializeVars();
00609 }
00610 else if((double)t1 > last_cycle){
00611 TPIMupdateVars();
00612 }
00613 else {
00614 gl_error("current time is less than previous time");
00615 }
00616
00617
00618 TPIMUpdateProtection(delta_cycle);
00619
00620 if (motor_override == overrideON && ws_pu > 0.1 && Vas.Mag() > 0.1 && Vbs.Mag() > 0.1 && Vcs.Mag() > 0.1 &&
00621 motor_trip == 0) {
00622
00623
00624
00625 TPIMSteadyState(t1);
00626
00627
00628 pre_rotated_current[0] = Ias*Ibase;
00629 pre_rotated_current[1] = Ibs*Ibase;
00630 pre_rotated_current[2] = Ics*Ibase;
00631 }
00632 else {
00633 pre_rotated_current[0] = 0;
00634 pre_rotated_current[1] = 0;
00635 pre_rotated_current[2] = 0;
00636 TPIMStateOFF();
00637 }
00638
00639
00640 TPIMUpdateMotorStatus();
00641 }
00642
00643
00644 TIMESTAMP result = node::sync(t1);
00645
00646 if ((double)t1 > last_cycle) {
00647 last_cycle = (double)t1;
00648 }
00649
00650
00651 if (motor_op_mode == modeSPIM)
00652 {
00653 if (((Vs.Mag() < DM_volt_trig) || (wr < DM_speed_trig)) && deltamode_inclusive)
00654 {
00655
00656 if ((motor_trip == 1 && reconnect < reconnect_time-1) || (motor_override == overrideOFF)) {
00657 return result;
00658 }
00659
00660
00661 schedule_deltamode_start(t1);
00662 return t1;
00663 }
00664 else
00665 {
00666 return result;
00667 }
00668
00669 }
00670 else
00671 {
00672
00673 if ( ((Vas.Mag() < DM_volt_trig) || (Vbs.Mag() < DM_volt_trig) ||
00674 (Vcs.Mag() < DM_volt_trig) || (wr < DM_speed_trig))
00675 && deltamode_inclusive)
00676 {
00677
00678 if ((motor_trip == 1 && reconnect < reconnect_time-1) || (motor_override == overrideOFF)) {
00679 return result;
00680 }
00681
00682
00683 schedule_deltamode_start(t1);
00684 return t1;
00685 }
00686 else
00687 {
00688 return result;
00689 }
00690 }
00691 }
00692
00693 TIMESTAMP motor::postsync(TIMESTAMP t0, TIMESTAMP t1)
00694 {
00695
00696 TIMESTAMP result = node::postsync(t1);
00697 return result;
00698 }
00699
00701
00703
00704
00705 SIMULATIONMODE motor::inter_deltaupdate(unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val, bool interupdate_pos)
00706 {
00707 OBJECT *hdr = OBJECTHDR(this);
00708 STATUS return_status_val;
00709
00710
00711 curr_delta_time = gl_globaldeltaclock;
00712
00713
00714 double deltaTime = (double)dt/(double)DT_SECOND;
00715
00716
00717 if ((iteration_count_val==0) && (interupdate_pos == false) && (fmeas_type != FM_NONE))
00718 {
00719
00720 memcpy(&prev_freq_state,&curr_freq_state,sizeof(FREQM_STATES));
00721 }
00722
00723
00724 if ((delta_time==0) && (iteration_count_val==0) && (interupdate_pos == false))
00725 {
00726
00727 NR_node_presync_fxn(0);
00728
00729 if (fmeas_type != FM_NONE) {
00730
00731 init_freq_dynamics();
00732 }
00733
00734 if (motor_op_mode == modeSPIM)
00735 {
00736
00737 updateFreqVolt();
00738
00739
00740 SPIMupdateVars();
00741
00742 SPIMSteadyState(curr_delta_time);
00743
00744
00745 SPIMUpdateMotorStatus();
00746 }
00747 else
00748 {
00749
00750
00751 updateFreqVolt();
00752
00753
00754 TPIMupdateVars();
00755
00756 TPIMSteadyState(curr_delta_time);
00757
00758
00759 TPIMUpdateMotorStatus();
00760 }
00761 }
00762
00763 if (interupdate_pos == false)
00764 {
00765
00766 if (delta_time>0) {
00767 NR_node_presync_fxn(0);
00768
00769
00770 updateFreqVolt();
00771 }
00772
00773 if (motor_op_mode == modeSPIM)
00774 {
00775
00776 if (deltaTime > 0.0003) {
00777 gl_warning("Delta time for the SPIM model needs to be lower than 0.0003 seconds");
00778 }
00779
00780 if(curr_delta_time == last_cycle) {
00781 SPIMreinitializeVars();
00782 }
00783 else if(curr_delta_time > last_cycle){
00784 SPIMupdateVars();
00785 }
00786 else {
00787 gl_error("current time is less than previous time");
00788 }
00789
00790
00791 if (delta_time>0) {
00792 SPIMUpdateProtection(deltaTime);
00793 }
00794
00795 if (motor_override == overrideON && ws > 1 && Vs.Mag() > 0.1 && motor_trip == 0) {
00796
00797 SPIMDynamic(curr_delta_time, deltaTime);
00798
00799
00800 if (triplex_connected == true)
00801 {
00802
00803 if (triplex_connection_type == TPNconnected1N)
00804 {
00805 pre_rotated_current[0] = Is*Ibase;
00806 }
00807 else if (triplex_connection_type == TPNconnected2N)
00808 {
00809 pre_rotated_current[1] = Is*Ibase;
00810 }
00811 else
00812 {
00813 pre_rotated_current[2] = Is*Ibase;
00814 }
00815 }
00816 else
00817 {
00818 pre_rotated_current[connected_phase] = Is*Ibase;
00819 }
00820 }
00821 else {
00822 if (triplex_connected == true)
00823 {
00824
00825 if (triplex_connection_type == TPNconnected1N)
00826 {
00827 pre_rotated_current[0] = complex(0.0,0.0);
00828 }
00829 else if (triplex_connection_type == TPNconnected2N)
00830 {
00831 pre_rotated_current[1] = complex(0.0,0.0);
00832 }
00833 else
00834 {
00835 pre_rotated_current[2] = complex(0.0,0.0);
00836 }
00837
00838
00839 SPIMStateOFF();
00840 }
00841 else
00842 {
00843 pre_rotated_current[connected_phase] = 0;
00844 SPIMStateOFF();
00845 }
00846 }
00847
00848
00849 SPIMUpdateMotorStatus();
00850 }
00851 else
00852 {
00853
00854 if (deltaTime > 0.0005) {
00855 gl_warning("Delta time for the TPIM model needs to be lower than 0.0005 seconds");
00856 }
00857
00858 if(curr_delta_time == last_cycle) {
00859 TPIMreinitializeVars();
00860 }
00861 else if(curr_delta_time > last_cycle){
00862 TPIMupdateVars();
00863 }
00864 else {
00865 gl_error("current time is less than previous time");
00866 }
00867
00868
00869 if (delta_time>0) {
00870 TPIMUpdateProtection(deltaTime);
00871 }
00872
00873
00874 if (motor_override == overrideON && ws_pu > 0.1 && Vas.Mag() > 0.1 && Vbs.Mag() > 0.1 && Vcs.Mag() > 0.1 &&
00875 motor_trip == 0) {
00876
00877 TPIMDynamic(curr_delta_time, deltaTime);
00878
00879
00880 pre_rotated_current[0] = Ias*Ibase;
00881 pre_rotated_current[1] = Ibs*Ibase;
00882 pre_rotated_current[2] = Ics*Ibase;
00883 }
00884 else {
00885 pre_rotated_current[0] = 0;
00886 pre_rotated_current[1] = 0;
00887 pre_rotated_current[2] = 0;
00888 TPIMStateOFF();
00889 }
00890
00891
00892 TPIMUpdateMotorStatus();
00893 }
00894
00895
00896 NR_node_sync_fxn(hdr);
00897
00898 if (curr_delta_time > last_cycle) {
00899 last_cycle = curr_delta_time;
00900 }
00901
00902 return SM_DELTA;
00903 }
00904 else
00905 {
00906
00907 BOTH_node_postsync_fxn(hdr);
00908
00909
00910 if (fmeas_type != FM_NONE)
00911 {
00912 return_status_val = calc_freq_dynamics(deltaTime);
00913
00914
00915 if (return_status_val == FAILED)
00916 {
00917 return SM_ERROR;
00918 }
00919 }
00920
00921
00922 if (motor_op_mode == modeSPIM)
00923 {
00924
00925 if ((Vs.Mag() > DM_volt_exit) && (wr > DM_speed_exit))
00926 {
00927
00928 return SM_EVENT;
00929 } else if (motor_trip == 1 && reconnect < reconnect_time-1) {
00930
00931 return SM_EVENT;
00932 } else if (motor_override == overrideOFF) {
00933
00934 return SM_EVENT;
00935 }
00936
00937
00938 return SM_DELTA;
00939 }
00940 else
00941 {
00942
00943 if ((Vas.Mag() > DM_volt_exit) && (Vbs.Mag() > DM_volt_exit) && (Vcs.Mag() > DM_volt_exit)
00944 && (wr > DM_speed_exit) && ((fabs(wr_pu-wr_pu_prev)*wbase) > speed_error))
00945 {
00946 return SM_EVENT;
00947 }
00948 else if (motor_trip == 1 && reconnect < reconnect_time-1) {
00949
00950 return SM_EVENT;
00951 }
00952 else if (motor_override == overrideOFF) {
00953
00954 return SM_EVENT;
00955 }
00956
00957
00958 return SM_DELTA;
00959 }
00960 }
00961 }
00962
00963
00964 void motor::updateFreqVolt() {
00965
00966 if (motor_op_mode == modeSPIM)
00967 {
00968 if ( (SubNode == CHILD) || (SubNode == DIFF_CHILD) )
00969 {
00970 node *parNode = OBJECTDATA(SubNodeParent,node);
00971 if (triplex_connected == true)
00972 {
00973
00974 if (triplex_connection_type == TPNconnected1N)
00975 {
00976 Vs = parNode->voltage[0]/parNode->nominal_voltage;
00977 ws = parNode->curr_freq_state.fmeas[0]*2.0*PI;
00978 }
00979 else if (triplex_connection_type == TPNconnected2N)
00980 {
00981 Vs = parNode->voltage[1]/parNode->nominal_voltage;
00982 ws = parNode->curr_freq_state.fmeas[1]*2.0*PI;
00983 }
00984 else
00985 {
00986 Vs = parNode->voltaged[0]/(2.0*parNode->nominal_voltage);
00987 ws = parNode->curr_freq_state.fmeas[0]*2.0*PI;
00988 }
00989 }
00990 else
00991 {
00992 Vs = parNode->voltage[connected_phase]/parNode->nominal_voltage;
00993 ws = parNode->curr_freq_state.fmeas[connected_phase]*2.0*PI;
00994 }
00995 }
00996 else
00997 {
00998 if (triplex_connected == true)
00999 {
01000
01001 if (triplex_connection_type == TPNconnected1N)
01002 {
01003 Vs = voltage[0]/nominal_voltage;
01004 ws = curr_freq_state.fmeas[0]*2.0*PI;
01005 }
01006 else if (triplex_connection_type == TPNconnected2N)
01007 {
01008 Vs = voltage[1]/nominal_voltage;
01009 ws = curr_freq_state.fmeas[1]*2.0*PI;
01010 }
01011 else
01012 {
01013 Vs = voltaged[0]/(2.0*nominal_voltage);
01014 ws = curr_freq_state.fmeas[0]*2.0*PI;
01015 }
01016 }
01017 else
01018 {
01019 Vs = voltage[connected_phase]/nominal_voltage;
01020 ws = curr_freq_state.fmeas[connected_phase]*2.0*PI;
01021 }
01022 }
01023
01024
01025 ws_pu = ws/wbase;
01026 }
01027 else
01028 {
01029 if ( (SubNode == CHILD) || (SubNode == DIFF_CHILD) )
01030 {
01031 node *parNode = OBJECTDATA(SubNodeParent,node);
01032
01033 Vas = parNode->voltage[0]/parNode->nominal_voltage;
01034 Vbs = parNode->voltage[1]/parNode->nominal_voltage;
01035 Vcs = parNode->voltage[2]/parNode->nominal_voltage;
01036
01037 ws_pu = (parNode->curr_freq_state.fmeas[0]+ parNode->curr_freq_state.fmeas[1] + parNode->curr_freq_state.fmeas[2]) / nominal_frequency / 3.0;
01038 }
01039 else
01040 {
01041 Vas = voltage[0]/nominal_voltage;
01042 Vbs = voltage[1]/nominal_voltage;
01043 Vcs = voltage[2]/nominal_voltage;
01044 ws_pu = (curr_freq_state.fmeas[0] + curr_freq_state.fmeas[1] + curr_freq_state.fmeas[2]) / nominal_frequency / 3.0;
01045 }
01046
01047
01048 ws = ws_pu * wbase;
01049 }
01050 }
01051
01052
01053 void motor::SPIMupdateVars() {
01054 wr_prev = wr;
01055 Telec_prev = Telec;
01056 psi_dr_prev = psi_dr;
01057 psi_qr_prev = psi_qr;
01058 psi_f_prev = psi_f;
01059 psi_b_prev = psi_b;
01060 Iqs_prev = Iqs;
01061 Ids_prev =Ids;
01062 If_prev = If;
01063 Ib_prev = Ib;
01064 Is_prev = Is;
01065 motor_elec_power_prev = motor_elec_power;
01066 reconnect_prev = reconnect;
01067 motor_trip_prev = motor_trip;
01068 trip_prev = trip;
01069 psi_sat_prev = psi_sat;
01070 }
01071
01072
01073
01074 void motor::TPIMupdateVars() {
01075 phips_prev = phips;
01076 phins_cj_prev = phins_cj;
01077 phipr_prev = phipr;
01078 phinr_cj_prev = phinr_cj;
01079 wr_pu_prev = wr_pu;
01080 Ips_prev = Ips;
01081 Ipr_prev = Ipr;
01082 Ins_cj_prev = Ins_cj;
01083 Inr_cj_prev = Inr_cj;
01084
01085 reconnect_prev = reconnect;
01086 motor_trip_prev = motor_trip;
01087 trip_prev = trip;
01088
01089 }
01090
01091
01092 void motor::SPIMreinitializeVars() {
01093 wr = wr_prev;
01094 Telec = Telec_prev;
01095 psi_dr = psi_dr_prev;
01096 psi_qr = psi_qr_prev;
01097 psi_f = psi_f_prev;
01098 psi_b = psi_b_prev;
01099 Iqs = Iqs_prev;
01100 Ids =Ids_prev;
01101 If = If_prev;
01102 Ib = Ib_prev;
01103 Is = Is_prev;
01104 motor_elec_power = motor_elec_power_prev;
01105 reconnect = reconnect_prev;
01106 motor_trip = motor_trip_prev;
01107 trip = trip_prev;
01108 psi_sat = psi_sat_prev;
01109 }
01110
01111
01112 void motor::TPIMreinitializeVars() {
01113 phips = phips_prev;
01114 phins_cj = phins_cj_prev;
01115 phipr = phipr_prev;
01116 phinr_cj = phinr_cj_prev;
01117 wr_pu = wr_pu_prev;
01118 Ips = Ips_prev;
01119 Ipr = Ipr_prev;
01120 Ins_cj = Ins_cj_prev;
01121 Inr_cj = Inr_cj_prev;
01122
01123 reconnect = reconnect_prev;
01124 motor_trip = motor_trip_prev;
01125 trip = trip_prev;
01126
01127 }
01128
01129
01130 void motor::SPIMUpdateMotorStatus() {
01131 if (motor_override == overrideOFF || ws <= 1 || Vs.Mag() <= 0.1)
01132 {
01133 motor_status = statusOFF;
01134 }
01135 else if (wr > 1) {
01136 motor_status = statusRUNNING;
01137 }
01138 else if (motor_trip == 1) {
01139 motor_status = statusTRIPPED;
01140 }
01141 else {
01142 motor_status = statusSTALLED;
01143 }
01144 }
01145
01146
01147 void motor::TPIMUpdateMotorStatus() {
01148 if (motor_override == overrideOFF || ws_pu <= 0.1 ||
01149 Vas.Mag() <= 0.1 || Vbs.Mag() <= 0.1 || Vcs.Mag() <= 0.1) {
01150 motor_status = statusOFF;
01151 }
01152 else if (wr_pu > 0.0) {
01153 motor_status = statusRUNNING;
01154 }
01155 else if (motor_trip == 1) {
01156 motor_status = statusTRIPPED;
01157 }
01158 else {
01159 motor_status = statusSTALLED;
01160 }
01161 }
01162
01163
01164 void motor::SPIMUpdateProtection(double delta_time) {
01165 if (motor_override == overrideON) {
01166 if (wr < 1 && motor_trip == 0 && ws > 1 && Vs.Mag() > 0.1) {
01167 trip = trip + delta_time;
01168 }
01169 else if ( (wr >= 1 && motor_trip == 0) || ws <= 1 || Vs.Mag() <= 0.1) {
01170 trip = trip - (delta_time / (reconnect_time/trip_time)) < 0 ? 0 : trip - (delta_time / (reconnect_time/trip_time));
01171 }
01172
01173
01174 if (uv_lockout == 0) {
01175 if (Vs.Mag() <= uv_relay_trip_V && Vs.Mag() > 0.01 && uv_relay_install == uv_relay_INSTALLED) {
01176 if (uv_relay_time <= uv_relay_trip_time) {
01177 uv_relay_time = uv_relay_time + delta_time;
01178 uv_lockout = 0;
01179 }
01180 else {
01181 motor_override = overrideOFF;
01182 uv_lockout = 1;
01183 }
01184 } else {
01185 uv_relay_time = 0;
01186 }
01187 }
01188
01189
01190
01191 if (Vs.Mag() <= contactor_open_Vmin && uv_lockout == 0 && contactor_state == contactorCLOSED) {
01192
01193 motor_override = overrideOFF;
01194 contactor_state = contactorOPEN;
01195 }
01196
01197 }
01198 else {
01199 trip = trip - (delta_time / (reconnect_time/trip_time)) < 0 ? 0 : trip - (delta_time / (reconnect_time/trip_time));
01200 }
01201
01202 if (motor_trip == 1) {
01203 reconnect = reconnect + delta_time;
01204 }
01205
01206 if (trip >= trip_time) {
01207 motor_trip = 1;
01208 trip = 0;
01209 }
01210 if (reconnect >= reconnect_time) {
01211 motor_trip = 0;
01212 reconnect = 0;
01213 }
01214
01215 if (Vs.Mag() >= contactor_close_Vmax && uv_lockout == 0 && contactor_state == contactorOPEN ){
01216
01217 motor_override = overrideON;
01218 contactor_state = contactorCLOSED;
01219 }
01220 }
01221
01222
01223 void motor::TPIMUpdateProtection(double delta_time) {
01224 if (motor_override == overrideON) {
01225 if (wr_pu < 0.01 && motor_trip == 0 && ws_pu > 0.1 && Vas.Mag() > 0.1 && Vbs.Mag() > 0.1 && Vcs.Mag() > 0.1) {
01226 trip = trip + delta_time;
01227 }
01228 else if ( (wr_pu >= 0.01 && motor_trip == 0) || ws_pu <= 0.1 || Vas.Mag() <= 0.1 || Vbs.Mag() <= 0.1 || Vcs.Mag() <= 0.1) {
01229 trip = trip - (delta_time / (reconnect_time/trip_time)) < 0 ? 0 : trip - (delta_time / (reconnect_time/trip_time));
01230 }
01231
01232
01233 if (uv_lockout == 0) {
01234 if (((Vas.Mag() <= uv_relay_trip_V && Vas.Mag() > 0.001) || (Vbs.Mag() <= uv_relay_trip_V && Vbs.Mag() > 0.001) || (Vcs.Mag() <= uv_relay_trip_V) && Vcs.Mag() > 0.001) && uv_relay_install == uv_relay_INSTALLED) {
01235 if (uv_relay_time <= uv_relay_trip_time) {
01236
01237 uv_relay_time = uv_relay_time + delta_time;
01238 uv_lockout = 0;
01239 }
01240 else {
01241
01242 motor_override = overrideOFF;
01243 uv_lockout = 1;
01244 }
01245 } else {
01246
01247 uv_relay_time = 0;
01248 }
01249 }
01250
01251
01252 if ((Vas.Mag() <= contactor_open_Vmin || Vbs.Mag() <= contactor_open_Vmin || Vcs.Mag() <= contactor_open_Vmin) && uv_lockout == 0 && contactor_state == contactorCLOSED) {
01253
01254 motor_override = overrideOFF;
01255 contactor_state = contactorOPEN;
01256 }
01257 }
01258 else {
01259 trip = trip - (delta_time / (reconnect_time/trip_time)) < 0 ? 0 : trip - (delta_time / (reconnect_time/trip_time));
01260 }
01261
01262 if (motor_trip == 1) {
01263 reconnect = reconnect + delta_time;
01264 }
01265
01266 if (trip >= trip_time) {
01267 motor_trip = 1;
01268 trip = 0;
01269 }
01270 if (reconnect >= reconnect_time) {
01271 motor_trip = 0;
01272 reconnect = 0;
01273 }
01274
01275
01276 if ((Vas.Mag() >= contactor_close_Vmax && Vbs.Mag() >= contactor_close_Vmax && Vcs.Mag() >= contactor_close_Vmax ) && uv_lockout == 0 && contactor_state == contactorOPEN ){
01277
01278 motor_override = overrideON;
01279 contactor_state = contactorCLOSED;
01280 }
01281 }
01282
01283
01284 void motor::SPIMStateOFF() {
01285 psi_b = complex(0.0,0.0);
01286 psi_f = complex(0.0,0.0);
01287 psi_dr = complex(0.0,0.0);
01288 psi_qr = complex(0.0,0.0);
01289 Ids = complex(0.0,0.0);
01290 Iqs = complex(0.0,0.0);
01291 If = complex(0.0,0.0);
01292 Ib = complex(0.0,0.0);
01293 Is = complex(0.0,0.0);
01294 motor_elec_power = complex(0.0,0.0);
01295 Telec = 0.0;
01296 wr = 0.0;
01297 wr_pu = 0.0;
01298 }
01299
01300
01301 void motor::TPIMStateOFF() {
01302 phips = complex(0.0,0.0);
01303 phins_cj = complex(0.0,0.0);
01304 phipr = complex(0.0,0.0);
01305 phinr_cj = complex(0.0,0.0);
01306 wr = 0.0;
01307 wr_pu = 0.0;
01308 Ips = complex(0.0,0.0);
01309 Ipr = complex(0.0,0.0);
01310 Ins_cj = complex(0.0,0.0);
01311 Inr_cj = complex(0.0,0.0);
01312 motor_elec_power = complex(0.0,0.0);
01313 Telec = 0.0;
01314 Tmech_eff = 0.0;
01315 }
01316
01317
01318 void motor::SPIMSteadyState(TIMESTAMP t1) {
01319 double wr_delta = 1;
01320 psi_sat = 1;
01321 double psi = -1;
01322 int32 count = 1;
01323 double Xc = -1;
01324
01325 while (fabs(wr_delta) > speed_error && count < iteration_count) {
01326 count++;
01327
01328
01329 if (wr < cap_run_speed) {
01330 Xc = Xc2;
01331 }
01332 else {
01333 Xc = Xc1;
01334 }
01335
01336 TF[0] = (complex(0.0,1.0)*Xd_prime*ws_pu) + Rds;
01337 TF[1] = 0;
01338 TF[2] = (complex(0.0,1.0)*Xm*ws_pu)/Xr;
01339 TF[3] = (complex(0.0,1.0)*Xm*ws_pu)/Xr;
01340 TF[4] = 0;
01341 TF[5] = (complex(0.0,1.0)*Xc)/ws_pu + (complex(0.0,1.0)*Xq_prime*ws_pu) + Rqs;
01342 TF[6] = -(Xm*n*ws_pu)/Xr;
01343 TF[7] = (Xm*n*ws_pu)/Xr;
01344 TF[8] = Xm/2;
01345 TF[9] = -(complex(0.0,1.0)*Xm*n)/2;
01346 TF[10] = (complex(0.0,1.0)*wr - complex(0.0,1.0)*ws)*To_prime -psi_sat;
01347 TF[11] = 0;
01348 TF[12] = Xm/2;
01349 TF[13] = (complex(0.0,1.0)*Xm*n)/2;
01350 TF[14] = 0;
01351 TF[15] = (complex(0.0,1.0)*wr + complex(0.0,1.0)*ws)*-To_prime -psi_sat ;
01352
01353
01354 invertMatrix(TF,ITF);
01355 Ids = ITF[0]*Vs.Mag() + ITF[1]*Vs.Mag();
01356 Iqs = ITF[4]*Vs.Mag() + ITF[5]*Vs.Mag();
01357 psi_f = ITF[8]*Vs.Mag() + ITF[9]*Vs.Mag();
01358 psi_b = ITF[12]*Vs.Mag() + ITF[13]*Vs.Mag();
01359 If = (Ids-(complex(0.0,1.0)*n*Iqs))*0.5;
01360 Ib = (Ids+(complex(0.0,1.0)*n*Iqs))*0.5;
01361
01362
01363 Telec = (Xm/Xr)*2.0*(If.Im()*psi_f.Re() - If.Re()*psi_f.Im() - Ib.Im()*psi_b.Re() + Ib.Re()*psi_b.Im());
01364
01365
01366 wr_delta = Telec-Tmech;
01367
01368
01369 psi = sqrt(pow(psi_f.Re(),2)+pow(psi_f.Im(),2)+pow(psi_b.Re(),2)+pow(psi_b.Im(),2));
01370 if(psi<=bsat) {
01371 psi_sat = 1;
01372 }
01373 else {
01374 psi_sat = 1 + Asat*(pow(psi-bsat,2));
01375 }
01376
01377
01378 if (wr+wr_delta > 0) {
01379 wr = wr+wr_delta;
01380 wr_pu = wr/wbase;
01381 }
01382 else {
01383 wr = 0;
01384 wr_pu = 0.0;
01385 }
01386 }
01387
01388 psi_dr = psi_f + psi_b;
01389 psi_qr = complex(0.0,1.0)*psi_f + complex(0,-1)*psi_b;
01390
01391 Is = (Ids + Iqs)*complex_exp(Vs.Arg());
01392 motor_elec_power = (Vs*~Is) * Pbase;
01393 }
01394
01395
01396
01397 void motor::TPIMSteadyState(TIMESTAMP t1) {
01398 double omgr0_delta = 1;
01399 int32 count = 1;
01400 complex alpha = complex(0.0,0.0);
01401 complex A1, A2, A3, A4;
01402 complex B1, B2, B3, B4;
01403 complex C1, C2, C3, C4;
01404 complex D1, D2, D3, D4;
01405 complex E1, E2, E3, E4;
01406 complex Vap;
01407 complex Van;
01408
01409
01410 alpha = complex_exp(2.0/3.0 * PI);
01411
01412 Vap = (Vas + alpha * Vbs + alpha * alpha * Vcs) / 3.0;
01413 Van = (Vas + alpha * alpha * Vbs + alpha * Vcs) / 3.0;
01414
01415
01416
01417
01418 if (motor_status == statusRUNNING){
01419
01420 while (fabs(omgr0_delta) > speed_error && count < iteration_count) {
01421 count++;
01422
01423
01424 A1 = -(complex(0.0,1.0) * ws_pu + rs_pu / sigma1) ;
01425 B1 = 0.0 ;
01426 C1 = rs_pu / sigma1 * lm / Lr ;
01427 D1 = 0.0 ;
01428 E1 = Vap ;
01429
01430 A2 = 0.0;
01431 B2 = -(complex(0.0,-1.0) * ws_pu + rs_pu / sigma1) ;
01432 C2 = 0.0 ;
01433 D2 = rs_pu / sigma1 * lm / Lr ;
01434 E2 = ~Van ;
01435
01436 A3 = rr_pu / sigma2 * lm / Ls ;
01437 B3 = 0.0 ;
01438 C3 = -(complex(0.0,1.0) * (ws_pu - wr_pu) + rr_pu / sigma2) ;
01439 D3 = 0.0 ;
01440 E3 = 0.0 ;
01441
01442 A4 = 0.0 ;
01443 B4 = rr_pu / sigma2 * lm / Ls ;
01444 C4 = 0.0 ;
01445 D4 = -(complex(0.0,1.0) * (-ws_pu - wr_pu) + rr_pu / sigma2) ;
01446 E4 = 0.0 ;
01447
01448
01449 phips = (B1*C2*D3*E4 - B1*C2*D4*E3 - B1*C3*D2*E4 + B1*C3*D4*E2 + B1*C4*D2*E3
01450 - B1*C4*D3*E2 - B2*C1*D3*E4 + B2*C1*D4*E3 + B2*C3*D1*E4 - B2*C3*D4*E1
01451 - B2*C4*D1*E3 + B2*C4*D3*E1 + B3*C1*D2*E4 - B3*C1*D4*E2 - B3*C2*D1*E4
01452 + B3*C2*D4*E1 + B3*C4*D1*E2 - B3*C4*D2*E1 - B4*C1*D2*E3 + B4*C1*D3*E2
01453 + B4*C2*D1*E3 - B4*C2*D3*E1 - B4*C3*D1*E2 + B4*C3*D2*E1)/
01454 (A1*B2*C3*D4 - A1*B2*C4*D3 - A1*B3*C2*D4 + A1*B3*C4*D2 + A1*B4*C2*D3 -
01455 A1*B4*C3*D2 - A2*B1*C3*D4 + A2*B1*C4*D3 + A2*B3*C1*D4 - A2*B3*C4*D1 -
01456 A2*B4*C1*D3 + A2*B4*C3*D1 + A3*B1*C2*D4 - A3*B1*C4*D2 - A3*B2*C1*D4 +
01457 A3*B2*C4*D1 + A3*B4*C1*D2 - A3*B4*C2*D1 - A4*B1*C2*D3 + A4*B1*C3*D2 +
01458 A4*B2*C1*D3 - A4*B2*C3*D1 - A4*B3*C1*D2 + A4*B3*C2*D1) ;
01459
01460 phins_cj = -(A1*C2*D3*E4 - A1*C2*D4*E3 - A1*C3*D2*E4 + A1*C3*D4*E2 + A1*C4*D2*E3
01461 - A1*C4*D3*E2 - A2*C1*D3*E4 + A2*C1*D4*E3 + A2*C3*D1*E4 - A2*C3*D4*E1
01462 - A2*C4*D1*E3 + A2*C4*D3*E1 + A3*C1*D2*E4 - A3*C1*D4*E2 - A3*C2*D1*E4
01463 + A3*C2*D4*E1 + A3*C4*D1*E2 - A3*C4*D2*E1 - A4*C1*D2*E3 + A4*C1*D3*E2
01464 + A4*C2*D1*E3 - A4*C2*D3*E1 - A4*C3*D1*E2 + A4*C3*D2*E1)/
01465 (A1*B2*C3*D4 - A1*B2*C4*D3 - A1*B3*C2*D4 + A1*B3*C4*D2 + A1*B4*C2*D3 -
01466 A1*B4*C3*D2 - A2*B1*C3*D4 + A2*B1*C4*D3 + A2*B3*C1*D4 - A2*B3*C4*D1 -
01467 A2*B4*C1*D3 + A2*B4*C3*D1 + A3*B1*C2*D4 - A3*B1*C4*D2 - A3*B2*C1*D4 +
01468 A3*B2*C4*D1 + A3*B4*C1*D2 - A3*B4*C2*D1 - A4*B1*C2*D3 + A4*B1*C3*D2 +
01469 A4*B2*C1*D3 - A4*B2*C3*D1 - A4*B3*C1*D2 + A4*B3*C2*D1) ;
01470
01471 phipr = (A1*B2*D3*E4 - A1*B2*D4*E3 - A1*B3*D2*E4 + A1*B3*D4*E2 + A1*B4*D2*E3
01472 - A1*B4*D3*E2 - A2*B1*D3*E4 + A2*B1*D4*E3 + A2*B3*D1*E4 - A2*B3*D4*E1
01473 - A2*B4*D1*E3 + A2*B4*D3*E1 + A3*B1*D2*E4 - A3*B1*D4*E2 - A3*B2*D1*E4
01474 + A3*B2*D4*E1 + A3*B4*D1*E2 - A3*B4*D2*E1 - A4*B1*D2*E3 + A4*B1*D3*E2
01475 + A4*B2*D1*E3 - A4*B2*D3*E1 - A4*B3*D1*E2 + A4*B3*D2*E1)/
01476 (A1*B2*C3*D4 - A1*B2*C4*D3 - A1*B3*C2*D4 + A1*B3*C4*D2 + A1*B4*C2*D3 -
01477 A1*B4*C3*D2 - A2*B1*C3*D4 + A2*B1*C4*D3 + A2*B3*C1*D4 - A2*B3*C4*D1 -
01478 A2*B4*C1*D3 + A2*B4*C3*D1 + A3*B1*C2*D4 - A3*B1*C4*D2 - A3*B2*C1*D4 +
01479 A3*B2*C4*D1 + A3*B4*C1*D2 - A3*B4*C2*D1 - A4*B1*C2*D3 + A4*B1*C3*D2 +
01480 A4*B2*C1*D3 - A4*B2*C3*D1 - A4*B3*C1*D2 + A4*B3*C2*D1) ;
01481
01482 phinr_cj = -(A1*B2*C3*E4 - A1*B2*C4*E3 - A1*B3*C2*E4 + A1*B3*C4*E2 + A1*B4*C2*E3
01483 - A1*B4*C3*E2 - A2*B1*C3*E4 + A2*B1*C4*E3 + A2*B3*C1*E4 - A2*B3*C4*E1
01484 - A2*B4*C1*E3 + A2*B4*C3*E1 + A3*B1*C2*E4 - A3*B1*C4*E2 - A3*B2*C1*E4
01485 + A3*B2*C4*E1 + A3*B4*C1*E2 - A3*B4*C2*E1 - A4*B1*C2*E3 + A4*B1*C3*E2
01486 + A4*B2*C1*E3 - A4*B2*C3*E1 - A4*B3*C1*E2 + A4*B3*C2*E1)/
01487 (A1*B2*C3*D4 - A1*B2*C4*D3 - A1*B3*C2*D4 + A1*B3*C4*D2 + A1*B4*C2*D3 -
01488 A1*B4*C3*D2 - A2*B1*C3*D4 + A2*B1*C4*D3 + A2*B3*C1*D4 - A2*B3*C4*D1 -
01489 A2*B4*C1*D3 + A2*B4*C3*D1 + A3*B1*C2*D4 - A3*B1*C4*D2 - A3*B2*C1*D4 +
01490 A3*B2*C4*D1 + A3*B4*C1*D2 - A3*B4*C2*D1 - A4*B1*C2*D3 + A4*B1*C3*D2 +
01491 A4*B2*C1*D3 - A4*B2*C3*D1 - A4*B3*C1*D2 + A4*B3*C2*D1) ;
01492
01493 Ips = (phips - phipr * lm / Lr) / sigma1;
01494 Ipr = (phipr - phips * lm / Ls) / sigma2;
01495 Ins_cj = (phins_cj - phinr_cj * lm / Lr) / sigma1;
01496 Inr_cj = (phinr_cj - phins_cj * lm / Ls) / sigma2;
01497 Telec = (~phips * Ips + ~phins_cj * Ins_cj).Im() ;
01498
01499
01500
01501 omgr0_delta = ( Telec - Tmech_eff ) / ((double)iteration_count);
01502
01503
01504 if (wr_pu + omgr0_delta > -10) {
01505 wr_pu = wr_pu + omgr0_delta;
01506 wr = wr_pu * wbase;
01507 }
01508 else {
01509 wr_pu = -10;
01510 wr = wr_pu * wbase;
01511 }
01512
01513 }
01514
01515 }
01516 else
01517 {
01518 wr_pu = 0.0;
01519 wr = 0.0;
01520
01521
01522 A1 = -(complex(0.0,1.0) * ws_pu + rs_pu / sigma1) ;
01523 B1 = 0.0 ;
01524 C1 = rs_pu / sigma1 * lm / Lr ;
01525 D1 = 0.0 ;
01526 E1 = Vap ;
01527
01528 A2 = 0.0;
01529 B2 = -(complex(0.0,-1.0) * ws_pu + rs_pu / sigma1) ;
01530 C2 = 0.0 ;
01531 D2 = rs_pu / sigma1 * lm / Lr ;
01532 E2 = ~Van ;
01533
01534 A3 = rr_pu / sigma2 * lm / Ls ;
01535 B3 = 0.0 ;
01536 C3 = -(complex(0.0,1.0) * (ws_pu - wr_pu) + rr_pu / sigma2) ;
01537 D3 = 0.0 ;
01538 E3 = 0.0 ;
01539
01540 A4 = 0.0 ;
01541 B4 = rr_pu / sigma2 * lm / Ls ;
01542 C4 = 0.0 ;
01543 D4 = -(complex(0.0,1.0) * (-ws_pu - wr_pu) + rr_pu / sigma2) ;
01544 E4 = 0.0 ;
01545
01546
01547 phips = (B1*C2*D3*E4 - B1*C2*D4*E3 - B1*C3*D2*E4 + B1*C3*D4*E2 + B1*C4*D2*E3
01548 - B1*C4*D3*E2 - B2*C1*D3*E4 + B2*C1*D4*E3 + B2*C3*D1*E4 - B2*C3*D4*E1
01549 - B2*C4*D1*E3 + B2*C4*D3*E1 + B3*C1*D2*E4 - B3*C1*D4*E2 - B3*C2*D1*E4
01550 + B3*C2*D4*E1 + B3*C4*D1*E2 - B3*C4*D2*E1 - B4*C1*D2*E3 + B4*C1*D3*E2
01551 + B4*C2*D1*E3 - B4*C2*D3*E1 - B4*C3*D1*E2 + B4*C3*D2*E1)/
01552 (A1*B2*C3*D4 - A1*B2*C4*D3 - A1*B3*C2*D4 + A1*B3*C4*D2 + A1*B4*C2*D3 -
01553 A1*B4*C3*D2 - A2*B1*C3*D4 + A2*B1*C4*D3 + A2*B3*C1*D4 - A2*B3*C4*D1 -
01554 A2*B4*C1*D3 + A2*B4*C3*D1 + A3*B1*C2*D4 - A3*B1*C4*D2 - A3*B2*C1*D4 +
01555 A3*B2*C4*D1 + A3*B4*C1*D2 - A3*B4*C2*D1 - A4*B1*C2*D3 + A4*B1*C3*D2 +
01556 A4*B2*C1*D3 - A4*B2*C3*D1 - A4*B3*C1*D2 + A4*B3*C2*D1) ;
01557
01558 phins_cj = -(A1*C2*D3*E4 - A1*C2*D4*E3 - A1*C3*D2*E4 + A1*C3*D4*E2 + A1*C4*D2*E3
01559 - A1*C4*D3*E2 - A2*C1*D3*E4 + A2*C1*D4*E3 + A2*C3*D1*E4 - A2*C3*D4*E1
01560 - A2*C4*D1*E3 + A2*C4*D3*E1 + A3*C1*D2*E4 - A3*C1*D4*E2 - A3*C2*D1*E4
01561 + A3*C2*D4*E1 + A3*C4*D1*E2 - A3*C4*D2*E1 - A4*C1*D2*E3 + A4*C1*D3*E2
01562 + A4*C2*D1*E3 - A4*C2*D3*E1 - A4*C3*D1*E2 + A4*C3*D2*E1)/
01563 (A1*B2*C3*D4 - A1*B2*C4*D3 - A1*B3*C2*D4 + A1*B3*C4*D2 + A1*B4*C2*D3 -
01564 A1*B4*C3*D2 - A2*B1*C3*D4 + A2*B1*C4*D3 + A2*B3*C1*D4 - A2*B3*C4*D1 -
01565 A2*B4*C1*D3 + A2*B4*C3*D1 + A3*B1*C2*D4 - A3*B1*C4*D2 - A3*B2*C1*D4 +
01566 A3*B2*C4*D1 + A3*B4*C1*D2 - A3*B4*C2*D1 - A4*B1*C2*D3 + A4*B1*C3*D2 +
01567 A4*B2*C1*D3 - A4*B2*C3*D1 - A4*B3*C1*D2 + A4*B3*C2*D1) ;
01568
01569 phipr = (A1*B2*D3*E4 - A1*B2*D4*E3 - A1*B3*D2*E4 + A1*B3*D4*E2 + A1*B4*D2*E3
01570 - A1*B4*D3*E2 - A2*B1*D3*E4 + A2*B1*D4*E3 + A2*B3*D1*E4 - A2*B3*D4*E1
01571 - A2*B4*D1*E3 + A2*B4*D3*E1 + A3*B1*D2*E4 - A3*B1*D4*E2 - A3*B2*D1*E4
01572 + A3*B2*D4*E1 + A3*B4*D1*E2 - A3*B4*D2*E1 - A4*B1*D2*E3 + A4*B1*D3*E2
01573 + A4*B2*D1*E3 - A4*B2*D3*E1 - A4*B3*D1*E2 + A4*B3*D2*E1)/
01574 (A1*B2*C3*D4 - A1*B2*C4*D3 - A1*B3*C2*D4 + A1*B3*C4*D2 + A1*B4*C2*D3 -
01575 A1*B4*C3*D2 - A2*B1*C3*D4 + A2*B1*C4*D3 + A2*B3*C1*D4 - A2*B3*C4*D1 -
01576 A2*B4*C1*D3 + A2*B4*C3*D1 + A3*B1*C2*D4 - A3*B1*C4*D2 - A3*B2*C1*D4 +
01577 A3*B2*C4*D1 + A3*B4*C1*D2 - A3*B4*C2*D1 - A4*B1*C2*D3 + A4*B1*C3*D2 +
01578 A4*B2*C1*D3 - A4*B2*C3*D1 - A4*B3*C1*D2 + A4*B3*C2*D1) ;
01579
01580 phinr_cj = -(A1*B2*C3*E4 - A1*B2*C4*E3 - A1*B3*C2*E4 + A1*B3*C4*E2 + A1*B4*C2*E3
01581 - A1*B4*C3*E2 - A2*B1*C3*E4 + A2*B1*C4*E3 + A2*B3*C1*E4 - A2*B3*C4*E1
01582 - A2*B4*C1*E3 + A2*B4*C3*E1 + A3*B1*C2*E4 - A3*B1*C4*E2 - A3*B2*C1*E4
01583 + A3*B2*C4*E1 + A3*B4*C1*E2 - A3*B4*C2*E1 - A4*B1*C2*E3 + A4*B1*C3*E2
01584 + A4*B2*C1*E3 - A4*B2*C3*E1 - A4*B3*C1*E2 + A4*B3*C2*E1)/
01585 (A1*B2*C3*D4 - A1*B2*C4*D3 - A1*B3*C2*D4 + A1*B3*C4*D2 + A1*B4*C2*D3 -
01586 A1*B4*C3*D2 - A2*B1*C3*D4 + A2*B1*C4*D3 + A2*B3*C1*D4 - A2*B3*C4*D1 -
01587 A2*B4*C1*D3 + A2*B4*C3*D1 + A3*B1*C2*D4 - A3*B1*C4*D2 - A3*B2*C1*D4 +
01588 A3*B2*C4*D1 + A3*B4*C1*D2 - A3*B4*C2*D1 - A4*B1*C2*D3 + A4*B1*C3*D2 +
01589 A4*B2*C1*D3 - A4*B2*C3*D1 - A4*B3*C1*D2 + A4*B3*C2*D1) ;
01590
01591 Ips = (phips - phipr * lm / Lr) / sigma1;
01592 Ipr = (phipr - phips * lm / Ls) / sigma2;
01593 Ins_cj = (phins_cj - phinr_cj * lm / Lr) / sigma1;
01594 Inr_cj = (phinr_cj - phins_cj * lm / Ls) / sigma2;
01595 Telec = (~phips * Ips + ~phins_cj * Ins_cj).Im() ;
01596 }
01597
01598
01599 Ias = Ips + ~Ins_cj ;
01600 Ibs = alpha * alpha * Ips + alpha * ~Ins_cj ;
01601 Ics = alpha * Ips + alpha * alpha * ~Ins_cj ;
01602
01603 motor_elec_power = (Vap * ~Ips + Van * Ins_cj) * Pbase;
01604
01605 }
01606
01607
01608 void motor::SPIMDynamic(double curr_delta_time, double dTime) {
01609 double psi = -1;
01610 double Xc = -1;
01611
01612
01613 if (wr < cap_run_speed) {
01614 Xc = Xc2;
01615 }
01616 else {
01617 Xc = Xc1;
01618 }
01619
01620
01621 psi_b = (Ib*Xm) / ((complex(0.0,1.0)*(ws+wr)*To_prime)+psi_sat);
01622 psi_f = psi_f + ( If*(Xm/To_prime) - (complex(0.0,1.0)*(ws-wr) + psi_sat/To_prime)*psi_f )*dTime;
01623
01624
01625 psi = sqrt(psi_f.Re()*psi_f.Re() + psi_f.Im()*psi_f.Im() + psi_b.Re()*psi_b.Re() + psi_b.Im()*psi_b.Im());
01626 if(psi<=bsat) {
01627 psi_sat = 1;
01628 }
01629 else {
01630 psi_sat = 1 + Asat*((psi-bsat)*(psi-bsat));
01631 }
01632
01633
01634 psi_dr = psi_f + psi_b;
01635 psi_qr = complex(0.0,1.0)*psi_f + complex(0,-1)*psi_b;
01636
01637
01638 Ids = (-(complex(0.0,1.0)*ws_pu*(Xm/Xr)*psi_dr) + Vs.Mag()) / ((complex(0.0,1.0)*ws_pu*Xd_prime)+Rds);
01639 Iqs = (-(complex(0.0,1.0)*ws_pu*(n*Xm/Xr)*psi_qr) + Vs.Mag()) / ((complex(0.0,1.0)*ws_pu*Xq_prime)+(complex(0.0,1.0)/ws_pu*Xc)+Rqs);
01640
01641
01642 If = (Ids-(complex(0.0,1.0)*n*Iqs))*0.5;
01643 Ib = (Ids+(complex(0.0,1.0)*n*Iqs))*0.5;
01644
01645
01646 Is = (Ids + Iqs)*complex_exp(Vs.Arg());
01647 motor_elec_power = (Vs*~Is) * Pbase;
01648
01649
01650 Telec = (Xm/Xr)*2*(If.Im()*psi_f.Re() - If.Re()*psi_f.Im() - Ib.Im()*psi_b.Re() + Ib.Re()*psi_b.Im());
01651
01652
01653 wr = wr + (((Telec-Tmech)*wbase)/(2*H))*dTime;
01654
01655
01656 if (wr < 0) {
01657 wr = 0;
01658 }
01659
01660
01661 wr_pu = wr / wbase;
01662 }
01663
01664
01665 void motor::TPIMDynamic(double curr_delta_time, double dTime) {
01666 complex alpha = complex(0.0,0.0);
01667 complex Vap;
01668 complex Van;
01669
01670
01671 complex A1p, C1p;
01672 complex B2p, D2p;
01673 complex A3p, C3p;
01674 complex B4p, D4p;
01675 complex dphips_prev_dt ;
01676 complex dphins_cj_prev_dt ;
01677 complex dphipr_prev_dt ;
01678 complex dphinr_cj_prev_dt ;
01679 complex domgr0_prev_dt ;
01680
01681
01682 complex A1c, C1c;
01683 complex B2c, D2c;
01684 complex A3c, C3c;
01685 complex B4c, D4c;
01686 complex dphips_dt ;
01687 complex dphins_cj_dt ;
01688 complex dphipr_dt ;
01689 complex dphinr_cj_dt ;
01690 complex domgr0_dt ;
01691
01692 alpha = complex_exp(2.0/3.0 * PI);
01693
01694 Vap = (Vas + alpha * Vbs + alpha * alpha * Vcs) / 3.0;
01695 Van = (Vas + alpha * alpha * Vbs + alpha * Vcs) / 3.0;
01696
01697 TPIMupdateVars();
01698
01699 if (wr_pu >= 1.0)
01700 {
01701 Tmech_eff = Tmech;
01702 }
01703
01704
01705
01706 A1p = -(complex(0.0,1.0) * ws_pu + rs_pu / sigma1) ;
01707 C1p = rs_pu / sigma1 * lm / Lr ;
01708
01709 B2p = -(complex(0.0,-1.0) * ws_pu + rs_pu / sigma1) ;
01710 D2p = rs_pu / sigma1 *lm / Lr ;
01711
01712 A3p = rr_pu / sigma2 * lm / Ls ;
01713 C3p = -(complex(0.0,1.0) * (ws_pu - wr_pu_prev) + rr_pu / sigma2) ;
01714
01715 B4p = rr_pu / sigma2 * lm / Ls ;
01716 D4p = -(complex(0.0,1.0) * (-ws_pu - wr_pu_prev) + rr_pu / sigma2) ;
01717
01718
01719 dphips_prev_dt = ( Vap + A1p * phips_prev + C1p * phipr_prev ) * wbase;
01720 dphins_cj_prev_dt = ( ~Van + B2p * phins_cj_prev + D2p * phinr_cj_prev ) * wbase;
01721 dphipr_prev_dt = ( C3p * phipr_prev + A3p * phips_prev ) * wbase;
01722 dphinr_cj_prev_dt = ( D4p * phinr_cj_prev + B4p * phins_cj_prev ) * wbase;
01723 domgr0_prev_dt = ( (~phips_prev * Ips_prev + ~phins_cj_prev * Ins_cj_prev).Im() - Tmech_eff - Kfric * wr_pu_prev ) / (2.0 * H);
01724
01725
01726
01727 phips = phips_prev + dphips_prev_dt * dTime;
01728 phins_cj = phins_cj_prev + dphins_cj_prev_dt * dTime;
01729 phipr = phipr_prev + dphipr_prev_dt * dTime ;
01730 phinr_cj = phinr_cj_prev + dphinr_cj_prev_dt * dTime ;
01731 wr_pu = wr_pu_prev + domgr0_prev_dt.Re() * dTime ;
01732 wr = wr_pu * wbase;
01733
01734
01735 Ips = (phips - phipr * lm / Lr) / sigma1;
01736 Ipr = (phipr - phips * lm / Ls) / sigma2;
01737 Ins_cj = (phins_cj - phinr_cj * lm / Lr) / sigma1 ;
01738 Inr_cj = (phinr_cj - phins_cj * lm / Ls) / sigma2;
01739
01740
01741
01742
01743
01744
01745
01746 A1c = -(complex(0.0,1.0) * ws_pu + rs_pu / sigma1) ;
01747 C1c = rs_pu / sigma1 * lm / Lr ;
01748
01749 B2c = -(complex(0.0,-1.0) * ws_pu + rs_pu / sigma1) ;
01750 D2c = rs_pu / sigma1 *lm / Lr ;
01751
01752 A3c = rr_pu / sigma2 * lm / Ls ;
01753 C3c = -(complex(0.0,1.0) * (ws_pu - wr_pu) + rr_pu / sigma2) ;
01754
01755 B4c = rr_pu / sigma2 * lm / Ls ;
01756 D4c = -(complex(0.0,1.0) * (-ws_pu - wr_pu) + rr_pu / sigma2) ;
01757
01758
01759 dphips_dt = ( Vap + A1c * phips + C1c * phipr ) * wbase;
01760 dphins_cj_dt = ( ~Van + B2c * phins_cj + D2c * phinr_cj ) * wbase ;
01761 dphipr_dt = ( C3c * phipr + A3c * phips ) * wbase;
01762 dphinr_cj_dt = ( D4c * phinr_cj + B4c * phins_cj ) * wbase;
01763 domgr0_dt = 1.0/(2.0 * H) * ( (~phips * Ips + ~phins_cj * Ins_cj).Im() - Tmech_eff - Kfric * wr_pu );
01764
01765
01766 phips = phips_prev + (dphips_prev_dt + dphips_dt) * dTime/2.0;
01767 phins_cj = phins_cj_prev + (dphins_cj_prev_dt + dphins_cj_dt) * dTime/2.0;
01768 phipr = phipr_prev + (dphipr_prev_dt + dphipr_dt) * dTime/2.0 ;
01769 phinr_cj = phinr_cj_prev + (dphinr_cj_prev_dt + dphinr_cj_dt) * dTime/2.0 ;
01770 wr_pu = wr_pu_prev + (domgr0_prev_dt + domgr0_dt).Re() * dTime/2.0 ;
01771 wr = wr_pu * wbase;
01772
01773 if (wr_pu < -10.0) {
01774 wr_pu = -10.0;
01775 wr = wr_pu * wbase;
01776 }
01777
01778
01779 Ips = (phips - phipr * lm / Lr) / sigma1;
01780 Ipr = (phipr - phips * lm / Ls) / sigma2;
01781 Ins_cj = (phins_cj - phinr_cj * lm / Lr) / sigma1;
01782 Inr_cj = (phinr_cj - phins_cj * lm / Ls) / sigma2;
01783 Telec = (~phips * Ips + ~phins_cj * Ins_cj).Im() ;
01784
01785
01786 Ias = Ips + ~Ins_cj ;
01787 Ibs = alpha * alpha * Ips + alpha * ~Ins_cj ;
01788 Ics = alpha * Ips + alpha * alpha * ~Ins_cj ;
01789
01790 motor_elec_power = (Vap * ~Ips + Van * Ins_cj) * Pbase;
01791
01792 }
01793
01794
01795 complex motor::complex_exp(double angle)
01796 {
01797 complex output_val;
01798
01799
01800 output_val = complex(cos(angle),sin(angle));
01801
01802 return output_val;
01803 }
01804
01805
01806 int motor::invertMatrix(complex TF[16], complex ITF[16])
01807 {
01808 complex inv[16], det;
01809 int i;
01810
01811 inv[0] = TF[5] * TF[10] * TF[15] - TF[5] * TF[11] * TF[14] - TF[9] * TF[6] * TF[15] + TF[9] * TF[7] * TF[14] +TF[13] * TF[6] * TF[11] - TF[13] * TF[7] * TF[10];
01812 inv[4] = -TF[4] * TF[10] * TF[15] + TF[4] * TF[11] * TF[14] + TF[8] * TF[6] * TF[15] - TF[8] * TF[7] * TF[14] - TF[12] * TF[6] * TF[11] + TF[12] * TF[7] * TF[10];
01813 inv[8] = TF[4] * TF[9] * TF[15] - TF[4] * TF[11] * TF[13] - TF[8] * TF[5] * TF[15] + TF[8] * TF[7] * TF[13] + TF[12] * TF[5] * TF[11] - TF[12] * TF[7] * TF[9];
01814 inv[12] = -TF[4] * TF[9] * TF[14] + TF[4] * TF[10] * TF[13] +TF[8] * TF[5] * TF[14] - TF[8] * TF[6] * TF[13] - TF[12] * TF[5] * TF[10] + TF[12] * TF[6] * TF[9];
01815 inv[1] = -TF[1] * TF[10] * TF[15] + TF[1] * TF[11] * TF[14] + TF[9] * TF[2] * TF[15] - TF[9] * TF[3] * TF[14] - TF[13] * TF[2] * TF[11] + TF[13] * TF[3] * TF[10];
01816 inv[5] = TF[0] * TF[10] * TF[15] - TF[0] * TF[11] * TF[14] - TF[8] * TF[2] * TF[15] + TF[8] * TF[3] * TF[14] + TF[12] * TF[2] * TF[11] - TF[12] * TF[3] * TF[10];
01817 inv[9] = -TF[0] * TF[9] * TF[15] + TF[0] * TF[11] * TF[13] + TF[8] * TF[1] * TF[15] - TF[8] * TF[3] * TF[13] - TF[12] * TF[1] * TF[11] + TF[12] * TF[3] * TF[9];
01818 inv[13] = TF[0] * TF[9] * TF[14] - TF[0] * TF[10] * TF[13] - TF[8] * TF[1] * TF[14] + TF[8] * TF[2] * TF[13] + TF[12] * TF[1] * TF[10] - TF[12] * TF[2] * TF[9];
01819 inv[2] = TF[1] * TF[6] * TF[15] - TF[1] * TF[7] * TF[14] - TF[5] * TF[2] * TF[15] + TF[5] * TF[3] * TF[14] + TF[13] * TF[2] * TF[7] - TF[13] * TF[3] * TF[6];
01820 inv[6] = -TF[0] * TF[6] * TF[15] + TF[0] * TF[7] * TF[14] + TF[4] * TF[2] * TF[15] - TF[4] * TF[3] * TF[14] - TF[12] * TF[2] * TF[7] + TF[12] * TF[3] * TF[6];
01821 inv[10] = TF[0] * TF[5] * TF[15] - TF[0] * TF[7] * TF[13] - TF[4] * TF[1] * TF[15] + TF[4] * TF[3] * TF[13] + TF[12] * TF[1] * TF[7] - TF[12] * TF[3] * TF[5];
01822 inv[14] = -TF[0] * TF[5] * TF[14] + TF[0] * TF[6] * TF[13] + TF[4] * TF[1] * TF[14] - TF[4] * TF[2] * TF[13] - TF[12] * TF[1] * TF[6] + TF[12] * TF[2] * TF[5];
01823 inv[3] = -TF[1] * TF[6] * TF[11] + TF[1] * TF[7] * TF[10] + TF[5] * TF[2] * TF[11] - TF[5] * TF[3] * TF[10] - TF[9] * TF[2] * TF[7] + TF[9] * TF[3] * TF[6];
01824 inv[7] = TF[0] * TF[6] * TF[11] - TF[0] * TF[7] * TF[10] - TF[4] * TF[2] * TF[11] + TF[4] * TF[3] * TF[10] + TF[8] * TF[2] * TF[7] - TF[8] * TF[3] * TF[6];
01825 inv[11] = -TF[0] * TF[5] * TF[11] + TF[0] * TF[7] * TF[9] + TF[4] * TF[1] * TF[11] - TF[4] * TF[3] * TF[9] - TF[8] * TF[1] * TF[7] + TF[8] * TF[3] * TF[5];
01826 inv[15] = TF[0] * TF[5] * TF[10] - TF[0] * TF[6] * TF[9] - TF[4] * TF[1] * TF[10] + TF[4] * TF[2] * TF[9] + TF[8] * TF[1] * TF[6] - TF[8] * TF[2] * TF[5];
01827
01828 det = TF[0] * inv[0] + TF[1] * inv[4] + TF[2] * inv[8] + TF[3] * inv[12];
01829
01830 if (det == 0)
01831 return 0;
01832
01833 det = complex(1,0) / det;
01834
01835 for (i = 0; i < 16; i++)
01836 ITF[i] = inv[i] * det;
01837
01838 return 1;
01839 }
01840
01842
01844
01852 EXPORT int create_motor(OBJECT **obj, OBJECT *parent)
01853 {
01854 try
01855 {
01856 *obj = gl_create_object(motor::oclass);
01857 if (*obj!=NULL)
01858 {
01859 motor *my = OBJECTDATA(*obj,motor);
01860 gl_set_parent(*obj,parent);
01861 return my->create();
01862 }
01863 else
01864 return 0;
01865 }
01866 CREATE_CATCHALL(motor);
01867 }
01868
01875 EXPORT int init_motor(OBJECT *obj)
01876 {
01877 try {
01878 motor *my = OBJECTDATA(obj,motor);
01879 return my->init(obj->parent);
01880 }
01881 INIT_CATCHALL(motor);
01882 }
01883
01892 EXPORT TIMESTAMP sync_motor(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
01893 {
01894 TIMESTAMP t1 = TS_INVALID;
01895 motor *my = OBJECTDATA(obj,motor);
01896 try
01897 {
01898 switch (pass) {
01899 case PC_PRETOPDOWN:
01900 t1 = my->presync(obj->clock,t0);
01901 break;
01902 case PC_BOTTOMUP:
01903 t1 = my->sync(obj->clock,t0);
01904 break;
01905 case PC_POSTTOPDOWN:
01906 t1 = my->postsync(obj->clock,t0);
01907 break;
01908 default:
01909 GL_THROW("invalid pass request (%d)", pass);
01910 break;
01911 }
01912 if (pass == clockpass)
01913 obj->clock = t1;
01914 }
01915 SYNC_CATCHALL(motor);
01916 return t1;
01917 }
01918
01927 EXPORT int isa_motor(OBJECT *obj, char *classname)
01928 {
01929 if(obj != 0 && classname != 0){
01930 return OBJECTDATA(obj,motor)->isa(classname);
01931 } else {
01932 return 0;
01933 }
01934 }
01935
01939 EXPORT SIMULATIONMODE interupdate_motor(OBJECT *obj, unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val, bool interupdate_pos)
01940 {
01941 motor *my = OBJECTDATA(obj,motor);
01942 SIMULATIONMODE status = SM_ERROR;
01943 try
01944 {
01945 status = my->inter_deltaupdate(delta_time,dt,iteration_count_val,interupdate_pos);
01946 return status;
01947 }
01948 catch (char *msg)
01949 {
01950 gl_error("interupdate_motor(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
01951 return status;
01952 }
01953 }
01954