powerflow/link.cpp

00001 
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <errno.h>
00011 #include <math.h>
00012 
00013 #include "link.h"
00014 #include "node.h"
00015 
00016 CLASS* link::oclass = NULL;
00017 CLASS* link::pclass = NULL;
00018 link  *link::defaults = NULL;
00019 
00024 link::link(MODULE *mod) : powerflow_object(mod){
00025     
00026     // first time init
00027     if (oclass==NULL)
00028     {
00029         pclass = powerflow_object::oclass;
00030         oclass = gl_register_class(mod,"link",PC_BOTTOMUP|PC_POSTTOPDOWN);
00031         if (oclass==NULL)
00032             GL_THROW("unable to register object class implemented by %s",__FILE__);
00033         
00034         defaults = this;
00035         memset(this,0,sizeof(link));
00036     }
00037 }
00038 
00039 int link::isa(char *classname)
00040 {
00041     return strcmp(classname,"link")==0 || powerflow_object::isa(classname);
00042 }
00043 
00044 int link::create(void)
00045 {
00046     int result = powerflow_object::create();
00047     memcpy(this,defaults,sizeof(link));
00048     return result;
00049 }
00050 
00051 int link::init(void)
00052 {
00053     OBJECT *obj = GETOBJECT(this);
00054 
00055     powerflow_object::init();
00056 
00057     /* check link from node */
00058     if (from==NULL)
00059         throw "link from node is not specified";
00060     else if (obj->parent==NULL)
00061     {
00062         /* make 'from' object parent of this object */
00063         if (gl_object_isa(from,"node"))
00064             gl_set_parent(obj, from);
00065         else
00066             throw "link from reference not a node";
00067     }
00068     else
00069 
00070         /* promote 'from' object if necessary */
00071         gl_set_rank(from,obj->rank+1);
00072     
00073     /* check link to node */
00074     if (to==NULL)
00075         throw "link to node is not specified";
00076     else if (to->parent==NULL)
00077     {
00078         /* make this object parent to 'to' object */
00079         if (gl_object_isa(to,"node"))
00080             gl_set_parent(to, obj);
00081         else
00082             throw "link to reference not a node";
00083     }
00084     else
00085         /* promote this object if necessary */
00086         gl_set_rank(obj,to->rank+1);
00087 
00088     return 1;
00089 }
00090 
00091 TIMESTAMP link::sync(TIMESTAMP t0)
00092 {
00093     node *f = OBJECTDATA(from, node);
00094     node *t = OBJECTDATA(to, node);
00095     set nodeconditions = f->condition | t->condition;
00096 
00097     /* if the line is not operating normally */
00098     if (!is_normal())
00099     {
00100         /* pass condition to nodes on either end only when link is connected */
00101         if (!is_open(PHASE_A))
00102             t->condition = f->condition |= OC_PHASE_A_CONTACT&(nodeconditions|condition);
00103         if (!is_open(PHASE_B))
00104             t->condition = f->condition |= OC_PHASE_B_CONTACT&(nodeconditions|condition);
00105         if (!is_open(PHASE_C))
00106             t->condition = f->condition |= OC_PHASE_C_CONTACT&(nodeconditions|condition);
00107     }
00108 
00109     /* update the voltages */
00110     f->phaseA_I_in += c_mat[0][0] * t->phaseA_V +
00111                       c_mat[0][1] * t->phaseB_V +
00112                       c_mat[0][2] * t->phaseC_V +
00113                       d_mat[0][0] * t->phaseA_I_in +
00114                       d_mat[0][1] * t->phaseB_I_in +
00115                       d_mat[0][2] * t->phaseC_I_in;
00116     f->phaseB_I_in += c_mat[1][0] * t->phaseA_V +
00117                       c_mat[1][1] * t->phaseB_V +
00118                       c_mat[1][2] * t->phaseC_V +
00119                       d_mat[1][0] * t->phaseA_I_in +
00120                       d_mat[1][1] * t->phaseB_I_in +
00121                       d_mat[1][2] * t->phaseC_I_in;
00122     f->phaseC_I_in += c_mat[2][0] * t->phaseA_V +
00123                       c_mat[2][1] * t->phaseB_V +
00124                       c_mat[2][2] * t->phaseC_V +
00125                       d_mat[2][0] * t->phaseA_I_in +
00126                       d_mat[2][1] * t->phaseB_I_in +
00127                       d_mat[2][2] * t->phaseC_I_in;
00128 
00129     return TS_NEVER;
00130 }
00131 
00132 TIMESTAMP link::postsync(TIMESTAMP t0)
00133 {
00134     node *f = OBJECTDATA(from, node);
00135     node *t = OBJECTDATA(to, node);
00136     set nodeconditions = f->condition | t->condition;
00137 
00138     /* compute for normal operation */
00139     if (!(is_normal() && nodeconditions==OC_NORMAL))
00140 
00142         memset(d_mat,0,sizeof(d_mat));
00143 
00144     t->phaseA_V = A_mat[0][0] * f->phaseA_V +
00145                   A_mat[0][1] * f->phaseB_V +
00146                   A_mat[0][2] * f->phaseC_V -
00147                   B_mat[0][0] * t->phaseA_I_in -
00148                   B_mat[0][1] * t->phaseB_I_in -
00149                   B_mat[0][2] * t->phaseC_I_in;
00150     t->phaseB_V = A_mat[1][0] * f->phaseA_V +
00151                   A_mat[1][1] * f->phaseB_V +
00152                   A_mat[1][2] * f->phaseC_V -
00153                   B_mat[1][0] * t->phaseA_I_in -
00154                   B_mat[1][1] * t->phaseB_I_in -
00155                   B_mat[1][2] * t->phaseC_I_in;
00156     t->phaseC_V = A_mat[2][0] * f->phaseA_V +
00157                   A_mat[2][1] * f->phaseB_V +
00158                   A_mat[2][2] * f->phaseC_V -
00159                   B_mat[2][0] * t->phaseA_I_in -
00160                   B_mat[2][1] * t->phaseB_I_in -
00161                   B_mat[2][2] * t->phaseC_I_in;
00162 
00163     return TS_NEVER;
00164 }
00165 
00166 
00167 
00169 // IMPLEMENTATION OF CORE LINKAGE: link
00171 
00179 EXPORT int create_link(OBJECT **obj, OBJECT *parent)
00180 {
00181     try
00182     {
00183         *obj = gl_create_object(link::oclass,sizeof(link));
00184         if (*obj==NULL)
00185             throw "unable to create v";
00186         gl_set_parent(*obj,parent);
00187         return OBJECTDATA(*obj,link)->create();
00188     }
00189     catch (char *msg)
00190     {
00191         gl_error("create_link: %s", msg);
00192         return 0;
00193     }
00194 }
00195 
00196 
00197 
00204 EXPORT int init_link(OBJECT *obj)
00205 {
00206     link *my = OBJECTDATA(obj,link);
00207     try {
00208         return my->init();
00209     }
00210     catch (char *msg)
00211     {
00212         GL_THROW("%s (link:%d): %s", my->get_name(), my->get_id(), msg);
00213         return 0; 
00214     }
00215 }
00216 
00224 EXPORT TIMESTAMP sync_link(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00225 {
00226     link *pLink = OBJECTDATA(obj,link);
00227     try 
00228     {
00229         if (pass==PC_BOTTOMUP)
00230             return pLink->sync(t0);
00231         else if (pass==PC_POSTTOPDOWN) 
00232         {
00233             TIMESTAMP t1 = pLink->postsync(t0);
00234             obj->clock = t0;
00235             return t1;
00236         }
00237         else
00238             throw "invalid pass request";
00239     } 
00240     catch (const char *error) 
00241     {
00242         GL_THROW("%s (link:%d): %s", pLink->get_name(), pLink->get_id(), error);
00243         return TS_INVALID; 
00244     } 
00245     catch (...) 
00246     {
00247         GL_THROW("%s (link:%d): unknown exception", pLink->get_name(), pLink->get_id());
00248         return TS_INVALID;
00249     }
00250 }
00251 
00252 EXPORT int isa_link(OBJECT *obj, char *classname)
00253 {
00254     return OBJECTDATA(obj,link)->isa(classname);
00255 }
00256 
00258 // MATRIX OPS FOR LINKS
00260 
00261 void inverse(complex in[3][3], complex out[3][3])
00262 {
00263     complex x = complex(1.0) / (in[0][0] * in[1][1] * in[2][2] -
00264                                in[0][0] * in[1][2] * in[2][1] -
00265                                in[0][1] * in[1][0] * in[2][2] +
00266                                in[0][1] * in[1][2] * in[2][0] +
00267                                in[0][2] * in[1][0] * in[2][1] -
00268                                in[0][2] * in[1][1] * in[2][0]);
00269 
00270     out[0][0] = x * (in[1][1] * in[2][2] - in[1][2] * in[2][1]);
00271     out[0][1] = x * (in[0][2] * in[2][1] - in[0][1] * in[2][2]);
00272     out[0][2] = x * (in[0][1] * in[1][2] - in[0][2] * in[1][1]);
00273     out[1][0] = x * (in[1][2] * in[2][0] - in[1][0] * in[2][2]);
00274     out[1][1] = x * (in[0][0] * in[2][2] - in[0][2] * in[2][0]);
00275     out[1][2] = x * (in[0][2] * in[1][0] - in[0][0] * in[1][2]);
00276     out[2][0] = x * (in[1][0] * in[2][1] - in[1][1] * in[2][0]);
00277     out[2][1] = x * (in[0][1] * in[2][0] - in[0][0] * in[2][1]);
00278     out[2][2] = x * (in[0][0] * in[1][1] - in[0][1] * in[1][0]);
00279 }
00280 
00281 void multiply(double a, complex b[3][3], complex c[3][3])
00282 {
00283     #define MUL(i, j) c[i][j] = b[i][j] * a
00284     MUL(0, 0); MUL(0, 1); MUL(0, 2);
00285     MUL(1, 0); MUL(1, 1); MUL(1, 2);
00286     MUL(2, 0); MUL(2, 1); MUL(2, 2);
00287     #undef MUL
00288 }
00289 
00290 void multiply(complex a[3][3], complex b[3][3], complex c[3][3])
00291 {
00292     #define MUL(i, j) c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j]
00293     MUL(0, 0); MUL(0, 1); MUL(0, 2);
00294     MUL(1, 0); MUL(1, 1); MUL(1, 2);
00295     MUL(2, 0); MUL(2, 1); MUL(2, 2);
00296     #undef MUL
00297 }
00298 
00299 void subtract(complex a[3][3], complex b[3][3], complex c[3][3])
00300 {
00301     #define SUB(i, j) c[i][j] = a[i][j] - b[i][j]
00302     SUB(0, 0); SUB(0, 1); SUB(0, 2);
00303     SUB(1, 0); SUB(1, 1); SUB(1, 2);
00304     SUB(2, 0); SUB(2, 1); SUB(2, 2);
00305     #undef MUL
00306 }
00307 
00308 

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