00001
00009 #include <stdlib.h>
00010 #include <stdio.h>
00011 #include <errno.h>
00012 #include <math.h>
00013 #include <complex.h>
00014
00015 #include "windturb_dg.h"
00016
00017 CLASS *windturb_dg::oclass = NULL;
00018 windturb_dg *windturb_dg::defaults = NULL;
00019
00020 windturb_dg::windturb_dg(MODULE *module)
00021 {
00022 if (oclass==NULL)
00023 {
00024
00025 oclass = gl_register_class(module,"windturb_dg",sizeof(windturb_dg),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_AUTOLOCK);
00026 if (oclass==NULL)
00027 throw "unable to register class windturb_dg";
00028 else
00029 oclass->trl = TRL_PROOF;
00030
00031 if (gl_publish_variable(oclass,
00032 PT_enumeration,"Gen_status",PADDR(Gen_status), PT_DESCRIPTION, "Describes whether the generator is currently online or offline",
00033 PT_KEYWORD,"OFFLINE",(enumeration)OFFLINE, PT_DESCRIPTION, "Generator is currently not supplying power",
00034 PT_KEYWORD,"ONLINE",(enumeration)ONLINE, PT_DESCRIPTION, "Generator is currently available to supply power",
00035 PT_enumeration,"Gen_type",PADDR(Gen_type), PT_DESCRIPTION, "Type of generator",
00036 PT_KEYWORD,"INDUCTION",(enumeration)INDUCTION, PT_DESCRIPTION, "Standard induction generator",
00037 PT_KEYWORD,"SYNCHRONOUS",(enumeration)SYNCHRONOUS, PT_DESCRIPTION, "Standard synchronous generator; is also used to 'fake' a doubly-fed induction generator for now",
00038 PT_enumeration,"Gen_mode",PADDR(Gen_mode), PT_DESCRIPTION, "Control mode that is used for the generator output",
00039 PT_KEYWORD,"CONSTANTE",(enumeration)CONSTANTE, PT_DESCRIPTION, "Maintains the voltage at the terminals",
00040 PT_KEYWORD,"CONSTANTP",(enumeration)CONSTANTP, PT_DESCRIPTION, "Maintains the real power output at the terminals",
00041 PT_KEYWORD,"CONSTANTPQ",(enumeration)CONSTANTPQ, PT_DESCRIPTION, "Maintains the real and reactive output at the terminals - currently unsupported",
00042 PT_enumeration,"Turbine_Model",PADDR(Turbine_Model), PT_DESCRIPTION, "Type of turbine being represented; using any of these except USER_DEFINED also specifies a large number of defaults",
00043 PT_KEYWORD,"GENERIC_SYNCH_SMALL",(enumeration)GENERIC_SYNCH_SMALL, PT_DESCRIPTION, "Generic model for a small, fixed pitch synchronous turbine",
00044 PT_KEYWORD,"GENERIC_SYNCH_MID",(enumeration)GENERIC_SYNCH_MID, PT_DESCRIPTION, "Generic model for a mid-size, fixed pitch synchronous turbine",
00045 PT_KEYWORD,"GENERIC_SYNCH_LARGE",(enumeration)GENERIC_SYNCH_LARGE, PT_DESCRIPTION, "Generic model for a large, fixed pitch synchronous turbine",
00046 PT_KEYWORD,"GENERIC_IND_SMALL",(enumeration)GENERIC_IND_SMALL, PT_DESCRIPTION, "Generic model for a small induction, fixed pitch generator turbine",
00047 PT_KEYWORD,"GENERIC_IND_MID",(enumeration)GENERIC_IND_MID, PT_DESCRIPTION, "Generic model for a mid-size induction, fixed pitch generator turbine",
00048 PT_KEYWORD,"GENERIC_IND_LARGE",(enumeration)GENERIC_IND_LARGE, PT_DESCRIPTION, "Generic model for a large induction, fixed pitch generator turbine",
00049 PT_KEYWORD,"USER_DEFINED",(enumeration)USER_DEFINED, PT_DESCRIPTION, "Allows user to specify all parameters - is not currently supported",
00050 PT_KEYWORD,"VESTAS_V82",(enumeration)VESTAS_V82, PT_DESCRIPTION, "Sets all defaults to represent the power output of a VESTAS V82 turbine",
00051 PT_KEYWORD,"GE_25MW",(enumeration)GE_25MW, PT_DESCRIPTION, "Sets all defaults to represent the power output of a GE 2.5MW turbine",
00052 PT_KEYWORD,"BERGEY_10kW",(enumeration)BERGEY_10kW, PT_DESCRIPTION, "Sets all defaults to represent the power output of a Bergey 10kW turbine",
00053
00054
00055
00056 PT_double, "turbine_height[m]", PADDR(turbine_height), PT_DESCRIPTION, "Describes the height of the wind turbine hub above the ground",
00057 PT_double, "roughness_length_factor", PADDR(roughness_l), PT_DESCRIPTION, "European Wind Atlas unitless correction factor for adjusting wind speed at various heights above ground and terrain types, default=0.055",
00058 PT_double, "blade_diam[m]", PADDR(blade_diam), PT_DESCRIPTION, "Diameter of blades",
00059 PT_double, "blade_diameter[m]", PADDR(blade_diam), PT_DESCRIPTION, "Diameter of blades",
00060 PT_double, "cut_in_ws[m/s]", PADDR(cut_in_ws), PT_DESCRIPTION, "Minimum wind speed for generator operation",
00061 PT_double, "cut_out_ws[m/s]", PADDR(cut_out_ws), PT_DESCRIPTION, "Maximum wind speed for generator operation",
00062 PT_double, "ws_rated[m/s]", PADDR(ws_rated), PT_DESCRIPTION, "Rated wind speed for generator operation",
00063 PT_double, "ws_maxcp[m/s]", PADDR(ws_maxcp), PT_DESCRIPTION, "Wind speed at which generator reaches maximum Cp",
00064 PT_double, "Cp_max[pu]", PADDR(Cp_max), PT_DESCRIPTION, "Maximum coefficient of performance",
00065 PT_double, "Cp_rated[pu]", PADDR(Cp_rated), PT_DESCRIPTION, "Rated coefficient of performance",
00066 PT_double, "Cp[pu]", PADDR(Cp), PT_DESCRIPTION, "Calculated coefficient of performance",
00067
00068 PT_double, "Rated_VA[VA]", PADDR(Rated_VA), PT_DESCRIPTION, "Rated generator power output",
00069 PT_double, "Rated_V[V]", PADDR(Rated_V), PT_DESCRIPTION, "Rated generator terminal voltage",
00070 PT_double, "Pconv[W]", PADDR(Pconv), PT_DESCRIPTION, "Amount of electrical power converted from mechanical power delivered",
00071 PT_double, "P_converted[W]", PADDR(Pconv), PT_DESCRIPTION, "Amount of electrical power converted from mechanical power delivered",
00072
00073 PT_double, "GenElecEff[%]", PADDR(GenElecEff), PT_DESCRIPTION, "Calculated generator electrical efficiency",
00074 PT_double, "generator_efficiency[%]", PADDR(GenElecEff), PT_DESCRIPTION, "Calculated generator electrical efficiency",
00075 PT_double, "TotalRealPow[W]", PADDR(TotalRealPow), PT_DESCRIPTION, "Total real power output",
00076 PT_double, "total_real_power[W]", PADDR(TotalRealPow), PT_DESCRIPTION, "Total real power output",
00077 PT_double, "TotalReacPow[VA]", PADDR(TotalReacPow), PT_DESCRIPTION, "Total reactive power output",
00078 PT_double, "total_reactive_power[VA]", PADDR(TotalReacPow), PT_DESCRIPTION, "Total reactive power output",
00079
00080 PT_complex, "power_A[VA]", PADDR(power_A), PT_DESCRIPTION, "Total complex power injected on phase A",
00081 PT_complex, "power_B[VA]", PADDR(power_B), PT_DESCRIPTION, "Total complex power injected on phase B",
00082 PT_complex, "power_C[VA]", PADDR(power_C), PT_DESCRIPTION, "Total complex power injected on phase C",
00083
00084 PT_double, "WSadj[m/s]", PADDR(WSadj), PT_DESCRIPTION, "Speed of wind at hub height",
00085 PT_double, "wind_speed_adjusted[m/s]", PADDR(WSadj), PT_DESCRIPTION, "Speed of wind at hub height",
00086 PT_double, "Wind_Speed[m/s]", PADDR(Wind_Speed), PT_DESCRIPTION, "Wind speed at 5-15m level (typical measurement height)",
00087 PT_double, "wind_speed[m/s]", PADDR(Wind_Speed), PT_DESCRIPTION, "Wind speed at 5-15m level (typical measurement height)",
00088 PT_double, "air_density[kg/m^3]", PADDR(air_dens), PT_DESCRIPTION, "Estimated air density",
00089
00090 PT_double, "R_stator[pu*Ohm]", PADDR(Rst), PT_DESCRIPTION, "Induction generator primary stator resistance in p.u.",
00091 PT_double, "X_stator[pu*Ohm]", PADDR(Xst), PT_DESCRIPTION, "Induction generator primary stator reactance in p.u.",
00092 PT_double, "R_rotor[pu*Ohm]", PADDR(Rr), PT_DESCRIPTION, "Induction generator primary rotor resistance in p.u.",
00093 PT_double, "X_rotor[pu*Ohm]", PADDR(Xr), PT_DESCRIPTION, "Induction generator primary rotor reactance in p.u.",
00094 PT_double, "R_core[pu*Ohm]", PADDR(Rc), PT_DESCRIPTION, "Induction generator primary core resistance in p.u.",
00095 PT_double, "X_magnetic[pu*Ohm]", PADDR(Xm), PT_DESCRIPTION, "Induction generator primary core reactance in p.u.",
00096 PT_double, "Max_Vrotor[pu*V]", PADDR(Max_Vrotor), PT_DESCRIPTION, "Induction generator maximum induced rotor voltage in p.u., e.g. 1.2",
00097 PT_double, "Min_Vrotor[pu*V]", PADDR(Min_Vrotor), PT_DESCRIPTION, "Induction generator minimum induced rotor voltage in p.u., e.g. 0.8",
00098
00099 PT_double, "Rs[pu*Ohm]", PADDR(Rs), PT_DESCRIPTION, "Synchronous generator primary stator resistance in p.u.",
00100 PT_double, "Xs[pu*Ohm]", PADDR(Xs), PT_DESCRIPTION, "Synchronous generator primary stator reactance in p.u.",
00101 PT_double, "Rg[pu*Ohm]", PADDR(Rg), PT_DESCRIPTION, "Synchronous generator grounding resistance in p.u.",
00102 PT_double, "Xg[pu*Ohm]", PADDR(Xg), PT_DESCRIPTION, "Synchronous generator grounding reactance in p.u.",
00103 PT_double, "Max_Ef[pu*V]", PADDR(Max_Ef), PT_DESCRIPTION, "Synchronous generator maximum induced rotor voltage in p.u., e.g. 0.8",
00104 PT_double, "Min_Ef[pu*V]", PADDR(Min_Ef), PT_DESCRIPTION, "Synchronous generator minimum induced rotor voltage in p.u., e.g. 0.8",
00105
00106 PT_double, "pf[pu]", PADDR(pf), PT_DESCRIPTION, "Desired power factor in CONSTANTP mode (can be modified over time)",
00107 PT_double, "power_factor[pu]", PADDR(pf), PT_DESCRIPTION, "Desired power factor in CONSTANTP mode (can be modified over time)",
00108
00109 PT_complex, "voltage_A[V]", PADDR(voltage_A), PT_DESCRIPTION, "Terminal voltage on phase A",
00110 PT_complex, "voltage_B[V]", PADDR(voltage_B), PT_DESCRIPTION, "Terminal voltage on phase B",
00111 PT_complex, "voltage_C[V]", PADDR(voltage_C), PT_DESCRIPTION, "Terminal voltage on phase C",
00112 PT_complex, "current_A[A]", PADDR(current_A), PT_DESCRIPTION, "Calculated terminal current on phase A",
00113 PT_complex, "current_B[A]", PADDR(current_B), PT_DESCRIPTION, "Calculated terminal current on phase B",
00114 PT_complex, "current_C[A]", PADDR(current_C), PT_DESCRIPTION, "Calculated terminal current on phase C",
00115 PT_complex, "EfA[V]", PADDR(EfA), PT_DESCRIPTION, "Synchronous generator induced voltage on phase A",
00116 PT_complex, "EfB[V]", PADDR(EfB), PT_DESCRIPTION, "Synchronous generator induced voltage on phase B",
00117 PT_complex, "EfC[V]", PADDR(EfC), PT_DESCRIPTION, "Synchronous generator induced voltage on phase C",
00118 PT_complex, "Vrotor_A[V]", PADDR(Vrotor_A), PT_DESCRIPTION, "Induction generator induced voltage on phase A in p.u.",
00119 PT_complex, "Vrotor_B[V]", PADDR(Vrotor_B), PT_DESCRIPTION, "Induction generator induced voltage on phase B in p.u.",
00120 PT_complex, "Vrotor_C[V]", PADDR(Vrotor_C), PT_DESCRIPTION, "Induction generator induced voltage on phase C in p.u.",
00121 PT_complex, "Irotor_A[V]", PADDR(Irotor_A), PT_DESCRIPTION, "Induction generator induced current on phase A in p.u.",
00122 PT_complex, "Irotor_B[V]", PADDR(Irotor_B), PT_DESCRIPTION, "Induction generator induced current on phase B in p.u.",
00123 PT_complex, "Irotor_C[V]", PADDR(Irotor_C), PT_DESCRIPTION, "Induction generator induced current on phase C in p.u.",
00124
00125 PT_set, "phases", PADDR(phases), PT_DESCRIPTION, "Specifies which phases to connect to - currently not supported and assumes three-phase connection",
00126 PT_KEYWORD, "A",(set)PHASE_A,
00127 PT_KEYWORD, "B",(set)PHASE_B,
00128 PT_KEYWORD, "C",(set)PHASE_C,
00129 PT_KEYWORD, "N",(set)PHASE_N,
00130 PT_KEYWORD, "S",(set)PHASE_S,
00131 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00132 }
00133 }
00134
00135
00136 int windturb_dg::create(void)
00137 {
00138
00139
00140
00141 roughness_l = .055;
00142 ref_height = 10;
00143 Max_Vrotor = 1.2;
00144 Min_Vrotor = 0.8;
00145 Max_Ef = 1.2;
00146 Min_Ef = 0.8;
00147 avg_ws = 8;
00148
00149 time_advance = 3600;
00150
00151
00152 Ridealgas = 8.31447;
00153 Molar = 0.0289644;
00154
00155 std_air_temp = 0;
00156 std_air_press = 100000;
00157 Turbine_Model = GENERIC_SYNCH_LARGE;
00158 Gen_mode = CONSTANTP;
00159 Gen_status = ONLINE;
00160
00161 turbine_height = -9999;
00162 blade_diam = -9999;
00163 cut_in_ws = -9999;
00164 cut_out_ws = -9999;
00165 Cp_max = -9999;
00166 Cp_rated =-9999;
00167 ws_maxcp = -9999;
00168 ws_rated = -9999;
00169 CP_Data = CALCULATED;
00170
00171 pCircuit_V[0] = pCircuit_V[1] = pCircuit_V[2] = NULL;
00172 pLine_I[0] = pLine_I[1] = pLine_I[2] = NULL;
00173 value_Circuit_V[0] = value_Circuit_V[1] = value_Circuit_V[2] = complex(0.0,0.0);
00174 value_Line_I[0] = value_Line_I[1] = value_Line_I[2] = complex(0.0,0.0);
00175 parent_is_valid = false;
00176
00177 pPress = NULL;
00178 pTemp = NULL;
00179 pWS = NULL;
00180 value_Press = 0.0;
00181 value_Temp = 0.0;
00182 value_WS = 0.0;
00183 climate_is_valid = false;
00184
00185 return 1;
00186 }
00187
00188
00189
00190 int windturb_dg::init_climate()
00191 {
00192 OBJECT *hdr = OBJECTHDR(this);
00193
00194
00195 FINDLIST *climates = NULL;
00196
00197 climates = gl_find_objects(FL_NEW,FT_CLASS,SAME,"climate",FT_END);
00198 if (climates==NULL)
00199 {
00200
00201 climate_is_valid = false;
00202
00203 gl_warning("windturb_dg (id:%d)::init_climate(): no climate data found, using static data",hdr->id);
00204
00205
00206 value_WS = avg_ws;
00207 value_Press = std_air_press;
00208 value_Temp = std_air_temp;
00209 }
00210 else if (climates->hit_count>1)
00211 {
00212 gl_verbose("windturb_dg: %d climates found, using first one defined", climates->hit_count);
00213 }
00214
00215 if (climates!=NULL)
00216 {
00217 if (climates->hit_count==0)
00218 {
00219
00220 climate_is_valid = false;
00221
00222
00223 gl_warning("windturb_dg (id:%d)::init_climate(): no climate data found, using static data",hdr->id);
00224
00225
00226 value_WS = avg_ws;
00227 value_Press = std_air_press;
00228 value_Temp = std_air_temp;
00229 }
00230 else
00231 {
00232
00233 OBJECT *obj = gl_find_next(climates,NULL);
00234 if (obj->rank<=hdr->rank)
00235 gl_set_dependent(obj,hdr);
00236
00237 pWS = map_double_value(obj,"wind_speed");
00238 pPress = map_double_value(obj,"pressure");
00239 pTemp = map_double_value(obj,"temperature");
00240
00241
00242 climate_is_valid = true;
00243 }
00244 }
00245 return 1;
00246 }
00247
00248 int windturb_dg::init(OBJECT *parent)
00249 {
00250 OBJECT *obj = OBJECTHDR(this);
00251 double temp_double_value;
00252 gld_property *temp_property_pointer;
00253 set temp_phases_set;
00254 int temp_phases=0;
00255
00256 double ZB, SB, EB;
00257 complex tst, tst2, tst3, tst4;
00258
00259 switch (Turbine_Model) {
00260 case GENERIC_IND_LARGE:
00261 case GENERIC_SYNCH_LARGE:
00262 blade_diam = 82.5;
00263 turbine_height = 90;
00264 q = 3;
00265 Rated_VA = 1635000;
00266 Max_P = 1500000;
00267 Max_Q = 650000;
00268 Rated_V = 600;
00269 pf = 0.95;
00270 CP_Data = GENERAL_LARGE;
00271 cut_in_ws = 4;
00272 cut_out_ws = 25;
00273 Cp_max = 0.302;
00274 ws_maxcp = 7;
00275 Cp_rated = Cp_max-.05;
00276 ws_rated = 12.5;
00277 if (Turbine_Model == GENERIC_IND_LARGE) {
00278 Gen_type = INDUCTION;
00279 Rst = 0.12;
00280 Xst = 0.17;
00281 Rr = 0.12;
00282 Xr = 0.15;
00283 Rc = 999999;
00284 Xm = 9.0;
00285 }
00286 else if (Turbine_Model == GENERIC_SYNCH_LARGE) {
00287 Gen_type = SYNCHRONOUS;
00288 Rs = 0.05;
00289 Xs = 0.200;
00290 Rg = 0.000;
00291 Xg = 0.000;
00292 }
00293 break;
00294 case GENERIC_IND_MID:
00295 case GENERIC_SYNCH_MID:
00296 blade_diam = 23.2;
00297 turbine_height = 30;
00298 q = 0;
00299 Rated_VA = 156604;
00300 Max_P = 150000;
00301 Max_Q = 45000;
00302 Rated_V = 480;
00303 pf = 0.9;
00304 CP_Data = GENERAL_MID;
00305 cut_in_ws = 3.5;
00306 cut_out_ws = 25;
00307 Cp_max = 0.302;
00308 ws_maxcp = 7;
00309 Cp_rated = Cp_max-.05;
00310 ws_rated = 14.5;
00311 if (Turbine_Model == GENERIC_IND_MID) {
00312 Gen_type = INDUCTION;
00313 Rst = 0.12;
00314 Xst = 0.17;
00315 Rr = 0.12;
00316 Xr = 0.15;
00317 Rc = 999999;
00318 Xm = 9.0;
00319 }
00320 else if (Turbine_Model == GENERIC_SYNCH_MID) {
00321 Gen_type = SYNCHRONOUS;
00322 Rs = 0.05;
00323 Xs = 0.200;
00324 Rg = 0.000;
00325 Xg = 0.000;
00326 }
00327 break;
00328 case GENERIC_IND_SMALL:
00329 case GENERIC_SYNCH_SMALL:
00330 blade_diam = 5;
00331 turbine_height = 16;
00332 q = 0;
00333 Rated_VA = 6315;
00334 Max_P = 5800;
00335 Max_Q = 2500;
00336 Rated_V = 600;
00337 pf = 0.95;
00338 CP_Data = GENERAL_SMALL;
00339 cut_in_ws = 2.5;
00340 cut_out_ws = 25;
00341 Cp_max = 0.302;
00342 ws_maxcp = 7;
00343 Cp_rated = Cp_max-.05;
00344 ws_rated = 17;
00345 if (Turbine_Model == GENERIC_IND_SMALL) {
00346 Gen_type = INDUCTION;
00347 Rst = 0.12;
00348 Xst = 0.17;
00349 Rr = 0.12;
00350 Xr = 0.15;
00351 Rc = 999999;
00352 Xm = 9.0;
00353 }
00354 else if (Turbine_Model == GENERIC_SYNCH_SMALL) {
00355 Gen_type = SYNCHRONOUS;
00356 Rs = 0.05;
00357 Xs = 0.200;
00358 Rg = 0.000;
00359 Xg = 0.000;
00360 }
00361 break;
00362 case VESTAS_V82:
00363 turbine_height = 78;
00364 blade_diam = 82;
00365 Rated_VA = 1808000;
00366 Rated_V = 600;
00367 Max_P = 1650000;
00368 Max_Q = 740000;
00369 pf = 0.91;
00370 CP_Data = MANUF_TABLE;
00371 cut_in_ws = 3.5;
00372 cut_out_ws = 20;
00373 q = 2;
00374 Gen_type = SYNCHRONOUS;
00375 Rs = 0.025;
00376 Xs = 0.200;
00377 Rg = 0.000;
00378 Xg = 0.000;
00379 break;
00380 case GE_25MW:
00381 turbine_height = 100;
00382 blade_diam = 100;
00383 Rated_VA = 2727000;
00384 Rated_V = 690;
00385 Max_P = 2500000;
00386 Max_Q = 1090000;
00387 pf = 0.95;
00388 q = 3;
00389 CP_Data = GENERAL_LARGE;
00390 cut_in_ws = 3.5;
00391 cut_out_ws = 25;
00392 Cp_max = 0.28;
00393 Cp_rated = 0.275;
00394 ws_maxcp = 8.2;
00395 ws_rated = 12.5;
00396 Gen_type = SYNCHRONOUS;
00397 Rs = 0.035;
00398 Xs = 0.200;
00399 Rg = 0.000;
00400 Xg = 0.000;
00401 break;
00402 case BERGEY_10kW:
00403 turbine_height = 24;
00404 blade_diam = 7;
00405 Rated_VA = 10000;
00406 Rated_V = 360;
00407 Max_P = 15000;
00408 Max_Q = 4000;
00409 pf = 0.95;
00410 q = 0;
00411 CP_Data = GENERAL_SMALL;
00412 cut_in_ws = 2;
00413 cut_out_ws = 20;
00414 Cp_max = 0.28;
00415 Cp_rated = 0.275;
00416 ws_maxcp = 8.2;
00417 ws_rated = 12.5;
00418 Gen_type = SYNCHRONOUS;
00419 Rs = 0.05;
00420 Xs = 0.200;
00421 Rg = 0.000;
00422 Xg = 0.000;
00423 break;
00424 case USER_DEFINED:
00425
00426 CP_Data = USER_SPECIFY;
00427
00428 Gen_type = USER_TYPE;
00429 Rs = 0.2;
00430 Xs = 0.2;
00431 Rg = 0.1;
00432 Xg = 0;
00433
00434 if (turbine_height <=0)
00435 GL_THROW ("turbine height cannot have a negative or zero value.");
00436
00437
00438
00439 if (blade_diam <=0)
00440 GL_THROW ("blade diameter cannot have a negative or zero value.");
00441
00442
00443
00444 if (cut_in_ws <=0)
00445 GL_THROW ("cut in wind speed cannot have a negative or zero value.");
00446
00447
00448
00449 if (cut_out_ws <=0)
00450 GL_THROW ("cut out wind speed cannot have a negative or zero value.");
00451
00452
00453
00454 if (ws_rated <=0)
00455 GL_THROW ("rated wind speed cannot have a negative or zero value.");
00456
00457
00458
00459 if (ws_maxcp <=0)
00460 GL_THROW ("max cp cannot have a negative or zero value.");
00461
00462
00463
00464 break;
00465 default:
00466 GL_THROW("Unknown turbine model was specified");
00467
00468
00469
00470 }
00471
00472
00473 if (parent!=NULL)
00474 {
00475 if((parent->flags & OF_INIT) != OF_INIT){
00476 char objname[256];
00477 gl_verbose("windturb_dg::init(): deferring initialization on %s", gl_name(parent, objname, 255));
00478 return 2;
00479 }
00480 if (gl_object_isa(parent,"meter","powerflow"))
00481 {
00482
00483 parent_is_valid = true;
00484
00485
00486
00487 temp_property_pointer = new gld_property(parent,"phases");
00488
00489
00490 if ((temp_property_pointer->is_valid() != true) || (temp_property_pointer->is_set() != true))
00491 {
00492 GL_THROW("Unable to map phases property - ensure the parent is a meter or a node or a load");
00493
00494
00495
00496
00497
00498 }
00499
00500
00501 temp_phases_set = temp_property_pointer->get_set();
00502
00503
00504 delete temp_property_pointer;
00505
00506
00507 if ((temp_phases_set & PHASE_A) == PHASE_A)
00508 temp_phases += 1;
00509 if ((temp_phases_set & PHASE_B) == PHASE_B)
00510 temp_phases += 1;
00511 if ((temp_phases_set & PHASE_C) == PHASE_C)
00512 temp_phases += 1;
00513
00514 if (temp_phases < 3)
00515 GL_THROW("The wind turbine model currently only supports a 3-phase connection, please check meter connection");
00516
00517
00518
00519
00520
00521 temp_property_pointer = new gld_property(parent,"nominal_voltage");
00522
00523 if ((temp_property_pointer->is_valid() != true) || (temp_property_pointer->is_double() != true))
00524 {
00525 GL_THROW("Unable to map nominal_voltage property - ensure the parent is a powerflow:meter");
00526
00527
00528
00529
00530
00531 }
00532
00533
00534 temp_double_value = temp_property_pointer->get_double();
00535
00536
00537 delete temp_property_pointer;
00538
00539
00540 if ( fabs(1 - (temp_double_value * sqrt(3.0) / Rated_V) ) > 0.1 )
00541 gl_warning("windturb_dg (id:%d, name:%s): Rated generator voltage (LL: %.1f) and nominal voltage (LL: %.1f) of meter parent are different by greater than 10 percent. Odd behavior may occur.",obj->id,obj->name,Rated_V,temp_double_value * sqrt(3.0));
00542
00543
00544
00545
00546
00547
00548
00549
00550 pCircuit_V[0] = map_complex_value(parent,"voltage_A");
00551 pCircuit_V[1] = map_complex_value(parent,"voltage_B");
00552 pCircuit_V[2] = map_complex_value(parent,"voltage_C");
00553
00554 pLine_I[0] = map_complex_value(parent,"current_A");
00555 pLine_I[1] = map_complex_value(parent,"current_B");
00556 pLine_I[2] = map_complex_value(parent,"current_C");
00557 }
00558 else if (gl_object_isa(parent,"triplex_meter","powerflow"))
00559 {
00560 GL_THROW("The wind turbine model does currently support direct connection to single phase or triplex meters. Connect through a rectifier-inverter combination.");
00561
00562
00563
00564 }
00565 else if (gl_object_isa(parent,"rectifier","generators"))
00566 {
00567
00568 parent_is_valid = true;
00569
00570
00571 temp_property_pointer = new gld_property(parent,"V_Rated");
00572
00573 if ((temp_property_pointer->is_valid() != true) || (temp_property_pointer->is_double() != true))
00574 {
00575 GL_THROW("Unable to map V_Rated property - ensure the parent is a powerflow:meter");
00576
00577
00578
00579
00580
00581 }
00582
00583
00584 temp_double_value = temp_property_pointer->get_double();
00585
00586
00587 delete temp_property_pointer;
00588
00589
00590 if ( fabs(1 - (temp_double_value / Rated_V) ) > 0.1 )
00591 gl_warning("windturb_dg (id:%d, name:%s): Rated generator voltage (LL: %.1f) and nominal voltage (LL: %.1f) of meter parent are different by greater than 10 percent. Odd behavior may occur.",obj->id,obj->name,Rated_V,temp_double_value * sqrt(3.0));
00592
00593
00594
00595
00596
00597
00598
00599
00600 pCircuit_V[0] = map_complex_value(parent,"voltage_A");
00601 pCircuit_V[1] = map_complex_value(parent,"voltage_B");
00602 pCircuit_V[2] = map_complex_value(parent,"voltage_C");
00603
00604 pLine_I[0] = map_complex_value(parent,"current_A");
00605 pLine_I[1] = map_complex_value(parent,"current_B");
00606 pLine_I[2] = map_complex_value(parent,"current_C");
00607 }
00608 else
00609 {
00610 GL_THROW("windturb_dg (id:%d): Invalid parent object",obj->id);
00611
00612
00613
00614 }
00615 }
00616 else
00617 {
00618 gl_warning("windturb_dg:%d %s", obj->id, parent==NULL?"has no parent meter defined":"parent is not a meter");
00619
00620
00621 parent_is_valid = false;
00622
00623
00624
00625
00626 temp_double_value = Rated_V/sqrt(3.0);
00627
00628
00629 value_Circuit_V[0].SetPolar(temp_double_value,0.0);
00630 value_Circuit_V[1].SetPolar(temp_double_value,-2.0/3.0*PI);
00631 value_Circuit_V[2].SetPolar(temp_double_value,2.0/3.0*PI);
00632 }
00633
00634 if (Gen_status==OFFLINE)
00635 {
00636 gl_warning("init_windturb_dg (id:%d,name:%s): Generator is out of service!", obj->id,obj->name);
00637 }
00638
00639 if (Gen_type == SYNCHRONOUS || Gen_type == INDUCTION)
00640 {
00641 if (Gen_mode == CONSTANTE)
00642 {
00643 gl_warning("init_windturb_dg (id:%d,name:%s): Synchronous and induction generators in constant voltage mode has not been fully tested and my not work properly.", obj->id,obj->name);
00644 }
00645 }
00646
00647 if (Rated_VA!=0.0)
00648 SB = Rated_VA/3;
00649 if (Rated_V!=0.0)
00650 EB = Rated_V/sqrt(3.0);
00651 if (SB!=0.0)
00652 ZB = EB*EB/SB;
00653 else
00654 GL_THROW("Generator power capacity not specified!");
00655
00656
00657
00658
00659 if (Gen_type == INDUCTION)
00660 {
00661 complex Zrotor(Rr,Xr);
00662 complex Zmag = complex(Rc*Xm*Xm/(Rc*Rc + Xm*Xm),Rc*Rc*Xm/(Rc*Rc + Xm*Xm));
00663 complex Zstator(Rst,Xst);
00664
00665
00666 IndTPMat[0][0] = (Zmag + Zstator)/Zmag;
00667 IndTPMat[0][1] = Zrotor + Zstator + Zrotor*Zstator/Zmag;
00668 IndTPMat[1][0] = complex(1,0) / Zmag;
00669 IndTPMat[1][1] = (Zmag + Zrotor) / Zmag;
00670 }
00671
00672 else if (Gen_type == SYNCHRONOUS)
00673 {
00674 double Real_Rs = Rs * ZB;
00675 double Real_Xs = Xs * ZB;
00676 double Real_Rg = Rg * ZB;
00677 double Real_Xg = Xg * ZB;
00678 tst = complex(Real_Rg,Real_Xg);
00679 tst2 = complex(Real_Rs,Real_Xs);
00680 AMx[0][0] = tst2 + tst;
00681 AMx[1][1] = tst2 + tst;
00682 AMx[2][2] = tst2 + tst;
00683 AMx[0][1] = AMx[0][2] = AMx[1][0] = AMx[1][2] = AMx[2][0] = AMx[2][1] = tst;
00684 tst3 = (complex(1,0) + complex(2,0)*tst/tst2)/(tst2 + complex(3,0)*tst);
00685 tst4 = (-tst/tst2)/(tst2 + tst);
00686 invAMx[0][0] = tst3;
00687 invAMx[1][1] = tst3;
00688 invAMx[2][2] = tst3;
00689 invAMx[0][1] = AMx[0][2] = AMx[1][0] = AMx[1][2] = AMx[2][0] = AMx[2][1] = tst4;
00690 }
00691 else
00692 GL_THROW("Unknown generator type specified");
00693
00694
00695
00696
00697 init_climate();
00698
00699 return 1;
00700 }
00701
00702
00703 TIMESTAMP windturb_dg::presync(TIMESTAMP t0, TIMESTAMP t1)
00704 {
00705
00706 return TS_NEVER;
00707 }
00708
00709 TIMESTAMP windturb_dg::sync(TIMESTAMP t0, TIMESTAMP t1)
00710 {
00711 TIMESTAMP t2 = TS_NEVER;
00712 double Pwind, Pmech, detCp, F, G, gearbox_eff;
00713 double matCp[2][3];
00714
00715 store_last_current = current_A.Mag() + current_B.Mag() + current_C.Mag();
00716
00717
00718 if (climate_is_valid == true)
00719 {
00720 value_Press = pPress->get_double();
00721 value_Temp = pTemp->get_double();
00722 value_WS = pWS->get_double();
00723 }
00724
00725
00726
00727 air_dens = (value_Press*100) * Molar / (Ridealgas * ( (value_Temp - 32)*5/9 + 273.15));
00728
00729
00730 if(ref_height == roughness_l){
00731 ref_height = roughness_l+0.001;
00732 }
00733 WSadj = value_WS * log(turbine_height/roughness_l)/log(ref_height/roughness_l);
00734
00735
00736
00737
00738
00739 Pwind = 0.5 * (air_dens) * PI * pow(blade_diam/2,2) * pow(WSadj,3);
00740
00741 if (CP_Data == GENERAL_LARGE || CP_Data == GENERAL_MID || CP_Data == GENERAL_SMALL)
00742 {
00743 if (WSadj <= cut_in_ws)
00744 {
00745 Cp = 0;
00746 }
00747
00748 else if (WSadj > cut_out_ws)
00749 {
00750 Cp = 0;
00751 }
00752
00753 else if(WSadj > ws_rated)
00754 {
00755 Cp = Cp_rated * pow(ws_rated,3) / pow(WSadj,3);
00756 }
00757 else
00758 {
00759 if (WSadj == 0 || WSadj <= cut_in_ws || WSadj >= cut_out_ws)
00760 {
00761 Cp = 0;
00762 }
00763 else {
00764 matCp[0][0] = pow((ws_maxcp/cut_in_ws - 1),2);
00765 matCp[0][1] = pow((ws_maxcp/cut_in_ws - 1),3);
00766 matCp[0][2] = 1;
00767 matCp[1][0] = pow((ws_maxcp/ws_rated - 1),2);
00768 matCp[1][1] = pow((ws_maxcp/ws_rated - 1),3);
00769 matCp[1][2] = 1 - Cp_rated/Cp_max;
00770 detCp = matCp[0][0]*matCp[1][1] - matCp[0][1]*matCp[1][0];
00771
00772 F = (matCp[0][2]*matCp[1][1] - matCp[0][1]*matCp[1][2])/detCp;
00773 G = (matCp[0][0]*matCp[1][2] - matCp[0][2]*matCp[1][0])/detCp;
00774
00775 Cp = Cp_max*(1 - F*pow((ws_maxcp/WSadj - 1),2) - G*pow((ws_maxcp/WSadj - 1),3));
00776 }
00777 }
00778 }
00779 else if (CP_Data == MANUF_TABLE)
00780 {
00781 switch (Turbine_Model) {
00782 case VESTAS_V82:
00783 if (WSadj <= cut_in_ws || WSadj >= cut_out_ws)
00784 {
00785 Cp = 0;
00786 }
00787 else
00788 {
00789
00790 double z = (WSadj - 10.5)/5.9161;
00791
00792
00793 Cp = -0.08609*pow(z,10) + 0.078599*pow(z,9) + 0.50509*pow(z,8) - 0.45466*pow(z,7) - 0.94154*pow(z,6) + 0.77922*pow(z,5) + 0.59082*pow(z,4) - 0.23196*pow(z,3) - 0.25009*pow(z,2) - 0.24282*z + 0.37502;
00794 }
00795 break;
00796 default:
00797 GL_THROW("Coefficient of Performance model not determined.");
00798 }
00799
00800 }
00801 else if (CP_Data == CALCULATED)
00802 {
00803 matCp[0][0] = pow((ws_maxcp/cut_in_ws - 1),2);
00804 matCp[0][1] = pow((ws_maxcp/cut_in_ws - 1),3);
00805 matCp[0][2] = 1;
00806 matCp[1][0] = pow((ws_maxcp/ws_rated - 1),2);
00807 matCp[1][1] = pow((ws_maxcp/ws_rated - 1),3);
00808 matCp[1][2] = 1 - Cp_rated/Cp_max;
00809 detCp = matCp[0][0]*matCp[1][1] - matCp[0][1]*matCp[1][0];
00810
00811 F = (matCp[0][2]*matCp[1][1] - matCp[0][1]*matCp[1][2])/detCp;
00812 G = (matCp[0][0]*matCp[1][2] - matCp[0][2]*matCp[1][0])/detCp;
00813
00814 Cp = Cp_max*(1 - F*pow((ws_maxcp/WSadj - 1),2) - G*pow((ws_maxcp/WSadj - 1),3));
00815 }
00816 else
00817 {
00818 GL_THROW("CP_Data not defined.");
00819 }
00820
00822
00823 Pmech = Pwind * Cp;
00824
00825 if (Pmech != 0)
00826 {
00827 gearbox_eff = 1 - (q*.01*Rated_VA / Pmech);
00828
00829 if (gearbox_eff < .1)
00830 {
00831 gearbox_eff = .1;
00832 }
00833
00834 Pmech = Pwind * Cp * gearbox_eff;
00835 }
00836
00837 Pconv = 1 * Pmech;
00838
00839 if (Gen_status==ONLINE)
00840 {
00841 int k;
00842
00843
00844 if (parent_is_valid == true)
00845 {
00846 value_Circuit_V[0] = pCircuit_V[0]->get_complex();
00847 value_Circuit_V[1] = pCircuit_V[1]->get_complex();
00848 value_Circuit_V[2] = pCircuit_V[2]->get_complex();
00849 }
00850
00851 voltage_A = value_Circuit_V[0];
00852 voltage_B = value_Circuit_V[1];
00853 voltage_C = value_Circuit_V[2];
00854 double Pconva = 0.0;
00855 double Pconvb = 0.0;
00856 double Pconvc = 0.0;
00857 if((voltage_A.Mag() + voltage_B.Mag() + voltage_C.Mag()) > 1e-9){
00858 Pconva = (voltage_A.Mag() / (voltage_A.Mag() + voltage_B.Mag() + voltage_C.Mag()))*Pconv;
00859 Pconvb = (voltage_B.Mag() / (voltage_A.Mag() + voltage_B.Mag() + voltage_C.Mag()))*Pconv;
00860 Pconvc = (voltage_C.Mag() / (voltage_A.Mag() + voltage_B.Mag() + voltage_C.Mag()))*Pconv;
00861 }
00862
00863 if (Gen_type == INDUCTION)
00864 {
00865 Pconva = Pconva/Rated_VA;
00866 Pconvb = Pconvb/Rated_VA;
00867 Pconvc = Pconvc/Rated_VA;
00868
00869 Vapu = voltage_A/(Rated_V/sqrt(3.0));
00870 Vbpu = voltage_B/(Rated_V/sqrt(3.0));
00871 Vcpu = voltage_C/(Rated_V/sqrt(3.0));
00872
00873 Vrotor_A = Vapu;
00874 Vrotor_B = Vbpu;
00875 Vrotor_C = Vcpu;
00876
00877 complex detTPMat = IndTPMat[1][1]*IndTPMat[0][0] - IndTPMat[1][0]*IndTPMat[0][1];
00878
00879 if (Pconv > 0)
00880 {
00881 switch (Gen_mode)
00882 {
00883 case CONSTANTE:
00884 for(k = 0; k < 6; k++)
00885 {
00886 Irotor_A = (~((complex(Pconva,0)/Vrotor_A)));
00887 Irotor_B = (~((complex(Pconvb,0)/Vrotor_B)));
00888 Irotor_C = (~((complex(Pconvc,0)/Vrotor_C)));
00889
00890 Iapu = IndTPMat[1][0]*Vrotor_A + IndTPMat[1][1]*Irotor_A;
00891 Ibpu = IndTPMat[1][0]*Vrotor_B + IndTPMat[1][1]*Irotor_B;
00892 Icpu = IndTPMat[1][0]*Vrotor_C + IndTPMat[1][1]*Irotor_C;
00893
00894 Vrotor_A = complex(1,0)/detTPMat * (IndTPMat[1][1]*Vapu - IndTPMat[0][1]*Iapu);
00895 Vrotor_B = complex(1,0)/detTPMat * (IndTPMat[1][1]*Vbpu - IndTPMat[0][1]*Ibpu);
00896 Vrotor_C = complex(1,0)/detTPMat * (IndTPMat[1][1]*Vcpu - IndTPMat[0][1]*Icpu);
00897
00898 Vrotor_A = Vrotor_A * Max_Vrotor / Vrotor_A.Mag();
00899 Vrotor_B = Vrotor_B * Max_Vrotor / Vrotor_B.Mag();
00900 Vrotor_C = Vrotor_C * Max_Vrotor / Vrotor_C.Mag();
00901 }
00902 break;
00903 case CONSTANTPQ:
00904 double last_Ipu = 0;
00905 double current_Ipu = 1;
00906 unsigned int temp_ind = 1;
00907
00908 while ( fabs( (last_Ipu-current_Ipu)/current_Ipu) > 0.005 )
00909 {
00910 last_Ipu = current_Ipu;
00911
00912 Irotor_A = -(~complex(-Pconva/Vrotor_A.Mag()*cos(Vrotor_A.Arg()),Pconva/Vrotor_A.Mag()*sin(Vrotor_A.Arg())));
00913 Irotor_B = -(~complex(-Pconvb/Vrotor_B.Mag()*cos(Vrotor_B.Arg()),Pconvb/Vrotor_B.Mag()*sin(Vrotor_B.Arg())));
00914 Irotor_C = -(~complex(-Pconvc/Vrotor_C.Mag()*cos(Vrotor_C.Arg()),Pconvc/Vrotor_C.Mag()*sin(Vrotor_C.Arg())));
00915
00916 Iapu = IndTPMat[1][0]*Vrotor_A - IndTPMat[1][1]*Irotor_A;
00917 Ibpu = IndTPMat[1][0]*Vrotor_B - IndTPMat[1][1]*Irotor_B;
00918 Icpu = IndTPMat[1][0]*Vrotor_C - IndTPMat[1][1]*Irotor_C;
00919
00920 Vrotor_A = complex(1,0)/detTPMat * (IndTPMat[1][1]*Vapu - IndTPMat[0][1]*Iapu);
00921 Vrotor_B = complex(1,0)/detTPMat * (IndTPMat[1][1]*Vbpu - IndTPMat[0][1]*Ibpu);
00922 Vrotor_C = complex(1,0)/detTPMat * (IndTPMat[1][1]*Vcpu - IndTPMat[0][1]*Icpu);
00923
00924 current_Ipu = Iapu.Mag() + Ibpu.Mag() + Icpu.Mag();
00925
00926 temp_ind += 1;
00927 if (temp_ind > 100)
00928 {
00929 OBJECT *obj = OBJECTHDR(this);
00930
00931 gl_warning("windturb_dg (id:%d,name:%s): internal iteration limit reached, breaking out of loop. Injected current may not be solved sufficiently.",obj->id,obj->name);
00932
00933
00934
00935
00936
00937
00938
00939 break;
00940 }
00941 }
00942 break;
00943 }
00944
00945
00946 current_A = Iapu * Rated_VA/(Rated_V/sqrt(3.0));
00947 current_B = Ibpu * Rated_VA/(Rated_V/sqrt(3.0));
00948 current_C = Icpu * Rated_VA/(Rated_V/sqrt(3.0));
00949 }
00950 else
00951 {
00952 current_A = 0;
00953 current_B = 0;
00954 current_C = 0;
00955 }
00956 }
00957
00958 else if (Gen_type == SYNCHRONOUS)
00959 {
00960 double Mxef, Mnef, PoutA, PoutB, PoutC, QoutA, QoutB, QoutC;
00961 complex SoutA, SoutB, SoutC;
00962 complex lossesA, lossesB, lossesC;
00963
00964 Mxef = Max_Ef * Rated_V/sqrt(3.0);
00965 Mnef = Min_Ef * Rated_V/sqrt(3.0);
00966
00967
00968 if (Gen_mode == CONSTANTE)
00969 {
00970 current_A = invAMx[0][0]*(voltage_A - EfA) + invAMx[0][1]*(voltage_B - EfB) + invAMx[0][2]*(voltage_C - EfC);
00971 current_B = invAMx[1][0]*(voltage_A - EfA) + invAMx[1][1]*(voltage_B - EfB) + invAMx[1][2]*(voltage_C - EfC);
00972 current_C = invAMx[2][0]*(voltage_A - EfA) + invAMx[2][1]*(voltage_B - EfB) + invAMx[2][2]*(voltage_C - EfC);
00973
00974 SoutA = -voltage_A * (~(current_A));
00975 SoutB = -voltage_B * (~(current_B));
00976 SoutC = -voltage_C * (~(current_C));
00977
00978 }
00979
00980 else if (Gen_mode == CONSTANTP)
00981 {
00982
00983 if (Pconva > 1.025*Max_P/3) {
00984 Pconva = 1.025*Max_P/3;
00985 }
00986 if (Pconvb > 1.025*Max_P/3) {
00987 Pconvb = 1.025*Max_P/3;
00988 }
00989 if (Pconvc > 1.025*Max_P/3) {
00990 Pconvc = 1.025*Max_P/3;
00991 }
00992 if(voltage_A.Mag() > 0.0){
00993 current_A = -(~(complex(Pconva,Pconva*tan(acos(pf)))/voltage_A));
00994 } else {
00995 current_A = complex(0.0,0.0);
00996 }
00997 if(voltage_B.Mag() > 0.0){
00998 current_B = -(~(complex(Pconvb,Pconvb*tan(acos(pf)))/voltage_B));
00999 } else {
01000 current_B = complex(0.0,0.0);
01001 }
01002 if(voltage_B.Mag() > 0.0){
01003 current_C = -(~(complex(Pconvc,Pconvc*tan(acos(pf)))/voltage_C));
01004 } else {
01005 current_C = complex(0.0,0.0);
01006 }
01007
01008 if (Pconv > 0)
01009 {
01010 double last_current = 0;
01011 double current_current = current_A.Mag() + current_B.Mag() + current_C.Mag();
01012 unsigned int temp_count = 1;
01013
01014 while ( fabs( (last_current-current_current)/current_current) > 0.005 )
01015 {
01016 last_current = current_current;
01017
01018 PoutA = Pconva - current_A.Mag()*current_A.Mag()*(AMx[0][0] - AMx[0][1]).Re();
01019 PoutB = Pconvb - current_B.Mag()*current_B.Mag()*(AMx[1][1] - AMx[0][1]).Re();
01020 PoutC = Pconvc - current_C.Mag()*current_C.Mag()*(AMx[2][2] - AMx[0][1]).Re();
01021
01022 QoutA = pf/fabs(pf)*PoutA*sin(acos(pf));
01023 QoutB = pf/fabs(pf)*PoutB*sin(acos(pf));
01024 QoutC = pf/fabs(pf)*PoutC*sin(acos(pf));
01025 if(voltage_A.Mag() > 0.0){
01026 current_A = -(~(complex(PoutA,QoutA)/voltage_A));
01027 } else {
01028 current_A = complex(0.0,0.0);
01029 }
01030 if(voltage_B.Mag() > 0.0){
01031 current_B = -(~(complex(PoutB,QoutB)/voltage_B));
01032 } else {
01033 current_B = complex(0.0,0.0);
01034 }
01035 if(voltage_C.Mag() > 0.0){
01036 current_C = -(~(complex(PoutC,QoutC)/voltage_C));
01037 } else {
01038 current_C = complex(0.0,0.0);
01039 }
01040
01041 current_current = current_A.Mag() + current_B.Mag() + current_C.Mag();
01042
01043 temp_count += 1;
01044
01045 if ( temp_count > 100 )
01046 {
01047 OBJECT *obj = OBJECTHDR(this);
01048
01049 gl_warning("windturb_dg (id:%d,name:%s): internal iteration limit reached, breaking out of loop. Injected current may not be solved sufficiently.",obj->id,obj->name);
01050
01051
01052
01053
01054
01055
01056
01057 break;
01058 }
01059 }
01060 gl_debug("windturb_dg iteration count = %d",temp_count);
01061 }
01062 else
01063 {
01064 current_A = 0;
01065 current_B = 0;
01066 current_C = 0;
01067 }
01068
01069 EfA = voltage_A - (AMx[0][0] - AMx[0][1])*current_A - AMx[0][2]*(current_A + current_B + current_C);
01070 EfB = voltage_B - (AMx[1][1] - AMx[1][0])*current_A - AMx[1][2]*(current_A + current_B + current_C);
01071 EfC = voltage_C - (AMx[2][2] - AMx[2][0])*current_A - AMx[2][1]*(current_A + current_B + current_C);
01072 }
01073 else
01074 GL_THROW("Unknown generator mode");
01075 }
01076
01077
01078 double PowerA, PowerB, PowerC, QA, QB, QC;
01079
01080 PowerA = -voltage_A.Mag()*current_A.Mag()*cos(voltage_A.Arg() - current_A.Arg());
01081 PowerB = -voltage_B.Mag()*current_B.Mag()*cos(voltage_B.Arg() - current_B.Arg());
01082 PowerC = -voltage_C.Mag()*current_C.Mag()*cos(voltage_C.Arg() - current_C.Arg());
01083
01084 QA = -voltage_A.Mag()*current_A.Mag()*sin(voltage_A.Arg() - current_A.Arg());
01085 QB = -voltage_B.Mag()*current_B.Mag()*sin(voltage_B.Arg() - current_B.Arg());
01086 QC = -voltage_C.Mag()*current_C.Mag()*sin(voltage_C.Arg() - current_C.Arg());
01087
01088 power_A = complex(PowerA,QA);
01089 power_B = complex(PowerB,QB);
01090 power_C = complex(PowerC,QC);
01091
01092 TotalRealPow = PowerA + PowerB + PowerC;
01093 TotalReacPow = QA + QB + QC;
01094
01095 GenElecEff = TotalRealPow/Pconv * 100;
01096
01097 Wind_Speed = WSadj;
01098
01099
01100 value_Line_I[0] = current_A;
01101 value_Line_I[1] = current_B;
01102 value_Line_I[2] = current_C;
01103
01104
01105 if (parent_is_valid == true)
01106 {
01107 push_complex_powerflow_values();
01108 }
01109 }
01110
01111 else
01112 {
01113 current_A = 0;
01114 current_B = 0;
01115 current_C = 0;
01116
01117 power_A = complex(0,0);
01118 power_B = complex(0,0);
01119 power_C = complex(0,0);
01120 }
01121
01122
01123
01124
01125 double store_current_current = current_A.Mag() + current_B.Mag() + current_C.Mag();
01126 if ( fabs((store_current_current - store_last_current) / store_last_current) > 0.005 )
01127 t2 = t1;
01128
01129 return t2;
01130 }
01131
01132 TIMESTAMP windturb_dg::postsync(TIMESTAMP t0, TIMESTAMP t1)
01133 {
01134 TIMESTAMP t2 = TS_NEVER;
01135
01136
01137
01138 value_Line_I[0] = -current_A;
01139 value_Line_I[1] = -current_B;
01140 value_Line_I[2] = -current_C;
01141
01142
01143 if (parent_is_valid == true)
01144 {
01145 push_complex_powerflow_values();
01146 }
01147
01148 return t2;
01149 }
01150
01151
01152 gld_property *windturb_dg::map_complex_value(OBJECT *obj, char *name)
01153 {
01154 gld_property *pQuantity;
01155 OBJECT *objhdr = OBJECTHDR(this);
01156
01157
01158 pQuantity = new gld_property(obj,name);
01159
01160
01161 if ((pQuantity->is_valid() != true) || (pQuantity->is_complex() != true))
01162 {
01163 GL_THROW("windturb_dg:%d %s - Unable to map property %s from object:%d %s",objhdr->id,(objhdr->name ? objhdr->name : "Unnamed"),name,obj->id,(obj->name ? obj->name : "Unnamed"));
01164
01165
01166
01167
01168 }
01169
01170
01171 return pQuantity;
01172 }
01173
01174
01175 gld_property *windturb_dg::map_double_value(OBJECT *obj, char *name)
01176 {
01177 gld_property *pQuantity;
01178 OBJECT *objhdr = OBJECTHDR(this);
01179
01180
01181 pQuantity = new gld_property(obj,name);
01182
01183
01184 if ((pQuantity->is_valid() != true) || (pQuantity->is_double() != true))
01185 {
01186 GL_THROW("windturb_dg:%d %s - Unable to map property %s from object:%d %s",objhdr->id,(objhdr->name ? objhdr->name : "Unnamed"),name,obj->id,(obj->name ? obj->name : "Unnamed"));
01187
01188
01189
01190
01191 }
01192
01193
01194 return pQuantity;
01195 }
01196
01197
01198 void windturb_dg::push_complex_powerflow_values(void)
01199 {
01200 complex temp_complex_val;
01201 gld_wlock *test_rlock;
01202 int indexval;
01203
01204
01205 for (indexval=0; indexval<3; indexval++)
01206 {
01207
01208
01209 temp_complex_val = pLine_I[indexval]->get_complex();
01210
01211
01212 temp_complex_val += value_Line_I[indexval];
01213
01214
01215 pLine_I[indexval]->setp<complex>(temp_complex_val,*test_rlock);
01216 }
01217 }
01218
01220
01222
01223 EXPORT int create_windturb_dg(OBJECT **obj, OBJECT *parent)
01224 {
01225 try
01226 {
01227 *obj = gl_create_object(windturb_dg::oclass);
01228 if (*obj!=NULL)
01229 {
01230 windturb_dg *my = OBJECTDATA(*obj,windturb_dg);
01231 gl_set_parent(*obj,parent);
01232 return my->create();
01233 }
01234 else
01235 return 0;
01236 }
01237 CREATE_CATCHALL(windturb_dg);
01238 }
01239
01240
01241
01242 EXPORT int init_windturb_dg(OBJECT *obj, OBJECT *parent)
01243 {
01244 try
01245 {
01246 if (obj!=NULL)
01247 return OBJECTDATA(obj,windturb_dg)->init(parent);
01248 else
01249 return 0;
01250 }
01251 INIT_CATCHALL(windturb_dg);
01252 }
01253
01254 EXPORT TIMESTAMP sync_windturb_dg(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
01255 {
01256 TIMESTAMP t1 = TS_NEVER;
01257 windturb_dg *my = OBJECTDATA(obj,windturb_dg);
01258 try
01259 {
01260 switch (pass) {
01261 case PC_PRETOPDOWN:
01262 t1 = my->presync(obj->clock,t0);
01263 break;
01264 case PC_BOTTOMUP:
01265 t1 = my->sync(obj->clock,t0);
01266 break;
01267 case PC_POSTTOPDOWN:
01268 t1 = my->postsync(obj->clock,t0);
01269 break;
01270 default:
01271 GL_THROW("invalid pass request (%d)", pass);
01272 break;
01273 }
01274 }
01275 SYNC_CATCHALL(windturb_dg);
01276 return t1;
01277 }
01278
01279
01280
01281
01282
01283
01284
01285
01286