xref: /petsc/src/snes/tutorials/network/power/PFReadData.c (revision ad540459ab38c4a232710a68077e487eb6627fe2)
1 #include "petscmat.h"
2 #include "power.h"
3 #include <string.h>
4 #include <ctype.h>
5 
6 PetscErrorCode PFReadMatPowerData(PFDATA *pf, char *filename) {
7   FILE        *fp;
8   VERTEX_Power Bus;
9   LOAD         Load;
10   GEN          Gen;
11   EDGE_Power   Branch;
12   PetscInt     line_counter   = 0;
13   PetscInt     bus_start_line = -1, bus_end_line = -1; /* xx_end_line points to the next line after the record ends */
14   PetscInt     gen_start_line = -1, gen_end_line = -1;
15   PetscInt     br_start_line = -1, br_end_line = -1;
16   char         line[MAXLINE];
17   PetscInt     loadi = 0, geni = 0, bri = 0, busi = 0, i, j;
18   int          extbusnum, bustype_i;
19   double       Pd, Qd;
20   PetscInt     maxbusnum = -1, intbusnum, *busext2intmap, genj, loadj;
21   GEN          newgen;
22   LOAD         newload;
23 
24   PetscFunctionBegin;
25   fp = fopen(filename, "r");
26   /* Check for valid file */
27   PetscCheck(fp, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Can't open Matpower data file %s", filename);
28   pf->nload = 0;
29   while (fgets(line, MAXLINE, fp)) {
30     if (strstr(line, "mpc.bus = [")) bus_start_line = line_counter + 1;                     /* Bus data starts from next line */
31     if (strstr(line, "mpc.gen") && gen_start_line == -1) gen_start_line = line_counter + 1; /* Generator data starts from next line */
32     if (strstr(line, "mpc.branch")) br_start_line = line_counter + 1;                       /* Branch data starts from next line */
33     if (strstr(line, "];")) {
34       if (bus_start_line != -1 && bus_end_line == -1) bus_end_line = line_counter;
35       if (gen_start_line != -1 && gen_end_line == -1) gen_end_line = line_counter;
36       if (br_start_line != -1 && br_end_line == -1) br_end_line = line_counter;
37     }
38 
39     /* Count the number of pq loads */
40     if (bus_start_line != -1 && line_counter >= bus_start_line && bus_end_line == -1) {
41       sscanf(line, "%d %d %lf %lf", &extbusnum, &bustype_i, &Pd, &Qd);
42       if (!((Pd == 0.0) && (Qd == 0.0))) pf->nload++;
43       if (extbusnum > maxbusnum) maxbusnum = extbusnum;
44     }
45     line_counter++;
46   }
47   fclose(fp);
48 
49   pf->nbus    = bus_end_line - bus_start_line;
50   pf->ngen    = gen_end_line - gen_start_line;
51   pf->nbranch = br_end_line - br_start_line;
52 
53   PetscCall(PetscCalloc1(pf->nbus, &pf->bus));
54   PetscCall(PetscCalloc1(pf->ngen, &pf->gen));
55   PetscCall(PetscCalloc1(pf->nload, &pf->load));
56   PetscCall(PetscCalloc1(pf->nbranch, &pf->branch));
57   Bus    = pf->bus;
58   Gen    = pf->gen;
59   Load   = pf->load;
60   Branch = pf->branch;
61 
62   /* Setting pf->sbase to 100 */
63   pf->sbase = 100.0;
64 
65   PetscCall(PetscMalloc1(maxbusnum + 1, &busext2intmap));
66   for (i = 0; i < maxbusnum + 1; i++) busext2intmap[i] = -1;
67 
68   fp = fopen(filename, "r");
69   /* Reading data */
70   for (i = 0; i < line_counter; i++) {
71     PetscCheck(fgets(line, MAXLINE, fp), PETSC_COMM_SELF, PETSC_ERR_SUP, "File is incorrectly formatted");
72 
73     if ((i >= bus_start_line) && (i < bus_end_line)) {
74       double gl, bl, vm, va, basekV;
75       int    bus_i, ide, area;
76       /* Bus data */
77       sscanf(line, "%d %d %lf %lf %lf %lf %d %lf %lf %lf", &bus_i, &ide, &Pd, &Qd, &gl, &bl, &area, &vm, &va, &basekV);
78       Bus[busi].bus_i                = bus_i;
79       Bus[busi].ide                  = ide;
80       Bus[busi].area                 = area;
81       Bus[busi].gl                   = gl;
82       Bus[busi].bl                   = bl;
83       Bus[busi].vm                   = vm;
84       Bus[busi].va                   = va;
85       Bus[busi].basekV               = basekV;
86       Bus[busi].internal_i           = busi;
87       busext2intmap[Bus[busi].bus_i] = busi;
88 
89       if (!((Pd == 0.0) && (Qd == 0.0))) {
90         Load[loadi].bus_i                 = Bus[busi].bus_i;
91         Load[loadi].status                = 1;
92         Load[loadi].pl                    = Pd;
93         Load[loadi].ql                    = Qd;
94         Load[loadi].area                  = Bus[busi].area;
95         Load[loadi].internal_i            = busi;
96         Bus[busi].lidx[Bus[busi].nload++] = loadi;
97         PetscCheck(Bus[busi].nload <= NLOAD_AT_BUS_MAX, PETSC_COMM_SELF, PETSC_ERR_SUP, "Exceeded maximum number of loads allowed at bus");
98         loadi++;
99       }
100       busi++;
101     }
102 
103     /* Read generator data */
104     if (i >= gen_start_line && i < gen_end_line) {
105       double pg, qg, qt, qb, vs, mbase, pt, pb;
106       int    bus_i, status;
107       sscanf(line, "%d %lf %lf %lf %lf %lf %lf %d %lf %lf", &bus_i, &pg, &qg, &qt, &qb, &vs, &mbase, &status, &pt, &pb);
108       Gen[geni].bus_i  = bus_i;
109       Gen[geni].status = status;
110       Gen[geni].pg     = pg;
111       Gen[geni].qg     = qg;
112       Gen[geni].qt     = qt;
113       Gen[geni].qb     = qb;
114       Gen[geni].vs     = vs;
115       Gen[geni].mbase  = mbase;
116       Gen[geni].pt     = pt;
117       Gen[geni].pb     = pb;
118 
119       intbusnum                                  = busext2intmap[Gen[geni].bus_i];
120       Gen[geni].internal_i                       = intbusnum;
121       Bus[intbusnum].gidx[Bus[intbusnum].ngen++] = geni;
122 
123       Bus[intbusnum].vm = Gen[geni].vs;
124 
125       PetscCheck(Bus[intbusnum].ngen <= NGEN_AT_BUS_MAX, PETSC_COMM_SELF, PETSC_ERR_SUP, "Exceeded maximum number of generators allowed at bus");
126       geni++;
127     }
128 
129     if (i >= br_start_line && i < br_end_line) {
130       PetscScalar R, X, Bc, B, G, Zm, tap, shift, tap2, tapr, tapi;
131       double      r, x, b, rateA, rateB, rateC, tapratio, phaseshift;
132       int         fbus, tbus, status;
133       sscanf(line, "%d %d %lf %lf %lf %lf %lf %lf %lf %lf %d", &fbus, &tbus, &r, &x, &b, &rateA, &rateB, &rateC, &tapratio, &phaseshift, &status);
134       Branch[bri].fbus       = fbus;
135       Branch[bri].tbus       = tbus;
136       Branch[bri].status     = status;
137       Branch[bri].r          = r;
138       Branch[bri].x          = x;
139       Branch[bri].b          = b;
140       Branch[bri].rateA      = rateA;
141       Branch[bri].rateB      = rateB;
142       Branch[bri].rateC      = rateC;
143       Branch[bri].tapratio   = tapratio;
144       Branch[bri].phaseshift = phaseshift;
145 
146       if (Branch[bri].tapratio == 0.0) Branch[bri].tapratio = 1.0;
147       Branch[bri].phaseshift *= PETSC_PI / 180.0;
148 
149       intbusnum              = busext2intmap[Branch[bri].fbus];
150       Branch[bri].internal_i = intbusnum;
151 
152       intbusnum              = busext2intmap[Branch[bri].tbus];
153       Branch[bri].internal_j = intbusnum;
154 
155       /* Compute self and transfer admittances */
156       R  = Branch[bri].r;
157       X  = Branch[bri].x;
158       Bc = Branch[bri].b;
159 
160       Zm = R * R + X * X;
161       G  = R / Zm;
162       B  = -X / Zm;
163 
164       tap   = Branch[bri].tapratio;
165       shift = Branch[bri].phaseshift;
166       tap2  = tap * tap;
167       tapr  = tap * PetscCosScalar(shift);
168       tapi  = tap * PetscSinScalar(shift);
169 
170       Branch[bri].yff[0] = G / tap2;
171       Branch[bri].yff[1] = (B + Bc / 2.0) / tap2;
172 
173       Branch[bri].yft[0] = -(G * tapr - B * tapi) / tap2;
174       Branch[bri].yft[1] = -(B * tapr + G * tapi) / tap2;
175 
176       Branch[bri].ytf[0] = -(G * tapr + B * tapi) / tap2;
177       Branch[bri].ytf[1] = -(B * tapr - G * tapi) / tap2;
178 
179       Branch[bri].ytt[0] = G;
180       Branch[bri].ytt[1] = B + Bc / 2.0;
181 
182       bri++;
183     }
184   }
185   fclose(fp);
186 
187   /* Reorder the generator data structure according to bus numbers */
188   genj  = 0;
189   loadj = 0;
190   PetscCall(PetscMalloc1(pf->ngen, &newgen));
191   PetscCall(PetscMalloc1(pf->nload, &newload));
192   for (i = 0; i < pf->nbus; i++) {
193     for (j = 0; j < pf->bus[i].ngen; j++) PetscCall(PetscMemcpy(&newgen[genj++], &pf->gen[pf->bus[i].gidx[j]], sizeof(struct _p_GEN)));
194     for (j = 0; j < pf->bus[i].nload; j++) PetscCall(PetscMemcpy(&newload[loadj++], &pf->load[pf->bus[i].lidx[j]], sizeof(struct _p_LOAD)));
195   }
196   PetscCall(PetscFree(pf->gen));
197   PetscCall(PetscFree(pf->load));
198   pf->gen  = newgen;
199   pf->load = newload;
200 
201   PetscCall(PetscFree(busext2intmap));
202   PetscFunctionReturn(0);
203 }
204