powerflow/node.cpp

00001 
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <errno.h>
00026 #include <math.h>
00027 
00028 #include "node.h"
00029 
00030 CLASS *node::oclass = NULL;
00031 CLASS *node::pclass = NULL;
00032 node *node::defaults = NULL;
00033 
00034 node::node(MODULE *mod) : powerflow_object(mod)
00035 {
00036     if(oclass == NULL)
00037     {
00038         pclass = powerflow_object::oclass;
00039         oclass = gl_register_class(mod,"node",PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN);
00040         if(oclass == NULL)
00041             GL_THROW("unable to register object class implemented by %s",__FILE__);
00042         
00043         if(gl_publish_variable(oclass,
00044             PT_double,"sync_V_limit[V]",PADDR(sync_V_limit),
00045             PT_complex, "phaseA_V[V]", PADDR(phaseA_V),
00046             PT_complex, "phaseB_V[V]", PADDR(phaseB_V),
00047             PT_complex, "phaseC_V[V]", PADDR(phaseC_V),
00048             PT_set, "phases", PADDR(phases),
00049                 PT_KEYWORD, "D", PHASE_D,
00050                 PT_KEYWORD, "S", PHASE_S,
00051                 PT_KEYWORD, "A", PHASE_A,
00052                 PT_KEYWORD, "B", PHASE_B,
00053                 PT_KEYWORD, "C", PHASE_C,
00054                 PT_KEYWORD, "N", PHASE_N,
00055                 PT_KEYWORD, "G", GROUND,
00056             PT_set, "condition", PADDR(condition),
00057                 PT_KEYWORD, "NORMAL", OC_NORMAL,
00058                 PT_KEYWORD, "CONTACT", OC_CONTACT,
00059                 PT_KEYWORD, "OPEN", OC_OPEN,
00060                 PT_KEYWORD, "A", PHASE_A,
00061                 PT_KEYWORD, "B", PHASE_B,
00062                 PT_KEYWORD, "C", PHASE_C,
00063                 PT_KEYWORD, "N", PHASE_N,
00064                 PT_KEYWORD, "G", GROUND,
00065                 PT_KEYWORD, "S1", PHASE_S1,
00066                 PT_KEYWORD, "S2", PHASE_S2,
00067                 PT_KEYWORD, "SN", PHASE_SN,
00068             PT_enumeration, "solution", PADDR(solution),
00069                 PT_KEYWORD, "NORMAL", PS_NORMAL,
00070                 PT_KEYWORD, "OUTAGE", PS_OUTAGE,
00071             NULL) < 1) GL_THROW("unable to publish properties in %s",__FILE__);
00072         
00073         // Set up defaults
00074         memset(this,0,sizeof(node));
00075         defaults = this;
00076     }
00077 }
00078 
00079 int node::isa(char *classname)
00080 {
00081     return strcmp(classname,"node")==0 || powerflow_object::isa(classname);
00082 }
00083 
00084 int node::create(void)
00085 {
00086     memcpy(this,defaults,sizeof(node));
00087     int result = powerflow_object::create();
00088     return result;
00089 }
00090 
00091 int node::init(OBJECT *parent)
00092 {
00093     /* initialize the powerflow base object */
00094     int result = powerflow_object::init();
00095 
00096     /* make sure the sync voltage limit is positive */
00097     if (sync_V_limit<0)
00098     {
00099         gl_warning("node %s (node:%d): negative sync_V_limit is changed to positive value", get_name(), get_id());
00100         sync_V_limit = -sync_V_limit;
00101     }
00102 
00103     return result;
00104 }
00105 
00106 TIMESTAMP node::presync(TIMESTAMP t0)
00107 {
00108     /* reset the current injections for the coming pass (this is better done here, even though it's faster in postbottomup) */
00109     phaseA_I_in = phaseB_I_in = phaseC_I_in = 0.0;
00110 
00111     return TS_NEVER; /* request another pass */
00112 }
00113 
00114 TIMESTAMP node::sync(TIMESTAMP t0)
00115 {
00116     /* if condition is normal */
00117     if (is_normal())
00118     {
00119         /* record the last sync voltage */
00120         lastA_V = phaseA_V;
00121         lastB_V = phaseB_V;
00122         lastC_V = phaseC_V;
00123 
00124         return TS_NEVER;
00125     }
00126 
00127     /* condition is not normal (treat all as outage) */
00128     lastA_V = lastB_V = lastC_V = complex(0,0);
00129     return TS_NEVER; /* request another pass */
00130 }
00131 
00132 TIMESTAMP node::postsync(TIMESTAMP t0)
00133 {
00134     /* node is operation ok */
00135     if (is_normal())
00136     {
00137         /* solution is normal */
00138         solution = PS_NORMAL;
00139 
00140         /* compute the sync voltage change */
00141         double sync_V = (lastA_V - phaseA_V).Mag() + (lastB_V-phaseB_V).Mag() + (lastC_V-phaseC_V).Mag();
00142 
00143         /* if the sync voltage limit is defined and the sync voltage is larger */
00144         if (sync_V_limit != 0.0 && sync_V > sync_V_limit)
00145 
00146             /* request another pass */
00147             return t0;
00148     }
00149 
00150     /* solution is abnormal */
00151     else
00152         solution = PS_OUTAGE;
00153 
00154     /* the solution is satisfactory */
00155     return TS_NEVER;
00156 }
00157 
00159 // IMPLEMENTATION OF CORE LINKAGE: node
00161 
00169 EXPORT int create_node(OBJECT **obj, OBJECT *parent)
00170 {
00171     try
00172     {
00173         *obj = gl_create_object(node::oclass,sizeof(node));
00174         if (*obj==NULL)
00175             throw "unable to create node";
00176         gl_set_parent(*obj,parent);
00177         return OBJECTDATA(*obj,node)->create();
00178     }
00179     catch (char *msg)
00180     {
00181         gl_error("create_node: %s", msg);
00182         return 0;
00183     }
00184 }
00185 
00186 
00187 
00194 EXPORT int init_node(OBJECT *obj)
00195 {
00196     node *my = OBJECTDATA(obj,node);
00197     try {
00198         return my->init(obj->parent);
00199     }
00200     catch (char *msg)
00201     {
00202         GL_THROW("%s (node:%d): %s", my->get_name(), my->get_id(), msg);
00203         return 0; 
00204     }
00205 }
00206 
00214 EXPORT TIMESTAMP sync_node(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00215 {
00216     node *pObj = OBJECTDATA(obj,node);
00217     try {
00218         TIMESTAMP t1 = TS_NEVER;
00219         switch (pass) {
00220         case PC_PRETOPDOWN:
00221             return pObj->presync(t0);
00222         case PC_BOTTOMUP:
00223             return pObj->sync(t0);
00224         case PC_POSTTOPDOWN:
00225             t1 = pObj->postsync(t0);
00226             obj->clock = t0;
00227             return t1;
00228         default:
00229             throw "invalid pass request";
00230         }
00231     }
00232     catch (char *msg)
00233     {
00234         gl_error("node %s (node:%d): %s", pObj->get_name(), pObj->get_id(), msg);
00235     }
00236     catch (...)
00237     {
00238         gl_error("node %s (node:%d): unknown exception", pObj->get_name(), pObj->get_id());
00239     }
00240     return TS_INVALID; /* stop the clock */
00241 }
00242 
00243 EXPORT int isa_node(OBJECT *obj, char *classname)
00244 {
00245     return OBJECTDATA(obj,node)->isa(classname);
00246 }
00247 

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