powerflow/relay.cpp

00001 
00011 #include <stdlib.h>
00012 #include <stdio.h>
00013 #include <errno.h>
00014 #include <math.h>
00015 
00016 #include "relay.h"
00017 #include "node.h"
00018 
00020 // relay CLASS FUNCTIONS
00022 CLASS* relay::oclass = NULL;
00023 CLASS* relay::pclass = NULL;
00024 relay *relay::defaults = NULL;
00025 
00026 relay::relay(MODULE *mod) : link(mod)
00027 {
00028     if(oclass == NULL)
00029     {
00030         pclass = link::oclass;
00031         
00032         oclass = gl_register_class(mod,"relay",PC_BOTTOMUP|PC_POSTTOPDOWN);
00033         if(oclass == NULL)
00034             GL_THROW("unable to register object class implemented by %s",__FILE__);
00035         
00036         if(gl_publish_variable(oclass,
00037             PT_double, "time_to_change", PADDR(time_to_change),
00038             PT_enumeration, "status", PADDR(status),
00039                 PT_KEYWORD, "OPEN", RS_OPEN,
00040                 PT_KEYWORD, "CLOSED", RS_CLOSED,
00041             PT_double, "recloser_delay[s]", PADDR(recloser_delay),
00042             PT_int16, "recloser_tries", PADDR(recloser_tries),
00043             PT_object, "from",PADDR(from),
00044             PT_object, "to", PADDR(to),
00045             PT_set, "phases", PADDR(phases),
00046                PT_KEYWORD, "A",PHASE_A,
00047                PT_KEYWORD, "B",PHASE_B,
00048                PT_KEYWORD, "C",PHASE_C,
00049                PT_KEYWORD, "N",PHASE_N,
00050                PT_KEYWORD, "S",PHASE_S,
00051             NULL) < 1) GL_THROW("unable to publish properties in %s",__FILE__);
00052         
00053         // Set up defaults
00054         memset(this,0,sizeof(relay));
00055         defaults = this;
00056     }
00057 }
00058 
00059 int relay::isa(char *classname)
00060 {
00061     return strcmp(classname,"relay")==0 || link::isa(classname);
00062 }
00063 
00064 int relay::create()
00065 {
00066     int result = link::create();
00067     memcpy(this,defaults,sizeof(relay));
00068     status = RS_CLOSED;
00069     recloser_delay = 5;
00070     recloser_tries = 3;
00071     return result;
00072 }
00073 
00074 int relay::init()
00075 {
00076     int result = link::init();
00077 
00078     if (recloser_delay<=1.0)
00079         throw "recloser delay must be at least 1 second";
00080     
00081     a_mat[0][0] = d_mat[0][0] = A_mat[0][0] = (status==RS_CLOSED && has_phase(PHASE_A) ? 1.0 : 0.0);
00082     a_mat[1][1] = d_mat[1][1] = A_mat[1][1] = (status==RS_CLOSED && has_phase(PHASE_B) ? 1.0 : 0.0);
00083     a_mat[2][2] = d_mat[2][2] = A_mat[2][2] = (status==RS_CLOSED && has_phase(PHASE_C) ? 1.0 : 0.0);
00084 
00085     b_mat[0][0] = c_mat[0][0] = B_mat[0][0] = 0.0;
00086     b_mat[1][1] = c_mat[1][1] = B_mat[1][1] = 0.0;
00087     b_mat[2][2] = c_mat[2][2] = B_mat[2][2] = 0.0;
00088 
00089     for (int i = 0; i < 3; i++)
00090         i_abc_in[i] = i_n_in[i] = i_abc_out[i] = i_n_out[i] = 1.0;
00091 
00092 #ifdef _TESTING
00093     extern bool show_matrix_values;
00094     if (show_matrix_values)
00095     {
00096         gl_testmsg("Relay: a matrix");
00097         print_matrix(a_mat);
00098 
00099         gl_testmsg("Relay: A matrix");
00100         print_matrix(A_mat);
00101 
00102         gl_testmsg("Relay: b matrix");
00103         print_matrix(b_mat);
00104 
00105         gl_testmsg("Relay: B matrix");
00106         print_matrix(B_mat);
00107 
00108         gl_testmsg("Relay: c matrix");
00109         print_matrix(c_mat);
00110 
00111         gl_testmsg("Relay: d matrix");
00112         print_matrix(d_mat);
00113     }
00114 #endif
00115     return result;
00116 }
00117 
00118 TIMESTAMP relay::sync(TIMESTAMP t0)
00119 {
00120     TIMESTAMP t1 = TS_NEVER;
00121     node *f = OBJECTDATA(from, node);
00122     node *t = OBJECTDATA(to, node);
00123     set trip = (f->is_contact_any() || t->is_contact_any());
00124 
00125     /* perform relay operation if any line contact has occurred */
00126     if (status==RS_CLOSED && trip)
00127     {
00128         status = RS_OPEN;
00129 
00130         /* schedule recloser operation */
00131         t1 = t0+(TIMESTAMP)(recloser_delay*TS_SECOND);
00132     }
00133 
00134     /* recloser time has arrived */
00135     else if (status==RS_OPEN && t0>=reclose_time)
00136     {
00137         /* still have contact */
00138         if (trip)
00139         {
00140             /* reschedule automatic recloser if retries permits */ 
00141             if (recloser_tries>0)
00142             {
00143                 recloser_tries--;
00144                 t1 = t0+(TIMESTAMP)(recloser_delay*TS_SECOND);
00145             }
00146 
00147             /* automatic retries exhausted, manual takes an average of an hour */
00148             else
00149             {
00150                 t1 = t0+(TIMESTAMP)(gl_random_exponential(3600)*TS_SECOND);
00151             }
00152         }
00153         else
00154             status = RS_CLOSED;
00155     }
00156 
00157     /* compute matrix values */
00158     a_mat[0][0] = d_mat[0][0] = A_mat[0][0] = (status==RS_CLOSED && has_phase(PHASE_A) ? 1.0 : 0.0);
00159     a_mat[1][1] = d_mat[1][1] = A_mat[1][1] = (status==RS_CLOSED && has_phase(PHASE_B) ? 1.0 : 0.0);
00160     a_mat[2][2] = d_mat[2][2] = A_mat[2][2] = (status==RS_CLOSED && has_phase(PHASE_C) ? 1.0 : 0.0);
00161     
00162     /* adjust operating condition */
00163     if (status==RS_CLOSED)
00164         condition = OC_NORMAL;
00165     else
00166         condition = OC_OPEN_ALL;
00167     
00168     TIMESTAMP t2=link::sync(t0);
00169 
00170     return t1<t2?t1:t2;
00171 }
00172 
00173 TIMESTAMP relay::postsync(TIMESTAMP t0)
00174 {
00175     return link::postsync(t0);
00176 }
00177 
00179 // IMPLEMENTATION OF CORE LINKAGE: relay
00181 
00189 EXPORT int create_relay(OBJECT **obj, OBJECT *parent)
00190 {
00191     try
00192     {
00193         *obj = gl_create_object(relay::oclass,sizeof(relay));
00194         if (*obj!=NULL)
00195         {
00196             relay *my = OBJECTDATA(*obj,relay);
00197             gl_set_parent(*obj,parent);
00198             return my->create();
00199         }
00200     }
00201     catch (char *msg)
00202     {
00203         gl_error("create_relay: %s", msg);
00204     }
00205     return 1;
00206 }
00207 
00214 EXPORT int init_relay(OBJECT *obj)
00215 {
00216     relay *my = OBJECTDATA(obj,relay);
00217     try {
00218         return my->init();
00219     }
00220     catch (char *msg)
00221     {
00222         GL_THROW("%s (relay:%d): %s", my->get_name(), my->get_id(), msg);
00223         return 0; 
00224     }
00225 }
00226 
00234 EXPORT TIMESTAMP sync_relay(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00235 {
00236     relay *pObj = OBJECTDATA(obj,relay);
00237     try {
00238         if (pass==PC_BOTTOMUP)
00239             return pObj->sync(t0);
00240         else
00241         {
00242             TIMESTAMP t1 = pObj->postsync(t0);
00243             obj->clock = t0;
00244             return t1;
00245         }
00246     } catch (const char *error) {
00247         GL_THROW("%s (%s:%d): %s", pObj->get_name(), pObj->get_id(), error);
00248         return 0; 
00249     } catch (...) {
00250         GL_THROW("%s (%s:%d): %s", pObj->get_name(), pObj->get_id(), "unknown exception");
00251         return 0;
00252     }
00253 }
00254 
00255 EXPORT int isa_relay(OBJECT *obj, char *classname)
00256 {
00257     return OBJECTDATA(obj,relay)->isa(classname);
00258 }
00259 

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy