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
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
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
00126 if (status==RS_CLOSED && trip)
00127 {
00128 status = RS_OPEN;
00129
00130
00131 t1 = t0+(TIMESTAMP)(recloser_delay*TS_SECOND);
00132 }
00133
00134
00135 else if (status==RS_OPEN && t0>=reclose_time)
00136 {
00137
00138 if (trip)
00139 {
00140
00141 if (recloser_tries>0)
00142 {
00143 recloser_tries--;
00144 t1 = t0+(TIMESTAMP)(recloser_delay*TS_SECOND);
00145 }
00146
00147
00148 else
00149 {
00150 t1 = t0+(TIMESTAMP)(gl_random_exponential(3600)*TS_SECOND);
00151 }
00152 }
00153 else
00154 status = RS_CLOSED;
00155 }
00156
00157
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
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
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