00001
00009 #include <math.h>
00010
00011 #include "vfd.h"
00012
00013
00014 CLASS* vfd::oclass = NULL;
00015 CLASS* vfd::pclass = NULL;
00016
00018
00020
00021 vfd::vfd(MODULE *mod) : link_object(mod)
00022 {
00023 if(oclass == NULL)
00024 {
00025 pclass = link_object::oclass;
00026
00027 oclass = gl_register_class(mod,"vfd",sizeof(vfd),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_UNSAFE_OVERRIDE_OMIT|PC_AUTOLOCK);
00028 if (oclass==NULL)
00029 throw "unable to register class vfd";
00030 else
00031 oclass->trl = TRL_PROTOTYPE;
00032
00033 if(gl_publish_variable(oclass,
00034 PT_INHERIT, "link",
00035
00036 PT_double, "rated_motor_speed[1/min]", PADDR(ratedRPM), PT_DESCRIPTION, "Rated speed of the VFD in RPM. Default = 1800 RPM",
00037 PT_double, "desired_motor_speed[1/min]", PADDR(desiredRPM), PT_DESCRIPTION, "Desired speed of the VFD In ROM. Default = 1800 RPM (max)",
00038 PT_double, "motor_poles", PADDR(motorPoles), PT_DESCRIPTION, "Number of Motor Poles. Default = 4",
00039 PT_double, "rated_output_voltage[V]", PADDR(voltageLLRating), PT_DESCRIPTION, "Line to Line Voltage - VFD Rated voltage. Default to TO node nominal_voltage",
00040 PT_double, "rated_horse_power[hp]", PADDR(horsePowerRatedVFD), PT_DESCRIPTION, "Rated Horse Power of the VFD. Default = 75 HP",
00041 PT_double, "nominal_output_frequency[Hz]", PADDR(nominal_output_frequency), PT_DESCRIPTION, "Nominal VFD output frequency. Default = 60 Hz",
00042
00043 PT_double, "desired_output_frequency[Hz]", PADDR(desiredFrequency), PT_DESCRIPTION, "VFD desired output frequency based on the desired RPM",
00044 PT_double, "current_output_frequency[Hz]", PADDR(currentFrequency), PT_DESCRIPTION, "VFD currently output frequency",
00045 PT_double, "efficiency[%]", PADDR(currEfficiency), PT_DESCRIPTION, "Current VFD efficiency based on the load/VFD output Horsepower",
00046
00047 PT_double, "stable_time[s]", PADDR(stableTime), PT_DESCRIPTION, "Time taken by the VFD to reach desired frequency (based on RPM). Default = 1.45 seconds",
00048
00049 PT_enumeration, "vfd_state", PADDR(vfdState), PT_DESCRIPTION, "Current state of the VFD",
00050 PT_KEYWORD, "OFF", (enumeration)VFD_OFF,
00051 PT_KEYWORD, "CHANGING", (enumeration)VFD_CHANGING,
00052 PT_KEYWORD, "STEADY_STATE", (enumeration)VFD_STEADY,
00053
00054 NULL) < 1) GL_THROW("unable to publish properties in %s",__FILE__);
00055
00056
00057 if (gl_publish_function(oclass, "interupdate_pwr_object", (FUNCTIONADDR)interupdate_vfd)==NULL)
00058 GL_THROW("Unable to publish VFD deltamode function");
00059 if (gl_publish_function(oclass, "postupdate_pwr_object", (FUNCTIONADDR)postupdate_vfd)==NULL)
00060 GL_THROW("Unable to publish VFD deltamode function");
00061
00062
00063 if (gl_publish_function(oclass, "update_power_pwr_object", (FUNCTIONADDR)updatepowercalc_link)==NULL)
00064 GL_THROW("Unable to publish VFD external power calculation function");
00065 if (gl_publish_function(oclass, "check_limits_pwr_object", (FUNCTIONADDR)calculate_overlimit_link)==NULL)
00066 GL_THROW("Unable to publish VFD external power limit calculation function");
00067
00068
00069 if (gl_publish_function(oclass, "vfd_current_injection_update", (FUNCTIONADDR)current_injection_update_VFD)==NULL)
00070 GL_THROW("Unable to publish VFD external current injection calculation function");
00071 }
00072 }
00073
00074 int vfd::isa(char *classname)
00075 {
00076 return strcmp(classname,"vfd")==0 || link_object::isa(classname);
00077 }
00078
00079 int vfd::create()
00080 {
00081 int result = link_object::create();
00082
00083 ratedRPM = 1800;
00084 desiredRPM = 1800;
00085 motorPoles = 4;
00086 voltageLLRating = -1.0;
00087 horsePowerRatedVFD = 75;
00088 nominal_output_frequency = -1.0;
00089 stableTime = 1.45;
00090
00091 vfdState = VFD_OFF;
00092 prev_vfdState = VFD_OFF;
00093
00094 desiredFrequency = 0.0;
00095 currentFrequency = 0.0;
00096 currEfficiency = 0.0;
00097 prev_desiredRPM = 0.0;
00098
00099 curr_time_value = 0.0;
00100 prev_time_value = 0.0;
00101
00102
00103 settleFreq = NULL;
00104 settleFreq_length = 0;
00105 curr_array_position = 0;
00106 force_array_realloc = false;
00107
00108 nominal_output_radian_freq = 0.0;
00109 VbyF = 0.0;
00110 HPbyF = 0.0;
00111
00112
00113 fNode = NULL;
00114 tNode = NULL;
00115
00116
00117
00118
00119
00120
00121 efficiency_coeffs[0] = 96.014;
00122 efficiency_coeffs[1] = 3.8759;
00123 efficiency_coeffs[2] = -4.4504;
00124 efficiency_coeffs[3] = -3.2079;
00125 efficiency_coeffs[4] = 8.7113;
00126 efficiency_coeffs[5] = 0.97848;
00127 efficiency_coeffs[6] = -8.2828;
00128 efficiency_coeffs[7] = 3.497;
00129
00130
00131 prev_power[0] = complex(0.0,0.0);
00132 prev_power[1] = complex(0.0,0.0);
00133 prev_power[2] = complex(0.0,0.0);
00134
00135
00136 SpecialLnk=VFD;
00137
00138 return result;
00139 }
00140
00147 int vfd::init(OBJECT *parent)
00148 {
00149 OBJECT *obj = OBJECTHDR(this);
00150 FUNCTIONADDR temp_fxn;
00151 STATUS temp_status_val;
00152 double temp_voltage_check, temp_diff_value;
00153
00154 int result = link_object::init(parent);
00155
00156 if (stableTime <= 0.0)
00157 {
00158 GL_THROW("VFD:%d - %s - the stableTime must be positive",obj->id,(obj->name ? obj->name : "Unnamed"));
00159
00160
00161
00162
00163 }
00164
00165
00166 fNode = OBJECTDATA(from,node);
00167 tNode = OBJECTDATA(to,node);
00168
00169
00170 if (voltageLLRating <= 0.0)
00171 {
00172 voltageLLRating = tNode->nominal_voltage * sqrt(3.0);
00173
00174 gl_warning("VFD:%d - %s - rated_output_voltage was not set, defaulting to TO node nominal",obj->id,(obj->name ? obj->name : "Unnamed"));
00175
00176
00177
00178 }
00179 else
00180 {
00181
00182 temp_voltage_check = tNode->nominal_voltage * sqrt(3.0);
00183
00184
00185 temp_diff_value = fabs(voltageLLRating - temp_voltage_check);
00186
00187 if (temp_diff_value > 0.5)
00188 {
00189 gl_warning("VFD:%d - %s - rated_output_voltage does not match the TO node nominal voltage",obj->id,(obj->name ? obj->name : "Unnamed"));
00190
00191
00192
00193 }
00194 }
00195
00196
00197 temp_voltage_check = fNode->nominal_voltage - tNode->nominal_voltage;
00198
00199 if (temp_voltage_check < 0.0)
00200 {
00201 gl_warning("VFD:%d - %s - FROM node nominal_voltage is not equal to or greater than TO node nominal_voltage - implies DC-DC converter!e",obj->id,(obj->name ? obj->name : "Unnamed"));
00202
00203
00204
00205
00206 }
00207
00208
00209 if (nominal_output_frequency <= 0.0)
00210 {
00211 gl_warning("VFD:%d - %s - nominal_output_frequency is not set or is negative - defaulting to system nominal",obj->id,(obj->name ? obj->name : "Unnamed"));
00212
00213
00214
00215
00216 nominal_output_frequency = nominal_frequency;
00217 }
00218
00219
00220 if (ratedRPM <= 0.0)
00221 {
00222 GL_THROW("VFD:%d - %s - rated_motor_speed must be positive and non-zero!",obj->id,(obj->name ? obj->name : "Unnamed"));
00223
00224
00225
00226
00227 return 0;
00228 }
00229
00230
00231 if (motorPoles <= 0.0)
00232 {
00233 GL_THROW("VFD:%d - %s - motor_poles must be positive and non-zero!",obj->id,(obj->name ? obj->name : "Unnamed"));
00234
00235
00236
00237
00238 return 0;
00239 }
00240
00241
00242 if (horsePowerRatedVFD <= 0.0)
00243 {
00244 GL_THROW("VFD:%d - %s - rated_horse_power must be positive and non-zero!",obj->id,(obj->name ? obj->name : "Unnamed"));
00245
00246
00247
00248
00249 return 0;
00250 }
00251
00252
00253 if ((has_phase(PHASE_A) & has_phase(PHASE_B) & has_phase(PHASE_C)) != true)
00254 {
00255 GL_THROW("VFD:%d - %s - Must be three-phase!",obj->id,(obj->name ? obj->name : "Unnamed"));
00256
00257
00258
00259
00260 return 0;
00261 }
00262
00263
00264 phasorVal[0] = 0.0;
00265 phasorVal[1] = -2.0 * PI / 3.0;
00266 phasorVal[2] = 2.0 * PI / 3.0;
00267
00268
00269
00270
00271 nominal_output_radian_freq = nominal_frequency*2.0*PI;
00272
00273
00274 VbyF = voltageLLRating/nominal_output_frequency;
00275
00276
00277 HPbyF = 100.0/nominal_output_frequency;
00278
00279
00280 temp_status_val = alloc_freq_arrays(1.0);
00281
00282
00283 if (vfdState == VFD_STEADY)
00284 {
00285
00286 prev_desiredRPM = desiredRPM;
00287 prev_vfdState = vfdState;
00288
00289
00290 CheckParameters();
00291
00292 currentFrequency = desiredFrequency;
00293 }
00294
00295
00296
00297 if (temp_status_val == FAILED)
00298 {
00299 GL_THROW("VFD:%d - %s - Allocating the dynamic arrays for the frequency tracking failed",obj->id,(obj->name ? obj->name : "Unnamed"));
00300
00301
00302
00303
00304 }
00305
00306
00307 temp_fxn = (FUNCTIONADDR)(gl_get_function(to,"attach_vfd_to_pwr_object"));
00308
00309
00310 if (temp_fxn == NULL)
00311 {
00312 GL_THROW("VFD:%d - %s -- Failed to map TO-node flag function",obj->id,(obj->name ? obj->name : "Unnamed"));
00313
00314
00315
00316
00317 }
00318
00319
00320 temp_status_val = ((STATUS (*)(OBJECT *,OBJECT *))(*temp_fxn))(to,obj);
00321
00322
00323 if (temp_status_val == FAILED)
00324 {
00325 GL_THROW("VFD:%d - %s -- Failed to map TO-node flag function",obj->id,(obj->name ? obj->name : "Unnamed"));
00326
00327 }
00328
00329
00330 prev_time_value = (double)(gl_globalclock) - 1.0;
00331
00332 return result;
00333 }
00334
00335 void vfd::CheckParameters()
00336 {
00337 OBJECT *obj = OBJECTHDR(this);
00338
00339
00340 if (desiredRPM < 0.0)
00341 {
00342 GL_THROW("VFD:%d - %s - the desired_motor_speed must be positive",obj->id,(obj->name ? obj->name : "Unnamed"));
00343
00344
00345
00346
00347 }
00348
00349
00350 if (desiredRPM == 0.0)
00351 {
00352 vfdState = VFD_OFF;
00353 }
00354
00355
00356 if ((prev_desiredRPM == 0.0) && (desiredRPM > 0.0))
00357 {
00358
00359 vfdState = VFD_STEADY;
00360 }
00361
00362
00363 desiredFrequency = (desiredRPM*motorPoles)/120.0;
00364
00365 if ((desiredFrequency > 0.0) && (desiredFrequency < 3.0))
00366 {
00367 gl_warning("VFD:%d - %s - the desired_motor_speed results in a frequency of less than 3.0 Hz",obj->id,(obj->name ? obj->name : "Unnamed"));
00368
00369
00370
00371
00372 }
00373
00374 if (desiredRPM/ratedRPM <=0.75)
00375 {
00376 gl_warning("VFD:%d - %s - VFD currently at %f%% of rated speed -- VFDs perform best when running at >= 75 percent output",obj->id,(obj->name ? obj->name : "Unnamed"),(desiredRPM*100/ratedRPM));
00377
00378
00379
00380 }
00381 }
00382
00383
00384 STATUS vfd::VFD_current_injection(void)
00385 {
00386 complex currRat, lossCurr[3];
00387 int index_val, index_val_inner, index_new_limit;
00388 double z_val, driveCurrPower, temp_coeff, settleVolt, avg_freq_value;
00389 complex temp_power_val, powerOutElectrical, powerInElectrical;
00390 complex settleVoltOut[3];
00391 bool desiredChange;
00392 int tdiff_value;
00393 double diff_time_value;
00394
00395
00396 desiredChange = false;
00397
00398
00399 if (deltatimestep_running > 0)
00400 {
00401
00402 curr_time_value = gl_globaldeltaclock;
00403 }
00404
00405
00406 if (prev_desiredRPM != desiredRPM)
00407 {
00408
00409 CheckParameters();
00410
00411
00412 desiredChange = true;
00413
00414
00415 prev_desiredRPM = desiredRPM;
00416 }
00417
00418
00419
00420 if (curr_time_value != prev_time_value)
00421 {
00422
00423 diff_time_value = curr_time_value - prev_time_value;
00424
00425
00426 if (deltatimestep_running > 0)
00427 {
00428
00429 tdiff_value = 1;
00430 }
00431 else
00432 {
00433
00434 tdiff_value = (int)(curr_time_value - prev_time_value);
00435 }
00436
00437
00438
00439 if (vfdState == VFD_STEADY)
00440 {
00441
00442 if (prev_vfdState == VFD_OFF)
00443 {
00444
00445 vfdState = VFD_CHANGING;
00446
00447
00448 phasorVal[0] = 0.0;
00449 phasorVal[1] = -2.0 * PI / 3.0;
00450 phasorVal[2] = 2.0 * PI / 3.0;
00451
00452
00453 currentFrequency = 3.0;
00454
00455
00456 curr_array_position = 0;
00457
00458
00459 for (index_val=0; index_val<settleFreq_length; index_val++)
00460 {
00461
00462 settleFreq[index_val] = 3.0;
00463 }
00464
00465
00466 tdiff_value = 1;
00467 }
00468 else if (prev_vfdState == VFD_CHANGING)
00469 {
00470
00471
00472 prev_vfdState = VFD_STEADY;
00473 }
00474 else
00475 {
00476
00477 if (currentFrequency != desiredFrequency)
00478 {
00479
00480 vfdState = VFD_CHANGING;
00481
00482
00483 for (index_val=0; index_val<settleFreq_length; index_val++)
00484 {
00485
00486 settleFreq[index_val] = currentFrequency;
00487 }
00488
00489
00490 curr_array_position = 0;
00491
00492
00493 }
00494
00495 }
00496 }
00497
00498
00499 if (vfdState == VFD_CHANGING)
00500 {
00501
00502 if ((prev_vfdState == VFD_CHANGING) && (desiredChange == true))
00503 {
00504
00505 for (index_val=0; index_val<settleFreq_length; index_val++)
00506 {
00507 settleFreq[index_val] = currentFrequency;
00508 }
00509
00510
00511 curr_array_position = 0;
00512
00513
00514 tdiff_value = 1;
00515 }
00516
00517
00518
00519 if (curr_array_position == settleFreq_length)
00520 {
00521
00522 vfdState = VFD_STEADY;
00523 }
00524 else
00525 {
00526
00527 index_new_limit = curr_array_position + tdiff_value;
00528
00529
00530 if (index_new_limit > settleFreq_length)
00531 {
00532
00533
00534 for (index_val=curr_array_position; index_val<settleFreq_length; index_val++)
00535 {
00536
00537 settleFreq[index_val] = desiredFrequency;
00538 }
00539
00540
00541 curr_array_position = settleFreq_length;
00542
00543
00544 vfdState = VFD_STEADY;
00545
00546
00547 }
00548 else
00549 {
00550
00551 for (index_val=curr_array_position; index_val<index_new_limit; index_val++)
00552 {
00553
00554 settleFreq[index_val] = desiredFrequency;
00555 }
00556
00557
00558 curr_array_position = index_new_limit;
00559 }
00560
00561
00562
00563 avg_freq_value = 0.0;
00564
00565
00566 for (index_val=0; index_val<settleFreq_length; index_val++)
00567 {
00568 avg_freq_value += settleFreq[index_val];
00569 }
00570
00571
00572 avg_freq_value /= (double)settleFreq_length;
00573
00574
00575 currentFrequency = avg_freq_value;
00576 }
00577 }
00578
00579
00580 if (vfdState == VFD_OFF)
00581 {
00582
00583 currentFrequency = 0.0;
00584 }
00585
00586
00587 prev_vfdState = vfdState;
00588
00589
00590 prev_time_value = curr_time_value;
00591
00592
00593 if (vfdState != VFD_OFF)
00594 {
00595 phasorVal[0] += (2*PI*currentFrequency - nominal_output_radian_freq)*diff_time_value;
00596 phasorVal[1] += (2*PI*currentFrequency - nominal_output_radian_freq)*diff_time_value;
00597 phasorVal[2] += (2*PI*currentFrequency - nominal_output_radian_freq)*diff_time_value;
00598 }
00599
00600 }
00601
00602
00603 settleVolt = VbyF*currentFrequency;
00604
00605
00606 settleVoltOut[0] = complex(settleVolt,0)*complex_exp(phasorVal[0]);
00607 settleVoltOut[1] = complex(settleVolt,0)*complex_exp(phasorVal[1]);
00608 settleVoltOut[2] = complex(settleVolt,0)*complex_exp(phasorVal[2]);
00609
00610
00611 if (vfdState == VFD_OFF)
00612 {
00613
00614 currEfficiency = 0.0;
00615
00616
00617 for (index_val=0; index_val<3; index_val++)
00618 {
00619
00620 tNode->voltage[index_val] = complex(0.0,0.0);
00621
00622
00623 current_out[index_val] = complex(0.0,0.0);
00624 current_in[index_val] = complex(0.0,0.0);
00625
00626
00627 indiv_power_in[index_val] = complex(0.0,0.0);
00628 indiv_power_out[index_val] = complex(0.0,0.0);
00629
00630
00631 fNode->power[index_val] -= prev_power[index_val];
00632
00633
00634 prev_power[index_val] = complex(0.0,0.0);
00635
00636 }
00637 }
00638 else
00639 {
00640
00641
00642 driveCurrPower = HPbyF*currentFrequency;
00643
00644
00645 z_val = (driveCurrPower - 50.138)/37.009;
00646
00647
00648 currEfficiency = 0.0;
00649
00650
00651 for (index_val=0; index_val<8; index_val++)
00652 {
00653 if (index_val == 0)
00654 {
00655 currEfficiency = efficiency_coeffs[0];
00656 }
00657 else
00658 {
00659 temp_coeff = z_val;
00660
00661 for (index_val_inner=1; index_val_inner<index_val; index_val_inner++)
00662 {
00663 temp_coeff = temp_coeff * z_val;
00664 }
00665
00666
00667 temp_coeff = temp_coeff * efficiency_coeffs[index_val];
00668
00669
00670 currEfficiency += temp_coeff;
00671
00672 }
00673 }
00674
00675
00676 powerOutElectrical = complex(0.0,0.0);
00677
00678 for (index_val=0; index_val<3; index_val++)
00679 {
00680
00681 current_out[index_val] = tNode->current[index_val];
00682
00683
00684 temp_power_val = (tNode->voltage[index_val]*~current_out[index_val]);
00685
00686 powerOutElectrical += temp_power_val;
00687
00688
00689 indiv_power_out[index_val] = temp_power_val;
00690 }
00691
00692
00693
00694
00695 if (currEfficiency == 0.0)
00696 {
00697
00698 powerOutElectrical = complex(0.0,0.0);
00699 powerInElectrical = complex(0.0,0.0);
00700 }
00701 else
00702 {
00703 powerInElectrical = powerOutElectrical*100.0/currEfficiency/3.0;
00704 }
00705
00706
00707 for (index_val=0; index_val<3; index_val++)
00708 {
00709
00710 fNode->power[index_val] += powerInElectrical - prev_power[index_val];
00711
00712
00713 indiv_power_in[index_val] = powerInElectrical;
00714
00715
00716 prev_power[index_val] = powerInElectrical;
00717
00718
00719 if (fNode->voltage[index_val].Mag() == 0.0)
00720 {
00721 current_in[index_val] = complex(0.0,0.0);
00722 }
00723 else
00724 {
00725 current_in[index_val] = ~(powerInElectrical/fNode->voltage[index_val]);
00726 }
00727
00728
00729 tNode->voltage[index_val] = settleVoltOut[index_val];
00730 }
00731 }
00732
00733
00734 return SUCCESS;
00735 }
00736
00737 TIMESTAMP vfd::presync(TIMESTAMP t0)
00738 {
00739 return link_object::presync(t0);
00740 }
00741
00742 TIMESTAMP vfd::sync(TIMESTAMP t0)
00743 {
00744 TIMESTAMP t2;
00745
00746
00747 curr_time_value = (double)t0;
00748
00749 t2 = link_object::sync(t0);
00750
00751 return t2;
00752 }
00753
00754 TIMESTAMP vfd::postsync(TIMESTAMP t0)
00755 {
00756 TIMESTAMP t1, tret;
00757 int time_left;
00758
00759
00760 t1 = link_object::postsync(t0);
00761
00762
00763 if (vfdState == VFD_CHANGING)
00764 {
00765
00766 if (curr_array_position < settleFreq_length)
00767 {
00768
00769 time_left = settleFreq_length - curr_array_position;
00770
00771
00772 tret = t0 + (TIMESTAMP)time_left;
00773
00774
00775 if (t1 != TS_NEVER)
00776 {
00777 if (t1 < 0)
00778 {
00779 if (tret < (-t1))
00780 {
00781 return -tret;
00782 }
00783 else
00784 {
00785 return t1;
00786 }
00787 }
00788 else
00789 {
00790 if (tret < t1)
00791 {
00792 return -tret;
00793 }
00794 else
00795 {
00796 return t1;
00797 }
00798 }
00799 }
00800 else
00801 {
00802 return -tret;
00803 }
00804 }
00805 else
00806 {
00807
00808 vfdState = VFD_STEADY;
00809
00810 return t1;
00811 }
00812 }
00813 else
00814 {
00815 return t1;
00816 }
00817 }
00818
00819
00820
00821 complex vfd::complex_exp(double angle)
00822 {
00823 complex output_val;
00824 double temp_angle, new_angle;
00825 int even_amount;
00826
00827
00828 if (fabs(angle) > (2.0 * PI))
00829 {
00830
00831 even_amount = (int)(angle/(2.0 * PI));
00832
00833
00834 temp_angle = (double)(even_amount) * 2.0 * PI;
00835
00836
00837 new_angle = angle - temp_angle;
00838
00839
00840 angle = new_angle;
00841 }
00842
00843
00844 output_val = complex(cos(angle),sin(angle));
00845
00846 return output_val;
00847 }
00848
00849
00850 STATUS vfd::alloc_freq_arrays(double delta_t_val)
00851 {
00852 OBJECT *obj = OBJECTHDR(this);
00853 int a_index;
00854
00855
00856 if (force_array_realloc == true)
00857 {
00858
00859 if (settleFreq != NULL)
00860 {
00861
00862 gl_free(settleFreq);
00863
00864
00865 settleFreq_length = 0;
00866 }
00867
00868
00869
00870 force_array_realloc = false;
00871
00872
00873 settleFreq = NULL;
00874 }
00875
00876
00877 if (settleFreq == NULL)
00878 {
00879
00880 settleFreq_length = (int)(stableTime/delta_t_val + 0.5);
00881
00882
00883 if (settleFreq_length <= 0)
00884 {
00885 gl_error("vfd:%d %s -- the stable_time value must result in at least 1 timestep of averaging!",obj->id,(obj->name ? obj->name : "Unnamed"));
00886
00887
00888
00889
00890 return FAILED;
00891 }
00892
00893
00894 settleFreq = (double *)gl_malloc(settleFreq_length*sizeof(double));
00895
00896
00897 if (settleFreq == NULL)
00898 {
00899
00900 gl_error("vfd:%d %s -- failed to allocate dynamic array",obj->id,(obj->name ? obj->name : "Unnamed"));
00901
00902
00903
00904
00905
00906 return FAILED;
00907 }
00908
00909
00910 for (a_index=0; a_index<settleFreq_length; a_index++)
00911 {
00912 settleFreq[a_index] = 0.0;
00913 }
00914
00915
00916 curr_array_position = 0;
00917
00918
00919 return SUCCESS;
00920 }
00921 else
00922 {
00923 return SUCCESS;
00924 }
00925 }
00926
00927
00928 SIMULATIONMODE vfd::inter_deltaupdate_vfd(unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val,bool interupdate_pos)
00929 {
00930 double dt_value, deltatimedbl;
00931 STATUS ret_value;
00932
00933
00934 if ((delta_time == 0) && (iteration_count_val == 0) && (interupdate_pos == false))
00935 {
00936
00937 dt_value = (double)dt/(double)DT_SECOND;
00938
00939
00940 force_array_realloc = true;
00941
00942
00943 ret_value = alloc_freq_arrays(dt_value);
00944
00945
00946 if (ret_value == FAILED)
00947 {
00948 return SM_ERROR;
00949 }
00950 }
00951
00952
00953 if (interupdate_pos == false)
00954 {
00955
00956 NR_link_presync_fxn();
00957
00958 return SM_DELTA;
00959 }
00960 else
00961 {
00962
00963 BOTH_link_postsync_fxn();
00964
00965
00966 if (vfdState == VFD_CHANGING)
00967 {
00968 return SM_DELTA;
00969 }
00970 else
00971 {
00972 return SM_EVENT;
00973 }
00974 }
00975 }
00976
00977
00978 STATUS vfd::post_deltaupdate_vfd(void)
00979 {
00980
00981 force_array_realloc = true;
00982
00983
00984 return alloc_freq_arrays(1.0);
00985 }
00986
00987
00988 EXPORT STATUS current_injection_update_VFD(OBJECT *obj)
00989 {
00990 vfd *vfdObj = OBJECTDATA(obj,vfd);
00991
00992 return vfdObj->VFD_current_injection();
00993 }
00994
00996
00998
01006 EXPORT int create_vfd(OBJECT **obj, OBJECT *parent)
01007 {
01008 try
01009 {
01010 *obj = gl_create_object(vfd::oclass);
01011 if (*obj!=NULL)
01012 {
01013 vfd *my = OBJECTDATA(*obj,vfd);
01014 gl_set_parent(*obj,parent);
01015 return my->create();
01016 }
01017 else
01018 return 0;
01019 }
01020 CREATE_CATCHALL(vfd);
01021 }
01022
01029 EXPORT int init_vfd(OBJECT *obj)
01030 {
01031 try {
01032 vfd *my = OBJECTDATA(obj,vfd);
01033 return my->init(obj->parent);
01034 }
01035 INIT_CATCHALL(vfd);
01036 }
01037
01046 EXPORT TIMESTAMP sync_vfd(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
01047 {
01048 try
01049 {
01050 vfd *pObj = OBJECTDATA(obj,vfd);
01051 TIMESTAMP t1 = TS_NEVER;
01052 switch (pass) {
01053 case PC_PRETOPDOWN:
01054 return pObj->presync(t0);
01055 case PC_BOTTOMUP:
01056 return pObj->sync(t0);
01057 case PC_POSTTOPDOWN:
01058 t1 = pObj->postsync(t0);
01059 obj->clock = t0;
01060 return t1;
01061 default:
01062 throw "invalid pass request";
01063 }
01064 }
01065 SYNC_CATCHALL(vfd);
01066 }
01067
01068 EXPORT int isa_vfd(OBJECT *obj, char *classname)
01069 {
01070 return OBJECTDATA(obj,vfd)->isa(classname);
01071 }
01072
01073
01074 EXPORT SIMULATIONMODE interupdate_vfd(OBJECT *obj, unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val, bool interupdate_pos)
01075 {
01076 vfd *my = OBJECTDATA(obj,vfd);
01077 SIMULATIONMODE status = SM_ERROR;
01078 try
01079 {
01080 status = my->inter_deltaupdate_vfd(delta_time,dt,iteration_count_val,interupdate_pos);
01081 return status;
01082 }
01083 catch (char *msg)
01084 {
01085 gl_error("interupdate_vfd(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
01086 return status;
01087 }
01088 }
01089
01090
01091 EXPORT STATUS postupdate_vfd(OBJECT *obj)
01092 {
01093 vfd *my = OBJECTDATA(obj,vfd);
01094 STATUS status_val = FAILED;
01095 try
01096 {
01097 status_val = my->post_deltaupdate_vfd();
01098 return status_val;
01099 }
01100 catch (char *msg)
01101 {
01102 gl_error("postupdate_vfd(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
01103 return status_val;
01104 }
01105 }
01106