00001
00012 #include "pw_model.h"
00013
00014 #ifdef HAVE_POWERWORLD
00015 #ifndef PWX64
00016
00017 #include "comutil.h"
00018 #include "atlbase.h"
00019 #pragma comment(lib, "comsuppw.lib")
00020
00021 EXPORT_CREATE(pw_model);
00022 EXPORT_INIT(pw_model);
00023 EXPORT_SYNC(pw_model);
00024 EXPORT_ISA(pw_model);
00025
00026
00027 EXPORT int finalize_pw_model(OBJECT *obj)
00028 { pw_model *my = OBJECTDATA(obj,pw_model);
00029 try {
00030 return obj!=NULL ? my->finalize() : 0;
00031 }
00032
00033 catch (char *msg) {
00034 gl_error("finalize_pw_model" "(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
00035 return TS_INVALID;
00036 }
00037 catch (const char *msg) {
00038 gl_error("finalize_pw_model" "(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
00039 return TS_INVALID;
00040 }
00041 catch (...) {
00042 gl_error("finalize_pw_model" "(obj=%d;%s): unhandled exception", obj->id, obj->name?obj->name:"unnamed");
00043 return TS_INVALID;
00044 }
00045 }
00046
00047 CLASS *pw_model::oclass = NULL;
00048 pw_model *pw_model::defaults = NULL;
00049
00050 pw_model::pw_model(MODULE *module)
00051 {
00052 if (oclass==NULL)
00053 {
00054
00055
00056 oclass = gld_class::create(module,"pw_model",sizeof(pw_model),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_AUTOLOCK);
00057 if (oclass==NULL)
00058 throw "unable to register class assert";
00059 else
00060 oclass->trl = TRL_PROVEN;
00061
00062 defaults = this;
00063 if (gl_publish_variable(oclass,
00064
00065 PT_char1024, "model_name", PADDR(model_name),PT_DESCRIPTION, "the file path for the PowerWorld model to run",
00066
00067
00068
00069
00070
00071 PT_bool, "update_flag", get_update_flag_offset(), PT_ACCESS, PA_REFERENCE, PT_DESCRIPTION, "flag set by pw_load objects signaling the loads need updating",
00072 PT_int32, "exchange_count", get_exchange_count_offset(), PT_ACCESS, PA_REFERENCE, PT_DESCRIPTION, "number of times PowerWorld and GridLAB-D have exchanged data",
00073 PT_bool, "valid_flag", get_valid_flag_offset(), PT_ACCESS, PA_REFERENCE, PT_DESCRIPTION, "flag set by pw_model signaling if the PowerWorld model solved successfully",
00074 NULL)<1){
00075 char msg[256];
00076 sprintf(msg, "unable to publish properties in %s",__FILE__);
00077 throw msg;
00078 }
00079
00080 memset(this,0,sizeof(pw_model));
00081
00082 }
00083 }
00084
00085
00086 int pw_model::create(){
00087 return 1;
00088 }
00089
00098 int check_COM_output(_variant_t output){
00099 BSTR bHolder;
00100 _variant_t element;
00101 LONG indices[1] = {0};
00102 char *ptr = 0;
00103 HRESULT hr;
00104 SAFEARRAY *output_array;
00105 int rv;
00106
00107
00108
00109 if(output.vt != (VT_VARIANT | VT_ARRAY)){
00110 gl_error("check_COM_output: COM call did not return an array of variants");
00111
00112
00113
00114
00115 return 0;
00116 }
00117 output_array = output.parray;
00118 hr = SafeArrayGetElement(output_array, indices, &element);
00119 switch(hr){
00120 case S_OK:
00121 break;
00122 case DISP_E_BADINDEX:
00123 gl_error("check_COM_output: bad index in SafeArrayGetElement");
00124
00125
00126
00127
00128 return 0;
00129 break;
00130 case E_INVALIDARG:
00131 gl_error("check_COM_output: invalid arguement in SafeArrayGetElement");
00132
00133
00134
00135
00136 return 0;
00137 break;
00138 case E_OUTOFMEMORY:
00139 gl_error("check_COM_output: ran out of memory during SafeArrayGetElement");
00140
00141
00142
00143
00144
00145 return 0;
00146 break;
00147 }
00148 bHolder = element.bstrVal;
00149 ptr = _com_util::ConvertBSTRToString(bHolder);
00150 if(strlen(ptr) > 0){
00151 gl_error("check_COM_output: %s", ptr);
00152
00153
00154
00155
00156 rv = 0;
00157 } else {
00158 rv = 1;
00159 }
00160 delete [] ptr;
00161 return rv;
00162 }
00163
00164 int pw_model::init(OBJECT *parent){
00165 _variant_t output;
00166 _variant_t element;
00167
00168 HRESULT rv;
00169
00170 LONG indices[1] = {0};
00171 char *ptr = 0;
00172 bool trouble = false;
00173
00174
00175 if(0 != model_name[0]){
00176 LPCOLESTR clsid_str = L"pwrworld.SimulatorAuto";
00177
00178
00179 rv = ::CoInitialize(NULL);
00180
00181
00182 startedCOM=true;
00183 initiatorCOM=OBJECTHDR(this);
00184
00185
00186
00187 hr = CLSIDFromProgID(clsid_str, &clsid);
00188 switch(hr){
00189 case S_OK:
00190
00191 break;
00192 case CO_E_CLASSSTRING:
00193 gl_error("unable to find clsid \"pwerworld.SimulatorAuto\" at init()");
00194
00195
00196
00197
00198
00199 return 0;
00200 break;
00201 case REGDB_E_WRITEREGDB:
00202 gl_error("An error occured writing the CLSID to the registry.");
00203
00204
00205
00206
00207 return 0;
00208 break;
00209 default:
00210 gl_error("unexpected return code from CLSIDFromProdID() in init()");
00211 return 0;
00212 break;
00213 }
00214
00215
00216 A = new ISimulatorAutoPtr(__uuidof(SimulatorAuto));
00217 if(0 == A){
00218 gl_error("unable to allocate ISimulatorAutoPtr in init()");
00219
00220
00221
00222
00223
00224 return 0;
00225 }
00226 hr = A.CreateInstance(clsid, NULL, CLSCTX_SERVER);
00227
00228 output = A->OpenCase(model_name.get_string());
00229 if(0 == check_COM_output(output)){
00230 gl_error("OpenCase() failed");
00231
00232
00233
00234
00235 return 0;
00236 }
00237
00238 gl_verbose("OpenCase succeeded");
00239
00240
00241 output = A->RunScriptCommand("EnterMode(RUN);");
00242 if(0 == check_COM_output(output)){
00243 gl_error("RunScriptCommand(EnterMode(RUN);) failed");
00244
00245
00246
00247
00248 return 0;
00249 }
00250
00251 gl_verbose("RunScriptCommand(EnterMode(RUN)) succeeded");
00252
00253
00254 output = A->RunScriptCommand("SolvePowerFlow;");
00255 if(0 == check_COM_output(output)){
00256 gl_error("RunScriptCommand(SolvePowerFlow;) failed");
00257
00258
00259
00260 return 0;
00261 }
00262
00263 gl_verbose("RunScriptCommand(SolvePowerFlow) succeeded");
00264
00265
00266
00267 } else {
00268
00269 trouble = true;
00270 }
00271
00272
00273 #ifdef PW_THIS_IS_PUBLISHED
00274
00275 if(out_file[0] != 0){
00276 FILE *outfile;
00277 BSTR objtypebstr, filterbstr;
00278
00279 if(out_file_type == 0){
00280 gl_error("out_file '%s' did not define an object type");
00281 return 0;
00282 }
00283 outfile = fopen(out_file, "w");
00284 if(out_file == 0){
00285 gl_error("out_file '%s' could not be opened for writing");
00286 return 0;
00287 }
00288
00289 objtypebstr = _com_util::ConvertStringToBSTR(out_file_type);
00290 filterbstr = _com_util::ConvertStringToBSTR("");
00291 output = A->ListOfDevices(objtypebstr, filterbstr);
00292
00293 if(0 == check_COM_output(output)){
00294 gl_error("ListOfDevices(%s) failed", out_file_type);
00295 return 0;
00296 }
00297
00298 gl_verbose("ListOfDevices(%s) succeeded", out_file_type);
00299
00300
00301 if((0 == strcmp("load", out_file_type) ) || (0 == strcmp("Load", out_file_type) ) ){
00302
00303 ;
00304 } else {
00305 ;
00306 }
00307
00308 return 0;
00309 }
00310
00311
00312 if(field_file[0] != 0){
00313 FILE *fieldfile;
00314 BSTR fieldtypebstr;
00315 fieldfile = fopen(field_file, "w");
00316 fieldtypebstr = _com_util::ConvertStringToBSTR(field_type);
00317
00318 output = A->GetFieldList(fieldtypebstr);
00319 SysFreeString(fieldtypebstr);
00320 if(0 == check_COM_output(output)){
00321 gl_error("GetFieldList(%s) failed", field_type);
00322 return 0;
00323 }
00324
00325 gl_verbose("GetFieldList(%s) succeeded", field_type);
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 #endif
00341
00342 if(trouble){
00343 gl_error("pw_model::init(): no PowerWorld model file specified");
00344
00345
00346
00347
00348 return 0;
00349 }
00350
00351 exchange_count = 0;
00352 update_flag = false;
00353 valid_flag = true;
00354
00355 return 1;
00356 }
00357
00362 TIMESTAMP pw_model::presync(TIMESTAMP t1){
00363 TIMESTAMP rv = TS_NEVER;
00364 _variant_t output;
00365
00366
00367
00368 if(update_flag){
00369
00370
00371 output = A->RunScriptCommand("SolvePowerFlow;");
00372 if(0 == check_COM_output(output)){
00373 gl_error("RunScriptCommand(SolvePowerFlow;) failed");
00374
00375
00376
00377
00378 return TS_INVALID;
00379 }
00380 gl_verbose("RunScriptCommand(SolvePowerFlow) succeeded");
00381
00382
00383
00384
00385 if(!valid_flag){
00386
00387
00388 rv = t1;
00389 }
00390 }
00391
00392
00393 update_flag = false;
00394
00395 return rv;
00396 }
00397
00398 TIMESTAMP pw_model::sync(TIMESTAMP t1){
00399 OBJECT *hdr = OBJECTHDR(this);
00400 if(update_flag){
00401 return t1;
00402 }
00403 return TS_NEVER;
00404 }
00405
00406 TIMESTAMP pw_model::postsync(TIMESTAMP t1){
00407 return TS_NEVER;
00408 }
00409
00410 int pw_model::isa(char *classname){
00411 return (strcmp(classname, "pw_model") == 0 ? 1 : 0);
00412 }
00413
00418 int pw_model::finalize(){
00419 _variant_t output;
00420
00421 output = A->CloseCase();
00422 if(0 == check_COM_output(output)){
00423 gl_error("CloseCase() failed");
00424
00425
00426
00427
00428 return 0;
00429 }
00430
00431 gl_verbose("pw_model::finalize(): case closed.");
00432
00433 return 1;
00434 }
00435
00436
00437
00438 void pw_model::pw_close_COM(void)
00439 {
00440
00441 CoUninitialize();
00442 }
00443
00444 #endif //PWX64
00445 #endif //HAVE_POWERWORLD
00446