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