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 "dc_dc_converter.h"
00019
00020 #define DEFAULT 1.0;
00021
00022
00023 CLASS *dc_dc_converter::oclass = NULL;
00024 dc_dc_converter *dc_dc_converter::defaults = NULL;
00025
00026 static PASSCONFIG passconfig = PC_BOTTOMUP|PC_POSTTOPDOWN;
00027 static PASSCONFIG clockpass = PC_BOTTOMUP;
00028
00029
00030 dc_dc_converter::dc_dc_converter(MODULE *module)
00031 {
00032 if (oclass==NULL)
00033 {
00034 oclass = gl_register_class(module,"dc_dc_converter",sizeof(dc_dc_converter),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,"dc_dc_converter_type",PADDR(dc_dc_converter_type_v),
00041 PT_KEYWORD,"BUCK",BUCK,
00042 PT_KEYWORD,"BOOST",BOOST,
00043 PT_KEYWORD,"BUCK_BOOST",BUCK_BOOST,
00044
00045 PT_enumeration,"generator_mode",PADDR(gen_mode_v),
00046 PT_KEYWORD,"UNKNOWN",UNKNOWN,
00047 PT_KEYWORD,"CONSTANT_V",CONSTANT_V,
00048 PT_KEYWORD,"CONSTANT_PQ",CONSTANT_PQ,
00049 PT_KEYWORD,"CONSTANT_PF",CONSTANT_PF,
00050 PT_KEYWORD,"SUPPLY_DRIVEN",SUPPLY_DRIVEN,
00051
00052 PT_complex, "V_Out[V]",PADDR(V_Out),
00053 PT_complex, "I_Out[A]",PADDR(I_Out),
00054 PT_complex, "Vdc[V]", PADDR(Vdc),
00055 PT_complex, "VA_Out[VA]", PADDR(VA_Out),
00056 PT_double, "P_Out", PADDR(P_Out),
00057 PT_double, "Q_Out", PADDR(Q_Out),
00058
00059 PT_double, "service_ratio", PADDR(service_ratio),
00060
00061 PT_complex, "V_In[V]",PADDR(V_In),
00062 PT_complex, "I_In[A]",PADDR(I_In),
00063 PT_complex, "VA_In[VA]", PADDR(VA_In),
00064
00065
00066
00067 PT_set, "phases", PADDR(phases),
00068 PT_KEYWORD, "A",(set)PHASE_A,
00069 PT_KEYWORD, "B",(set)PHASE_B,
00070 PT_KEYWORD, "C",(set)PHASE_C,
00071 PT_KEYWORD, "N",(set)PHASE_N,
00072 PT_KEYWORD, "S",(set)PHASE_S,
00073 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00074 defaults = this;
00075
00076
00077
00078
00079 memset(this,0,sizeof(dc_dc_converter));
00080
00081 }
00082 }
00083
00084
00085
00086
00087
00088 int dc_dc_converter::create(void)
00089 {
00090 memcpy(this,defaults,sizeof(*this));
00091
00092 return 1;
00093 }
00094
00095
00096 int dc_dc_converter::init(OBJECT *parent)
00097 {
00098
00099
00100
00101
00102
00103
00104 Rated_kW = 1000;
00105 Max_P = 1000;
00106 Min_P = 0;
00107
00108
00109 Rated_kVA = 2500;
00110 Rated_kV = 100;
00111 Rinternal = 0.035;
00112 Rload = 1;
00113 Rtotal = 0.05;
00114
00115 Rground = 0.03;
00116 Rground_storage = 0.05;
00117
00118 Cinternal = 0;
00119 Cground = 0;
00120 Ctotal = 0;
00121 Linternal = 0;
00122 Lground = 0;
00123 Ltotal = 0;
00124 filter_120HZ = false;
00125 filter_180HZ = false;
00126 filter_240HZ = false;
00127 pf_in = 0;
00128 pf_out = 0;
00129 number_of_phases_in = 0;
00130 number_of_phases_out = 0;
00131 phaseAIn = false;
00132 phaseBIn = false;
00133 phaseCIn = false;
00134 phaseAOut = false;
00135 phaseBOut = false;
00136 phaseCOut = false;
00137
00138 switch_type_choice = IDEAL_SWITCH;
00139
00140 gen_status_v = ONLINE;
00141 filter_type_v = BAND_PASS;
00142 filter_imp_v = IDEAL_FILTER;
00143 dc_dc_converter_type_v = BUCK_BOOST;
00144 power_in = DC;
00145 power_out = DC;
00146
00147
00148 P_Out = 500;
00149 Q_Out = 0;
00150
00151 margin = 50;
00152 V_Set = 480;
00153 I_out_prev = 0;
00154 I_step_max = 50;
00155 internal_losses = 0;
00156 C_Storage_In = 0;
00157 C_Storage_Out = 0;
00158 losses = 0;
00159 efficiency = 0;
00160
00161
00162 service_ratio = 2;
00163
00164
00165
00166
00167
00168
00169
00170 gl_verbose("dc_dc_converter init: initialized the variables");
00171
00172 struct {
00173 complex **var;
00174 char *varname;
00175 } map[] = {
00176
00177 {&pCircuit_V, "V_In"},
00178 {&pLine_I, "I_In"},
00179 };
00180
00181
00182 static complex default_line_voltage[1], default_line_current[1];
00183 int i;
00184
00185
00186 if (parent!=NULL && strcmp(parent->oclass->name,"meter")==0)
00187 {
00188 parent_string = "meter";
00189 for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
00190 *(map[i].var) = get_complex(parent,map[i].varname);
00191
00192 gl_verbose("dc_dc_converter init: mapped METER objects to internal variables");
00193 }
00194 else if (parent!=NULL && ((strcmp(parent->oclass->name,"inverter")==0))){
00195 gl_verbose("dc_dc_converter init: parent WAS found, is an inverter!");
00196 parent_string = "inverter";
00197
00199
00200 for (i=0; i<sizeof(map)/sizeof(map[0]); i++){
00201 *(map[i].var) = get_complex(parent,map[i].varname);
00202 }
00203 gl_verbose("dc_dc_converter init: mapped INVERTER objects to local variables");
00204 }
00205 else if (parent!=NULL && strcmp(parent->oclass->name,"battery")==0){
00206 gl_verbose("dc_dc_converter init: parent WAS found, is an battery!");
00207 parent_string = "dc_dc_converter";
00208
00210
00211 for (i=0; i<sizeof(map)/sizeof(map[0]); i++){
00212 *(map[i].var) = get_complex(parent,map[i].varname);
00213 }
00214 gl_verbose("dc_dc_converter init: mapped BATTERY objects to internal variables");
00215 }
00216 else{
00217
00218
00220 gl_verbose("dc_dc_converter init: mapped meter objects to internal variables");
00221
00222 OBJECT *obj = OBJECTHDR(this);
00223 gl_verbose("dc_dc_converter init: no parent meter defined, parent is not a meter");
00224 gl_warning("dc_dc_converter:%d %s", obj->id, parent==NULL?"has no parent meter defined":"parent is not a meter");
00225
00226
00227 *(map[0].var) = &default_line_voltage[0];
00228 *(map[1].var) = &default_line_current[0];
00229
00230
00231 default_line_voltage[0] = complex(0,0);
00232 default_line_current[0] = complex(0,0);
00233
00234
00235
00236 }
00237
00238 gl_verbose("dc_dc_converter init: finished connecting with meter");
00239
00240
00241
00242
00243 if (gen_mode_v==UNKNOWN)
00244 {
00245 OBJECT *obj = OBJECTHDR(this);
00246 throw("Generator control mode is not specified");
00247 }
00248 if (gen_status_v== dc_dc_converter::OFFLINE)
00249 {
00250
00251 throw("Generator is out of service!");
00252 }else
00253 {
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 switch(dc_dc_converter_type_v){
00293 case BUCK:
00294 efficiency = 0.9;
00295 break;
00296 case BOOST:
00297 efficiency = 0.9;
00298 break;
00299 case BUCK_BOOST:
00300 efficiency = 0.8;
00301 break;
00302 default:
00303 efficiency = 0.8;
00304 break;
00305 }
00306
00307 internal_switch_resistance(switch_type_choice);
00308 filter_circuit_impact(filter_type_v, filter_imp_v);
00309
00310 }
00311
00312 return 1;
00313 }
00314
00315
00316
00317 complex *dc_dc_converter::get_complex(OBJECT *obj, char *name)
00318 {
00319 PROPERTY *p = gl_get_property(obj,name);
00320 if (p==NULL || p->ptype!=PT_complex)
00321 return NULL;
00322 return (complex*)GETADDR(obj,p);
00323 }
00324
00325
00326
00327
00328
00329 TIMESTAMP dc_dc_converter::presync(TIMESTAMP t0, TIMESTAMP t1)
00330 {
00331 I_Out = VA_Out = 0.0;
00332
00333 TIMESTAMP t2 = TS_NEVER;
00334
00335 return t2;
00336 }
00337
00338
00339 TIMESTAMP dc_dc_converter::sync(TIMESTAMP t0, TIMESTAMP t1)
00340 {
00341
00342 V_Out = pCircuit_V[0];
00343
00344 gl_verbose("dc_dc_c sync: got voltage from parent, is: %f", V_Out);
00345
00346 internal_losses = 1 - calculate_loss(Rtotal, Ltotal, Ctotal, DC, AC);
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 switch(gen_mode_v){
00373 case SUPPLY_DRIVEN:
00374 gl_verbose("dc_dc_c sync: supply driven");
00375 {
00376
00377
00378
00379
00380
00381 VA_In = V_In * ~ I_In;
00382
00383
00384 VA_Out = VA_In * efficiency * internal_losses;
00385 losses = VA_Out * Rtotal / (Rtotal + Rload);
00386 VA_Out = VA_Out * Rload / (Rtotal + Rload);
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 I_Out = VA_Out / V_Out;
00412 I_Out = ~ I_Out;
00413
00414 pLine_I[0] = I_Out;
00415
00416 return TS_NEVER;
00417 }
00418 break;
00419 case CONSTANT_PQ:
00420 gl_verbose("dc_dc_c sync: constant pq");
00421 {
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 if(parent_string = "meter"){
00457 VA_Out = complex(P_Out,Q_Out);
00458 gl_verbose("dc_dc_c sync: VA_Out set is: (%f , %f)", VA_Out.Re(), VA_Out.Im());
00459 }else{
00460 I_Out = pLine_I[0];
00461 gl_verbose("dc_dc_c sync: V_In requested is: (%f , %f)", V_In.Re(), V_In.Im());
00462 VA_Out = V_Out * ~ I_Out;
00463 gl_verbose("dc_dc_c sync: VA_Out set is: (%f , %f)", VA_Out.Re(), VA_Out.Im());
00464 }
00465
00466 V_In = V_Out / service_ratio;
00467
00468 VA_In = VA_Out / (efficiency * internal_losses);
00469
00470 gl_verbose("dc_dc_c sync: VA_In requested is: (%f , %f)", VA_In.Re(), VA_In.Im());
00471
00472 losses = VA_Out * (1 - (efficiency * internal_losses));
00473
00474 if(V_In == 0){
00475 I_In = 0;
00476 }else{
00477 I_In = VA_In / V_In;
00478 I_In = ~I_In;
00479 }
00480
00481 gl_verbose("dc_dc_c sync: I_In requested is: (%f , %f)", I_In.Re(), I_In.Im());
00482
00483 return TS_NEVER;
00484 }
00485 break;
00486 case CONSTANT_V:
00487 gl_verbose("dc_dc_c sync: constant v");
00488 {
00489 bool changed = false;
00490
00491
00492
00493
00494
00495 I_Out = pLine_I[0];
00496
00497 gl_verbose("dc_dc_c sync: I from parent is: (%f , %f)", I_Out.Re(), I_Out.Im());
00498
00499 V_In = V_Out / service_ratio;
00500
00501
00502 gl_verbose("dc_dc_c sync: V_Out from parent is: (%f , %f)", V_Out.Re(), V_Out.Im());
00503 gl_verbose("dc_dc_c sync: V_In calculated: (%f , %f)", V_In.Re(), V_In.Im());
00504
00505 if (V_Out < (V_Set - margin)){
00506 I_Out = I_out_prev + I_step_max / 2;
00507 changed = true;
00508 }else if (V_Out > (V_Set + margin)){
00509 I_Out = I_out_prev - I_step_max / 2;
00510 changed = true;
00511 }else{
00512 changed = false;
00513 }
00514
00515 gl_verbose("dc_dc_c sync: I_In after adjustment is: (%f , %f)", I_Out.Re(), I_Out.Im());
00516
00517
00518 VA_Out = (~I_Out) * V_Out;
00519
00520 gl_verbose("dc_dc_c sync: VA_Out pre-limits is: (%f , %f)", VA_Out.Re(), VA_Out.Im());
00521
00522 if(VA_Out > Rated_kVA){
00523 VA_Out = Rated_kVA;
00524 I_Out = VA_Out / V_Out;
00525 I_Out = ~I_Out;
00526 changed = false;
00527 }
00528
00529 if(VA_Out < 0){
00530 VA_Out = 0;
00531 I_Out = 0;
00532 changed = false;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 gl_verbose("dc_dc_c sync: VA_In requested pre-losses is: (%f , %f)", VA_Out.Re(), VA_Out.Im());
00607
00608 VA_In = VA_Out / (efficiency * internal_losses);
00609 losses = VA_Out * (1 - (efficiency * internal_losses));
00610
00611 gl_verbose("dc_dc_c sync: VA_In requested with losses is: (%f , %f)", VA_In.Re(), VA_In.Im());
00612
00613
00614 if(V_In == 0){
00615 I_In = 0;
00616 }else{
00617 I_In = VA_In / V_In;
00618 I_In = ~I_In;
00619 }
00620
00621 gl_verbose("dc_dc_c sync: I_In requested is: (%f , %f)", I_In.Re(), I_In.Im());
00622
00623
00624
00625 if(changed){
00626 TIMESTAMP t2 = t1 + 10 * 60 * TS_SECOND;
00627 return t2;
00628 }else{
00629 return TS_NEVER;
00630 }
00631 }
00632 break;
00633 default:
00634 break;
00635
00636 return TS_NEVER;
00637
00638 }
00639 return TS_NEVER;
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649
00651
00652
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669 TIMESTAMP dc_dc_converter::postsync(TIMESTAMP t0, TIMESTAMP t1)
00670 {
00671 TIMESTAMP t2 = TS_NEVER;
00673 return t2;
00674 }
00675
00677
00679
00680 EXPORT int create_dc_dc_converter(OBJECT **obj, OBJECT *parent)
00681 {
00682 try
00683 {
00684 *obj = gl_create_object(dc_dc_converter::oclass);
00685 if (*obj!=NULL)
00686 {
00687 dc_dc_converter *my = OBJECTDATA(*obj,dc_dc_converter);
00688 gl_set_parent(*obj,parent);
00689 return my->create();
00690 }
00691 }
00692 catch (char *msg)
00693 {
00694 gl_error("create_dc_dc_converter: %s", msg);
00695 }
00696
00697 return 0;
00698 }
00699
00700 EXPORT int init_dc_dc_converter(OBJECT *obj, OBJECT *parent)
00701 {
00702 try
00703 {
00704 if (obj!=NULL)
00705 return OBJECTDATA(obj,dc_dc_converter)->init(parent);
00706 }
00707 catch (char *msg)
00708 {
00709 gl_error("init_dc_dc_converter(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
00710 }
00711
00712 return 0;
00713 }
00714
00715 EXPORT TIMESTAMP sync_dc_dc_converter(OBJECT *obj, TIMESTAMP t1, PASSCONFIG pass)
00716 {
00717 TIMESTAMP t2 = TS_NEVER;
00718 dc_dc_converter *my = OBJECTDATA(obj,dc_dc_converter);
00719 try
00720 {
00721 switch (pass) {
00722 case PC_PRETOPDOWN:
00723 t2 = my->presync(obj->clock,t1);
00724 break;
00725 case PC_BOTTOMUP:
00726 t2 = my->sync(obj->clock,t1);
00727 break;
00728 case PC_POSTTOPDOWN:
00729 t2 = my->postsync(obj->clock,t1);
00730 break;
00731 default:
00732 GL_THROW("invalid pass request (%d)", pass);
00733 break;
00734 }
00735 if (pass==clockpass)
00736 obj->clock = t1;
00737 }
00738 catch (char *msg)
00739 {
00740 gl_error("sync_dc_dc_converter(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
00741 }
00742 return t2;
00743 }