00001
00010 #include <stdlib.h>
00011 #include <stdio.h>
00012 #include <errno.h>
00013 #include <math.h>
00014 #include <float.h>
00015 #include "network.h"
00016
00017 static int save_cdf(char *file)
00018 {
00019 FILE *fp=fopen(file,"w");
00020 if (fp==NULL) return 0;
00021 time_t now = time(NULL);
00022 char timestamp[32];
00023 int count=0;
00024
00025 double mvabase=100.0;
00026 char system_name[32]="GridLAB-D Network";
00027
00028 strftime(timestamp,sizeof(timestamp),"%m/%d/%y",gmtime(&now));
00029
00030 count += fprintf(fp," %s %-20.20s %5.1f %4d %c %s\n", timestamp, system_name, mvabase, model_year, model_case, model_name);
00031
00032
00033 FINDLIST *found = gl_find_objects(FL_NEW,FT_CLASS,SAME,"node",FT_END);
00034 count += fprintf(fp,"%-38.38s %d ITEMS\n","BUS DATA FOLLOWS",found->hit_count);
00035 OBJECT *obj=NULL;
00036 while ((obj=gl_find_next(found,obj))!=NULL)
00037 {
00038 node *my = (node*)(obj+1);
00039 char name[32];
00040 sprintf(name,"Bus %d", obj->id+1);
00041 count += fprintf(fp,"%4d %-12.12s %2d %2d %2d %5.3f %6.2f %7.1f %8.1f %7.1f %7.1f %6.1f %6.1f %6.1f %6.1f %8.5f %8.5f %d\n", obj->id+1,name,
00042 my->flow_area_num, my->loss_zone_num, my->type, my->V.Mag(),
00043 my->V.Arg()*180/PI,
00044 my->S.Re()<0?-my->S.Re()*mvabase:0, my->S.Re()<0?-my->S.Im()*mvabase:0,
00045 my->S.Re()>0?my->S.Re()*mvabase:0, my->S.Re()>0?my->S.Im()*mvabase:0,
00046 my->base_kV, my->desired_kV, my->Qmax_MVAR, my->Qmin_MVAR, my->G, my->B, my->remote_bus_id?my->remote_bus_id->id+1:0);
00047 }
00048 count += fprintf(fp,"-999\n");
00049 gl_free(found);
00050
00051
00052 found = gl_find_objects(FL_NEW,FT_CLASS,SAME,"link",FT_END);
00053 count += fprintf(fp,"%-38.38s %d ITEMS\n","BRANCH DATA FOLLOWS",found->hit_count);
00054 obj=NULL;
00055 while ((obj=gl_find_next(found,obj))!=NULL)
00056 {
00057 link *my = (link*)(obj+1);
00058 node *from = my->from?(node*)(((OBJECT*)my->from)+1):NULL;
00059 node *to= my->to?(node*)(((OBJECT*)my->to)+1):NULL;
00060 if (from==NULL||to==NULL)
00061 continue;
00062 double R = (complex(1)/my->Y).Re();
00063 double X = (complex(1)/my->Y).Im();
00064 count += fprintf(fp,"%4d %4d %2d %2d 1 0 %9.5f %11.5f %9.4f %4d %4d %4d %4d %1d %6.3f %7.2f %5f %5f %5f %5f %5f\n",
00065 my->from->id+1, my->to->id+1, from->flow_area_num, from->loss_zone_num, R,X,0.0,
00066 0,0,0,0, 0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0);
00067 }
00068 count += fprintf(fp,"-999\n");
00069 gl_free(found);
00070
00071 count += fprintf(fp,"LOSS ZONES FOLLOWS 1 ITEMS\n 1 %s\n-99\n",model_name);
00072 count += fprintf(fp,"INTERCHANGE DATA FOLLOWS 0 ITEMS\n-9\n");
00073 count += fprintf(fp,"TIE LINES FOLLOWS 0 ITEMS\n-999\n");
00074
00075 count += fprintf(fp,"END OF DATA\n");
00076
00077 return count;
00078 }
00079
00080 EXPORT int export_file(char *file)
00081 {
00082 if (file==NULL) file="network.cdf";
00083
00084 char *ext = strrchr(file,'.');
00085 if (ext!=NULL && stricmp(ext,".cdf")==0)
00086 return save_cdf(file);
00087 errno = ENOENT;
00088 return 0;
00089 }
00090
00091 EXPORT int kmldump(FILE *fp, OBJECT *obj)
00092 {
00093 if (obj==NULL)
00094 {
00095
00096 fprintf(fp," <Style id=\"TransmissionLine\">\n");
00097 fprintf(fp," <LineStyle>\n"
00098 " <color>7f00ffff</color>\n"
00099 " <width>4</width>\n"
00100 " </LineStyle>\n"
00101 " <PolyStyle>\n"
00102 " <color>7f00ff00</color>\n"
00103 " </PolyStyle>\n"
00104 " </Style>\n");
00105 }
00106 else if (strcmp(obj->oclass->name,"node")==0)
00107 {
00108 node *pNode = (node*)OBJECTDATA(obj,node);
00109 if (isnan(obj->latitude) || isnan(obj->longitude))
00110 return 0;
00111 fprintf(fp," <Placemark>\n");
00112 if (obj->name)
00113 fprintf(fp," <name>%s</name>\n", obj->name);
00114 else
00115 fprintf(fp," <name>%s %d</name>\n", obj->oclass->name, obj->id);
00116 fprintf(fp," <description>\n");
00117 fprintf(fp," <![CDATA[\n");
00118 fprintf(fp," <TABLE><TR>\n");
00119 switch (pNode->type) {
00120 case SWING:
00121 fprintf(fp," <TR><TH ALIGN=LEFT>Type</TH><TD ALIGN=RIGHT STYLE=\"font-family:courier;\">SWING </TD></TR>\n");
00122 break;
00123 case PV:
00124 fprintf(fp," <TR><TH ALIGN=LEFT>Type</TH><TD ALIGN=RIGHT STYLE=\"font-family:courier;\">PV </TD></TR>\n");
00125 break;
00126 case PQ:
00127 fprintf(fp," <TR><TH ALIGN=LEFT>Type</TH><TD ALIGN=RIGHT STYLE=\"font-family:courier;\">PQ </TD></TR>\n");
00128 break;
00129 }
00130 fprintf(fp," <TR><TH ALIGN=LEFT>Voltage</TH><TD ALIGN=RIGHT STYLE=\"font-family:courier;\">%.3f kV <BR>%.3f ∠ </TD></TR>\n",
00131 pNode->V.Mag()*pNode->base_kV,pNode->V.Arg()*180/3.1416);
00132 if (pNode->S.Mag()>0)
00133 fprintf(fp," <TR><TH ALIGN=LEFT>%s</TH><TD ALIGN=RIGHT STYLE=\"font-family:courier;\">%.3f MW <BR>%.3f MVAR</TD></TR>\n",
00134 pNode->S.Re()<0?"Demand":"Supply",fabs(pNode->S.Re())*mvabase,pNode->S.Im()*mvabase);
00135 fprintf(fp," </TR></TABLE>\n");
00136 fprintf(fp," ]]>\n");
00137 fprintf(fp," </description>\n");
00138 fprintf(fp," <Point>\n");
00139 fprintf(fp," <coordinates>%f,%f</coordinates>\n",obj->longitude,obj->latitude);
00140 fprintf(fp," </Point>\n");
00141 fprintf(fp," </Placemark>\n");
00142 }
00143 else if (strcmp(obj->oclass->name,"link")==0)
00144 {
00145 link *pLink = (link*)OBJECTDATA(obj,link);
00146 OBJECT *from = pLink->from;
00147 OBJECT *to = pLink->to;
00148 if (isnan(from->latitude) || isnan(to->latitude) || isnan(from->longitude) || isnan(to->longitude))
00149 return 0;
00150 fprintf(fp," <Placemark>\n");
00151 if (obj->name)
00152 fprintf(fp," <name>%s</name>\n", obj->name);
00153 else
00154 fprintf(fp," <name>%s ==> %s</name>\n", from->name?from->name:"unnamed", to->name?to->name:"unnamed");
00155 fprintf(fp," <description>\n");
00156 fprintf(fp," <![CDATA[\n");
00157 fprintf(fp," <TABLE><TR>\n");
00158 complex flow;
00159 node *pFrom = OBJECTDATA(from,node);
00160 node *pTo = OBJECTDATA(to,node);
00161 if (pLink->I.Re()<0)
00162 flow = pFrom->V * pLink->I;
00163 else
00164 flow = pTo->V * pLink->I;
00165 complex loss = pLink->I*pLink->I / pLink->Y;
00166 complex imp = complex(1,0)/pLink->Y;
00167 double current_base = mvabase/pFrom->base_kV*1000;
00168 fprintf(fp," <TR><TH ALIGN=LEFT>Flow</TH><TD ALIGN=RIGHT STYLE=\"font-family:courier;\">%.3f MW <BR>%.3f MVAR</TD></TR>\n",
00169 flow.Re()*mvabase, flow.Im()*mvabase);
00170 fprintf(fp," <TR><TH ALIGN=LEFT>Current</TH><TD ALIGN=RIGHT STYLE=\"font-family:courier;\">%.3f Amps</TD></TR>\n",
00171 pLink->I.Mag()*current_base);
00172 fprintf(fp," <TR><TH ALIGN=LEFT>Impedance</TH><TD ALIGN=RIGHT STYLE=\"font-family:courier;\">%.4f R <BR>%.4f X </TD></TR>\n",
00173 imp.Re(),imp.Im());
00174 fprintf(fp," <TR><TH ALIGN=LEFT>Losses</TH><TD ALIGN=RIGHT STYLE=\"font-family:courier;\">%.2f %%P <BR>%.2f %%Q </TD></TR>\n",
00175 loss.Re()/flow.Re()*100,loss.Im()/flow.Im()*100);
00176 fprintf(fp," </TR></TABLE>\n");
00177 fprintf(fp," ]]>\n");
00178 fprintf(fp," </description>\n");
00179 fprintf(fp," <styleUrl>#TransmissionLine</styleUrl>>\n");
00180 fprintf(fp," <coordinates>%f,%f</coordinates>\n",
00181 (from->longitude+to->longitude)/2,(from->latitude+to->latitude)/2);
00182 fprintf(fp," <LineString>\n");
00183 fprintf(fp," <extrude>0</extrude>\n");
00184 fprintf(fp," <tessellate>0</tessellate>\n");
00185 fprintf(fp," <altitudeMode>relative</altitudeMode>\n");
00186 fprintf(fp," <coordinates>%f,%f,50 %f,%f,50</coordinates>\n",
00187 from->longitude,from->latitude,to->longitude,to->latitude);
00188 fprintf(fp," </LineString>\n");
00189 fprintf(fp," </Placemark>\n");
00190 }
00191 return 0;
00192 }
00193