00001
00010 #include <stdlib.h>
00011 #include <stdio.h>
00012 #include <errno.h>
00013 #include <math.h>
00014
00015 #include "generators.h"
00016
00017 #include "power_electronics.h"
00018 #include "inverter.h"
00019
00020 #define DEFAULT 1.0;
00021
00022
00023 CLASS *inverter::oclass = NULL;
00024 inverter *inverter::defaults = NULL;
00025
00026 static PASSCONFIG passconfig = PC_BOTTOMUP|PC_POSTTOPDOWN;
00027 static PASSCONFIG clockpass = PC_BOTTOMUP;
00028
00029
00030 inverter::inverter(MODULE *module)
00031 {
00032 if (oclass==NULL)
00033 {
00034 oclass = gl_register_class(module,"inverter",sizeof(inverter),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN);
00035 if (oclass==NULL)
00036 GL_THROW("unable to register object class implemented by %s", __FILE__);
00037
00038 if (gl_publish_variable(oclass,
00039
00040 PT_enumeration,"inverter_type",PADDR(inverter_type_v),
00041 PT_KEYWORD,"TWO_PULSE",TWO_PULSE,
00042 PT_KEYWORD,"SIX_PULSE",SIX_PULSE,
00043 PT_KEYWORD,"TWELVE_PULSE",TWELVE_PULSE,
00044 PT_KEYWORD,"PWM",PWM,
00045
00046 PT_enumeration,"generator_status",PADDR(gen_status_v),
00047 PT_KEYWORD,"OFFLINE",OFFLINE,
00048 PT_KEYWORD,"ONLINE",ONLINE,
00049
00050 PT_enumeration,"generator_mode",PADDR(gen_mode_v),
00051 PT_KEYWORD,"UNKNOWN",UNKNOWN,
00052 PT_KEYWORD,"CONSTANT_V",CONSTANT_V,
00053 PT_KEYWORD,"CONSTANT_PQ",CONSTANT_PQ,
00054 PT_KEYWORD,"CONSTANT_PF",CONSTANT_PF,
00055 PT_KEYWORD,"SUPPLY_DRIVEN",SUPPLY_DRIVEN,
00056
00057 PT_complex, "V_In[V]",PADDR(V_In),
00058 PT_complex, "I_In[A]",PADDR(I_In),
00059 PT_complex, "VA_In[VA]", PADDR(VA_In),
00060 PT_complex, "Vdc[V]", PADDR(Vdc),
00061 PT_complex, "phaseA_V_Out[V]", PADDR(phaseA_V_Out),
00062 PT_complex, "phaseB_V_Out[V]", PADDR(phaseB_V_Out),
00063 PT_complex, "phaseC_V_Out[V]", PADDR(phaseC_V_Out),
00064 PT_complex, "phaseA_I_Out[V]", PADDR(phaseA_I_Out),
00065 PT_complex, "phaseB_I_Out[V]", PADDR(phaseB_I_Out),
00066 PT_complex, "phaseC_I_Out[V]", PADDR(phaseC_I_Out),
00067 PT_complex, "power_A[VA]", PADDR(power_A),
00068 PT_complex, "power_B[VA]", PADDR(power_B),
00069 PT_complex, "power_C[VA]", PADDR(power_C),
00070 PT_double, "P_Out[VA]", PADDR(P_Out),
00071 PT_double, "Q_Out[VAr]", PADDR(Q_Out),
00072 PT_double, "power_factor[unit]", PADDR(power_factor),
00073
00074 PT_set, "phases", PADDR(phases),
00075 PT_KEYWORD, "A",(set)PHASE_A,
00076 PT_KEYWORD, "B",(set)PHASE_B,
00077 PT_KEYWORD, "C",(set)PHASE_C,
00078 PT_KEYWORD, "N",(set)PHASE_N,
00079 PT_KEYWORD, "S",(set)PHASE_S,
00080 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00081 defaults = this;
00082 memset(this,0,sizeof(inverter));
00083
00084
00085 P_Out = 1200;
00086 Q_Out = 500;
00087 V_In_Set_A = complex(480,0);
00088 V_In_Set_B = complex(-240, 415.69);
00089 V_In_Set_C = complex(-240,-415.69);
00090 V_Set_A = 240;
00091 V_Set_B = 240;
00092 V_Set_C = 240;
00093 margin = 10;
00094 I_out_prev = 0;
00095 I_step_max = 100;
00096 internal_losses = 0;
00097 C_Storage_In = 0;
00098 power_factor = 1;
00099
00100
00101 Rated_kW = 10;
00102 Max_P = 10;
00103 Min_P = 0;
00104 Max_Q = 10;
00105 Min_Q = 10;
00106 Rated_kVA = 15;
00107 Rated_kV = 10;
00108 Rinternal = 0.035;
00109 Rload = 1;
00110 Rtotal = 0.05;
00111 Rground = 0.03;
00112 Rground_storage = 0.05;
00113 Vdc = 480;
00114
00115 Cinternal = 0;
00116 Cground = 0;
00117 Ctotal = 0;
00118 Linternal = 0;
00119 Lground = 0;
00120 Ltotal = 0;
00121 filter_120HZ = true;
00122 filter_180HZ = true;
00123 filter_240HZ = true;
00124 pf_in = 0;
00125 pf_out = 1;
00126 number_of_phases_in = 0;
00127 phaseAIn = false;
00128 phaseBIn = false;
00129 phaseCIn = false;
00130 phaseAOut = true;
00131 phaseBOut = true;
00132 phaseCOut = true;
00133
00134 last_current[0] = last_current[1] = last_current[2] = last_current[3] = 0.0;
00135
00136 switch_type_choice = IDEAL_SWITCH;
00137 filter_type_v = BAND_PASS;
00138 filter_imp_v = IDEAL_FILTER;
00139 power_in = DC;
00140 power_out = AC;
00141
00142 efficiency = 0;
00143 }
00144 }
00145
00146
00147 int inverter::create(void)
00148 {
00149 memcpy(this,defaults,sizeof(*this));
00150
00151 return 1;
00152 }
00153
00154
00155 int inverter::init(OBJECT *parent)
00156 {
00157 OBJECT *obj = OBJECTHDR(this);
00158
00159
00160 static complex default_line123_voltage[3], default_line1_current[3];
00161 int i;
00162
00163
00164
00165 if (parent!=NULL && gl_object_isa(parent,"meter"))
00166 {
00167
00168 parent_string = "meter";
00169 struct {
00170 complex **var;
00171 char *varname;
00172 }
00173 map[] = {
00174
00175 {&pCircuit_V, "voltage_A"},
00176 {&pLine_I, "current_A"},
00177 };
00179
00180 for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
00181 *(map[i].var) = get_complex(parent,map[i].varname);
00182
00183 node *par = OBJECTDATA(parent, node);
00184 number_of_phases_out = 0;
00185 if (par->has_phase(PHASE_A))
00186 number_of_phases_out += 1;
00187 if (par->has_phase(PHASE_B))
00188 number_of_phases_out += 1;
00189 if (par->has_phase(PHASE_C))
00190 number_of_phases_out += 1;
00191 }
00192 else if (parent!=NULL && gl_object_isa(parent,"triplex_meter"))
00193 {
00194 parent_string = "triplex_meter";
00195 number_of_phases_out = 4;
00196 struct {
00197 complex **var;
00198 char *varname;
00199 }
00200 map[] = {
00201
00202 {&pCircuit_V, "voltage_12"},
00203 {&pLine_I, "current_1"},
00204 {&pLine12, "current_12"},
00206 };
00207
00208 for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
00209 {
00210 if ((*(map[i].var) = get_complex(parent,map[i].varname))==NULL)
00211 {
00212 GL_THROW("%s (%s:%d) does not implement triplex_meter variable %s for %s (house:%d)",
00213
00214
00215
00216
00217
00218
00219 parent->name?parent->name:"unnamed object", parent->oclass->name, parent->id, map[i].varname, obj->name?obj->name:"unnamed", obj->id);
00220 }
00221 }
00222 }
00223 else if ((parent != NULL && strcmp(parent->oclass->name,"meter") != 0)||(parent != NULL && strcmp(parent->oclass->name,"triplex_meter") != 0))
00224 {
00225 throw("Inverter must have a meter or triplex meter as it's parent");
00226
00227
00228
00229
00230
00231 }
00232 else
00233 {
00234 parent_string = "none";
00235 number_of_phases_out = 3;
00236 struct {
00237 complex **var;
00238 char *varname;
00239 }
00240 map[] = {
00241
00242 {&pCircuit_V, "voltage_A"},
00243 {&pLine_I, "current_A"},
00244 };
00245
00246 gl_warning("Inverter:%d has no parent meter object defined; using static voltages", obj->id);
00247
00248
00249 *(map[0].var) = &default_line123_voltage[0];
00250 *(map[1].var) = &default_line1_current[0];
00251
00252
00253 default_line123_voltage[0] = complex(Rated_kV*1000/sqrt(3.0),0);
00254 default_line123_voltage[1] = complex(Rated_kV*1000/sqrt(3.0)*cos(2*PI/3),Rated_kV*1000/sqrt(3.0)*sin(2*PI/3));
00255 default_line123_voltage[2] = complex(Rated_kV*1000/sqrt(3.0)*cos(-2*PI/3),Rated_kV*1000/sqrt(3.0)*sin(-2*PI/3));
00256 }
00257
00258 if (gen_mode_v == UNKNOWN)
00259 {
00260 gl_warning("Inverter control mode is not specified! Using default: SUPPLY_DRIVEN");
00261 gen_mode_v = SUPPLY_DRIVEN;
00262 }
00263 if (gen_status_v == UNKNOWN)
00264 {
00265 gl_warning("Inverter status is unknown! Using default: ONLINE");
00266 gen_status_v = ONLINE;
00267 }
00268 if (inverter_type_v == UNKNOWN)
00269 {
00270 gl_warning("Inverter type is unknown! Using default: PWM");
00271 inverter_type_v = PWM;
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 switch(inverter_type_v)
00310 {
00311 case TWO_PULSE:
00312 efficiency = 0.8;
00313 break;
00314 case SIX_PULSE:
00315 efficiency = 0.8;
00316 break;
00317 case TWELVE_PULSE:
00318 efficiency = 0.8;
00319 break;
00320 case PWM:
00321 efficiency = 0.9;
00322 break;
00323 default:
00324 efficiency = 0.8;
00325 break;
00326 }
00327
00328 internal_switch_resistance(switch_type_choice);
00329 filter_circuit_impact(filter_type_v, filter_imp_v);
00330
00331 return 1;
00332 }
00333
00334
00335 complex * inverter::get_complex(OBJECT *obj, char *name)
00336 {
00337 PROPERTY *p = gl_get_property(obj,name);
00338 if (p==NULL || p->ptype!=PT_complex)
00339 return NULL;
00340 return (complex*)GETADDR(obj,p);
00341 }
00342
00343 TIMESTAMP inverter::presync(TIMESTAMP t0, TIMESTAMP t1)
00344 {
00345 phaseA_I_Out = phaseB_I_Out = phaseC_I_Out = 0.0;
00346
00347
00348 TIMESTAMP t2 = TS_NEVER;
00349 return t2;
00350 }
00351
00352 TIMESTAMP inverter::sync(TIMESTAMP t0, TIMESTAMP t1)
00353 {
00354 phaseA_V_Out = pCircuit_V[0];
00355 phaseB_V_Out = pCircuit_V[1];
00356 phaseC_V_Out = pCircuit_V[2];
00357
00358 internal_losses = 1 - calculate_loss(Rtotal, Ltotal, Ctotal, DC, AC);
00359
00360 frequency_losses = 1 - calculate_frequency_loss(output_frequency, Rtotal,Ltotal, Ctotal);
00361
00362
00363 switch(gen_mode_v)
00364 {
00365 case CONSTANT_PF:
00366 {
00367 VA_In = V_In * ~ I_In;
00368
00369
00370
00371 VA_Out = VA_In * efficiency * internal_losses * frequency_losses;
00372
00373
00374
00375 if (number_of_phases_out == 4)
00376 {
00377 power_A = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)));
00378 if (phaseA_V_Out.Mag() != 0.0)
00379 phaseA_I_Out = ~(power_A / phaseA_V_Out);
00380 else
00381 phaseA_I_Out = complex(0.0,0.0);
00382
00383 *pLine12 += -phaseA_I_Out;
00384
00385
00386 last_current[3] = -phaseA_I_Out;
00387
00388
00389
00390
00391 }
00392 else if (number_of_phases_out == 3)
00393 {
00394 power_A = power_B = power_C = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)))/3;
00395 if (phaseA_V_Out.Mag() != 0.0)
00396 phaseA_I_Out = ~(power_A / phaseA_V_Out);
00397 else
00398 phaseA_I_Out = complex(0.0,0.0);
00399 if (phaseB_V_Out.Mag() != 0.0)
00400 phaseB_I_Out = ~(power_B / phaseB_V_Out);
00401 else
00402 phaseB_I_Out = complex(0.0,0.0);
00403 if (phaseC_V_Out.Mag() != 0.0)
00404 phaseC_I_Out = ~(power_C / phaseC_V_Out);
00405 else
00406 phaseC_I_Out = complex(0.0,0.0);
00407
00408 pLine_I[0] += -phaseA_I_Out;
00409 pLine_I[1] += -phaseB_I_Out;
00410 pLine_I[2] += -phaseC_I_Out;
00411
00412
00413 last_current[0] = -phaseA_I_Out;
00414 last_current[1] = -phaseB_I_Out;
00415 last_current[2] = -phaseC_I_Out;
00416
00417
00418
00419
00420
00421
00422
00423
00424 }
00425 else if(number_of_phases_out == 2)
00426 {
00427 OBJECT *obj = OBJECTHDR(this);
00428 node *par = OBJECTDATA(obj->parent, node);
00429
00430 if (par->has_phase(PHASE_A) && phaseA_V_Out.Mag() != 0)
00431 {
00432 power_A = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)))/2;;
00433 phaseA_I_Out = ~(power_A / phaseA_V_Out);
00434 }
00435 else
00436 phaseA_I_Out = complex(0,0);
00437
00438 if (par->has_phase(PHASE_B) && phaseB_V_Out.Mag() != 0)
00439 {
00440 power_B = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)))/2;;
00441 phaseB_I_Out = ~(power_B / phaseB_V_Out);
00442 }
00443 else
00444 phaseB_I_Out = complex(0,0);
00445
00446 if (par->has_phase(PHASE_C) && phaseC_V_Out.Mag() != 0)
00447 {
00448 power_C = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)))/2;;
00449 phaseC_I_Out = ~(power_C / phaseC_V_Out);
00450 }
00451 else
00452 phaseC_I_Out = complex(0,0);
00453
00454 pLine_I[0] += -phaseA_I_Out;
00455 pLine_I[1] += -phaseB_I_Out;
00456 pLine_I[2] += -phaseC_I_Out;
00457
00458
00459 last_current[0] = -phaseA_I_Out;
00460 last_current[1] = -phaseB_I_Out;
00461 last_current[2] = -phaseC_I_Out;
00462
00463 }
00464 else if(number_of_phases_out == 1)
00465 {
00466 if(phaseA_V_Out.Mag() != 0)
00467 {
00468 power_A = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)));
00469 phaseA_I_Out = ~(power_A / phaseA_V_Out);
00470
00471
00472 }
00473 else if(phaseB_V_Out.Mag() != 0)
00474 {
00475 power_B = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)));
00476 phaseB_I_Out = ~(power_B / phaseB_V_Out);
00477
00478
00479 }
00480 else if(phaseC_V_Out.Mag() != 0)
00481 {
00482 power_C = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)));
00483 phaseC_I_Out = ~(power_C / phaseC_V_Out);
00484
00485
00486 }
00487 else
00488 {
00489 gl_warning("None of the phases specified have voltages!");
00490 phaseA_I_Out = phaseB_I_Out = phaseC_I_Out = complex(0.0,0.0);
00491 }
00492 pLine_I[0] += -phaseA_I_Out;
00493 pLine_I[1] += -phaseB_I_Out;
00494 pLine_I[2] += -phaseC_I_Out;
00495
00496
00497 last_current[0] = -phaseA_I_Out;
00498 last_current[1] = -phaseB_I_Out;
00499 last_current[2] = -phaseC_I_Out;
00500
00501 }
00502 else
00503 {
00504 throw ("The number of phases given is unsupported.");
00505 }
00506 return TS_NEVER;
00507 }
00508 break;
00509 case CONSTANT_PQ:
00510 {
00511 GL_THROW("Constant PQ mode not supported at this time");
00512
00513
00514
00515 gl_verbose("inverter sync: constant pq");
00516
00517
00518
00519
00520
00521
00522
00523 if(parent_string = "meter")
00524 {
00525 VA_Out = complex(P_Out,Q_Out);
00526 }
00527 else if (parent_string = "triplex_meter")
00528 {
00529 VA_Out = complex(P_Out,Q_Out);
00530 }
00531 else
00532 {
00533 phaseA_I_Out = pLine_I[0];
00534 phaseB_I_Out = pLine_I[1];
00535 phaseC_I_Out = pLine_I[2];
00536
00537
00538
00539
00540 VA_Out = phaseA_V_Out * (~ phaseA_I_Out) + phaseB_V_Out * (~ phaseB_I_Out) + phaseC_V_Out * (~ phaseC_I_Out);
00541 }
00542
00543 pf_out = P_Out/VA_Out.Mag();
00544
00545
00546
00547 if (number_of_phases_out == 3)
00548 {
00549 power_A = power_B = power_C = VA_Out /3;
00550 phaseA_I_Out = (power_A / phaseA_V_Out);
00551 phaseB_I_Out = (power_B / phaseB_V_Out);
00552 phaseC_I_Out = (power_C / phaseC_V_Out);
00553
00554 phaseA_I_Out = ~ phaseA_I_Out;
00555 phaseB_I_Out = ~ phaseB_I_Out;
00556 phaseC_I_Out = ~ phaseC_I_Out;
00557
00558 }
00559 else if(number_of_phases_out == 1)
00560 {
00561 if(phaseAOut)
00562 {
00563 power_A = VA_Out;
00564 phaseA_I_Out = (power_A / phaseA_V_Out);
00565 phaseA_I_Out = ~ phaseA_I_Out;
00566 }
00567 else if(phaseBOut)
00568 {
00569 power_B = VA_Out;
00570 phaseB_I_Out = (power_B / phaseB_V_Out);
00571 phaseB_I_Out = ~ phaseB_I_Out;
00572 }
00573 else if(phaseCOut)
00574 {
00575 power_C = VA_Out;
00576 phaseC_I_Out = (power_C / phaseC_V_Out);
00577 phaseC_I_Out = ~ phaseC_I_Out;
00578 }
00579 else
00580 {
00581 throw ("none of the phases have voltages!");
00582 }
00583 }
00584 else
00585 {
00586 throw ("unsupported number of phases");
00587 }
00588
00589 VA_In = VA_Out / (efficiency * internal_losses * frequency_losses);
00590 losses = VA_Out * (1 - (efficiency * internal_losses * frequency_losses));
00591
00592
00593
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 V_In = Vdc;
00608
00609
00610
00611 I_In = VA_In / V_In;
00612 I_In = ~I_In;
00613
00614 V_In = filter_voltage_impact_source(I_In, V_In);
00615 I_In = filter_current_impact_source(I_In, V_In);
00616
00617 gl_verbose("Inverter sync: V_In asked for by inverter is: (%f , %f)", V_In.Re(), V_In.Im());
00618 gl_verbose("Inverter sync: I_In asked for by inverter is: (%f , %f)", I_In.Re(), I_In.Im());
00619
00620
00621 pLine_I[0] += phaseA_I_Out;
00622 pLine_I[1] += phaseB_I_Out;
00623 pLine_I[2] += phaseC_I_Out;
00624
00625
00626 last_current[0] = phaseA_I_Out;
00627 last_current[1] = phaseB_I_Out;
00628 last_current[2] = phaseC_I_Out;
00629
00630 return TS_NEVER;
00631 }
00632 break;
00633 case CONSTANT_V:
00634 {
00635 GL_THROW("Constant V mode not supported at this time");
00636
00637
00638
00639 gl_verbose("inverter sync: constant v");
00640 bool changed = false;
00641
00642
00643
00644
00645
00646 if(phaseAOut)
00647 {
00648 if (phaseA_V_Out.Re() < (V_Set_A - margin))
00649 {
00650 phaseA_I_Out = phaseA_I_Out_prev + I_step_max/2;
00651 changed = true;
00652 }
00653 else if (phaseA_V_Out.Re() > (V_Set_A + margin))
00654 {
00655 phaseA_I_Out = phaseA_I_Out_prev - I_step_max/2;
00656 changed = true;
00657 }
00658 else
00659 {
00660 changed = false;
00661 }
00662 }
00663 if (phaseBOut)
00664 {
00665 if (phaseB_V_Out.Re() < (V_Set_B - margin))
00666 {
00667 phaseB_I_Out = phaseB_I_Out_prev + I_step_max/2;
00668 changed = true;
00669 }
00670 else if (phaseB_V_Out.Re() > (V_Set_B + margin))
00671 {
00672 phaseB_I_Out = phaseB_I_Out_prev - I_step_max/2;
00673 changed = true;
00674 }
00675 else
00676 {
00677 changed = false;
00678 }
00679 }
00680 if (phaseCOut)
00681 {
00682 if (phaseC_V_Out.Re() < (V_Set_C - margin))
00683 {
00684 phaseC_I_Out = phaseC_I_Out_prev + I_step_max/2;
00685 changed = true;
00686 }
00687 else if (phaseC_V_Out.Re() > (V_Set_C + margin))
00688 {
00689 phaseC_I_Out = phaseC_I_Out_prev - I_step_max/2;
00690 changed = true;
00691 }
00692 else
00693 {
00694 changed = false;
00695 }
00696 }
00697
00698 power_A = (~phaseA_I_Out) * phaseA_V_Out;
00699 power_B = (~phaseB_I_Out) * phaseB_V_Out;
00700 power_C = (~phaseC_I_Out) * phaseC_V_Out;
00701
00702
00703 if (((power_A + power_B + power_C) > Rated_kVA) ||
00704 ((power_A.Re() + power_B.Re() + power_C.Re()) > Max_P) ||
00705 ((power_A.Im() + power_B.Im() + power_C.Im()) > Max_Q))
00706 {
00707 VA_Out = Rated_kVA / number_of_phases_out;
00708
00709 changed = false;
00710 if(phaseAOut)
00711 {
00712 phaseA_I_Out = VA_Out / phaseA_V_Out;
00713 phaseA_I_Out = (~phaseA_I_Out);
00714 }
00715 if(phaseBOut)
00716 {
00717 phaseB_I_Out = VA_Out / phaseB_V_Out;
00718 phaseB_I_Out = (~phaseB_I_Out);
00719 }
00720 if(phaseCOut)
00721 {
00722 phaseC_I_Out = VA_Out / phaseC_V_Out;
00723 phaseC_I_Out = (~phaseC_I_Out);
00724 }
00725 }
00726
00727
00728 if(power_A < 0)
00729 {
00730 power_A = 0;
00731 phaseA_I_Out = 0;
00732 throw("phaseA power is negative!");
00733 }
00734 if(power_B < 0)
00735 {
00736 power_B = 0;
00737 phaseB_I_Out = 0;
00738 throw("phaseB power is negative!");
00739 }
00740 if(power_C < 0)
00741 {
00742 power_C = 0;
00743 phaseC_I_Out = 0;
00744 throw("phaseC power is negative!");
00745 }
00746
00747 VA_In = VA_Out / (efficiency * internal_losses * frequency_losses);
00748 losses = VA_Out * (1 - (efficiency * internal_losses * frequency_losses));
00749
00750
00751
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765 V_In = Vdc;
00766
00767 I_In = VA_In / V_In;
00768 I_In = ~I_In;
00769
00770 gl_verbose("Inverter sync: I_In asked for by inverter is: (%f , %f)", I_In.Re(), I_In.Im());
00771
00772 V_In = filter_voltage_impact_source(I_In, V_In);
00773 I_In = filter_current_impact_source(I_In, V_In);
00774
00775
00776
00777 if(changed)
00778 {
00779 pLine_I[0] += phaseA_I_Out;
00780 pLine_I[1] += phaseB_I_Out;
00781 pLine_I[2] += phaseC_I_Out;
00782
00783
00784 last_current[0] = phaseA_I_Out;
00785 last_current[1] = phaseB_I_Out;
00786 last_current[2] = phaseC_I_Out;
00787
00788 TIMESTAMP t2 = t1 + 10 * 60 * TS_SECOND;
00789 return t2;
00790 }
00791 else
00792 {
00793 pLine_I[0] += phaseA_I_Out;
00794 pLine_I[1] += phaseB_I_Out;
00795 pLine_I[2] += phaseC_I_Out;
00796
00797
00798 last_current[0] = phaseA_I_Out;
00799 last_current[1] = phaseB_I_Out;
00800 last_current[2] = phaseC_I_Out;
00801
00802 return TS_NEVER;
00803 }
00804 }
00805 break;
00806 case SUPPLY_DRIVEN: {
00807 GL_THROW("SUPPLY_DRIVEN mode for inverters not supported at this time");
00808 }
00809 default:
00810 {
00811 pLine_I[0] += phaseA_I_Out;
00812 pLine_I[1] += phaseB_I_Out;
00813 pLine_I[2] += phaseC_I_Out;
00814
00815
00816 last_current[0] = phaseA_I_Out;
00817 last_current[1] = phaseB_I_Out;
00818 last_current[2] = phaseC_I_Out;
00819
00820 return TS_NEVER;
00821 }
00822 break;
00823 }
00824 if (number_of_phases_out == 4)
00825 {
00826 *pLine12 += phaseA_I_Out;
00827
00828
00829 last_current[3] = phaseA_I_Out;
00830 }
00831 else
00832 {
00833 pLine_I[0] += phaseA_I_Out;
00834 pLine_I[1] += phaseB_I_Out;
00835 pLine_I[2] += phaseC_I_Out;
00836
00837
00838 last_current[0] = phaseA_I_Out;
00839 last_current[1] = phaseB_I_Out;
00840 last_current[2] = phaseC_I_Out;
00841
00842 }
00843
00844 return TS_NEVER;
00845 }
00846
00847
00848
00849
00850
00851
00852
00853
00854
00856
00857
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874 TIMESTAMP inverter::postsync(TIMESTAMP t0, TIMESTAMP t1)
00875 {
00876 TIMESTAMP t2 = TS_NEVER;
00877
00878
00879 pLine_I[0] -= last_current[0];
00880 pLine_I[1] -= last_current[1];
00881 pLine_I[2] -= last_current[2];
00882
00883 if (number_of_phases_out == 4)
00884 *pLine12 -= last_current[3];
00885
00887 return t2;
00888 }
00889
00891
00893
00894 EXPORT int create_inverter(OBJECT **obj, OBJECT *parent)
00895 {
00896 try
00897 {
00898 *obj = gl_create_object(inverter::oclass);
00899 if (*obj!=NULL)
00900 {
00901 inverter *my = OBJECTDATA(*obj,inverter);
00902 gl_set_parent(*obj,parent);
00903 return my->create();
00904 }
00905 }
00906 catch (char *msg)
00907 {
00908 gl_error("create_inverter: %s", msg);
00909 }
00910
00911 return 0;
00912 }
00913
00914 EXPORT int init_inverter(OBJECT *obj, OBJECT *parent)
00915 {
00916 try
00917 {
00918 if (obj!=NULL)
00919 return OBJECTDATA(obj,inverter)->init(parent);
00920 }
00921 catch (char *msg)
00922 {
00923 gl_error("init_inverter(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
00924 }
00925
00926 return 0;
00927 }
00928
00929 EXPORT TIMESTAMP sync_inverter(OBJECT *obj, TIMESTAMP t1, PASSCONFIG pass)
00930 {
00931 TIMESTAMP t2 = TS_NEVER;
00932 inverter *my = OBJECTDATA(obj,inverter);
00933 try
00934 {
00935 switch (pass) {
00936 case PC_PRETOPDOWN:
00937 t2 = my->presync(obj->clock,t1);
00938 break;
00939 case PC_BOTTOMUP:
00940 t2 = my->sync(obj->clock,t1);
00941 break;
00942 case PC_POSTTOPDOWN:
00943 t2 = my->postsync(obj->clock,t1);
00944 break;
00945 default:
00946 GL_THROW("invalid pass request (%d)", pass);
00947 break;
00948 }
00949 if (pass==clockpass)
00950 obj->clock = t1;
00951 }
00952 catch (char *msg)
00953 {
00954 gl_error("sync_inverter(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
00955 }
00956 return t2;
00957 }