xref: /petsc/src/snes/tutorials/network/power/pffunctions.c (revision 0baf8eba40dbc839082666f9f7396a225d6f663c)
1 /* function subroutines used by power.c */
2 
3 #include "power.h"
4 
5 PetscErrorCode GetListofEdges_Power(PFDATA *pfdata, PetscInt *edgelist)
6 {
7   PetscInt   i, fbus, tbus, nbranches = pfdata->nbranch;
8   EDGE_Power branch  = pfdata->branch;
9   PetscBool  netview = PETSC_FALSE;
10 
11   PetscFunctionBegin;
12   PetscCall(PetscOptionsHasName(NULL, NULL, "-powernet_view", &netview));
13   for (i = 0; i < nbranches; i++) {
14     fbus                = branch[i].internal_i;
15     tbus                = branch[i].internal_j;
16     edgelist[2 * i]     = fbus;
17     edgelist[2 * i + 1] = tbus;
18     if (netview) PetscCall(PetscPrintf(PETSC_COMM_SELF, "branch %" PetscInt_FMT ", bus[%" PetscInt_FMT "] -> bus[%" PetscInt_FMT "]\n", i, fbus, tbus));
19   }
20   if (netview) {
21     for (i = 0; i < pfdata->nbus; i++) {
22       if (pfdata->bus[i].ngen) {
23         PetscCall(PetscPrintf(PETSC_COMM_SELF, " bus %" PetscInt_FMT ": gen\n", i));
24       } else if (pfdata->bus[i].nload) {
25         PetscCall(PetscPrintf(PETSC_COMM_SELF, " bus %" PetscInt_FMT ": load\n", i));
26       }
27     }
28   }
29   PetscFunctionReturn(PETSC_SUCCESS);
30 }
31 
32 PetscErrorCode FormJacobian_Power_private(DM networkdm, Vec localX, Mat J, PetscInt nv, PetscInt ne, const PetscInt *vtx, const PetscInt *edges, void *appctx)
33 {
34   const PetscScalar *xarr;
35   PetscInt           i, v, row[2], col[8], e, vfrom, vto;
36   PetscInt           offsetfrom, offsetto, goffsetfrom, goffsetto, numComps;
37   PetscScalar        values[8];
38   PetscInt           j, key, offset, goffset;
39   PetscScalar        Vm;
40   UserCtx_Power     *user_power = (UserCtx_Power *)appctx;
41   PetscScalar        Sbase      = user_power->Sbase;
42   VERTEX_Power       bus;
43   PetscBool          ghostvtex;
44   void              *component;
45 
46   PetscFunctionBegin;
47   PetscCall(VecGetArrayRead(localX, &xarr));
48 
49   for (v = 0; v < nv; v++) {
50     PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[v], &ghostvtex));
51 
52     PetscCall(DMNetworkGetNumComponents(networkdm, vtx[v], &numComps));
53     for (j = 0; j < numComps; j++) {
54       PetscCall(DMNetworkGetLocalVecOffset(networkdm, vtx[v], ALL_COMPONENTS, &offset));
55       PetscCall(DMNetworkGetGlobalVecOffset(networkdm, vtx[v], ALL_COMPONENTS, &goffset));
56       PetscCall(DMNetworkGetComponent(networkdm, vtx[v], j, &key, &component, NULL));
57 
58       if (key == user_power->compkey_bus) {
59         PetscInt        nconnedges;
60         const PetscInt *connedges;
61 
62         bus = (VERTEX_Power)component;
63         if (!ghostvtex) {
64           /* Handle reference bus constrained dofs */
65           if (bus->ide == REF_BUS || bus->ide == ISOLATED_BUS) {
66             row[0]    = goffset;
67             row[1]    = goffset + 1;
68             col[0]    = goffset;
69             col[1]    = goffset + 1;
70             col[2]    = goffset;
71             col[3]    = goffset + 1;
72             values[0] = 1.0;
73             values[1] = 0.0;
74             values[2] = 0.0;
75             values[3] = 1.0;
76             PetscCall(MatSetValues(J, 2, row, 2, col, values, ADD_VALUES));
77             break;
78           }
79 
80           Vm = xarr[offset + 1];
81 
82           /* Shunt injections */
83           row[0]    = goffset;
84           row[1]    = goffset + 1;
85           col[0]    = goffset;
86           col[1]    = goffset + 1;
87           values[0] = values[1] = values[2] = values[3] = 0.0;
88           if (bus->ide != PV_BUS) {
89             values[1] = 2.0 * Vm * bus->gl / Sbase;
90             values[3] = -2.0 * Vm * bus->bl / Sbase;
91           }
92           PetscCall(MatSetValues(J, 2, row, 2, col, values, ADD_VALUES));
93         }
94 
95         PetscCall(DMNetworkGetSupportingEdges(networkdm, vtx[v], &nconnedges, &connedges));
96 
97         for (i = 0; i < nconnedges; i++) {
98           EDGE_Power      branch;
99           VERTEX_Power    busf, bust;
100           PetscInt        keyf, keyt;
101           PetscScalar     Gff, Bff, Gft, Bft, Gtf, Btf, Gtt, Btt;
102           const PetscInt *cone;
103           PetscScalar     Vmf, Vmt, thetaf, thetat, thetaft, thetatf;
104 
105           e = connedges[i];
106           PetscCall(DMNetworkGetComponent(networkdm, e, 0, &key, (void **)&branch, NULL));
107           if (!branch->status) continue;
108 
109           Gff = branch->yff[0];
110           Bff = branch->yff[1];
111           Gft = branch->yft[0];
112           Bft = branch->yft[1];
113           Gtf = branch->ytf[0];
114           Btf = branch->ytf[1];
115           Gtt = branch->ytt[0];
116           Btt = branch->ytt[1];
117 
118           PetscCall(DMNetworkGetConnectedVertices(networkdm, edges[e], &cone));
119           vfrom = cone[0];
120           vto   = cone[1];
121 
122           PetscCall(DMNetworkGetLocalVecOffset(networkdm, vfrom, ALL_COMPONENTS, &offsetfrom));
123           PetscCall(DMNetworkGetLocalVecOffset(networkdm, vto, ALL_COMPONENTS, &offsetto));
124           PetscCall(DMNetworkGetGlobalVecOffset(networkdm, vfrom, ALL_COMPONENTS, &goffsetfrom));
125           PetscCall(DMNetworkGetGlobalVecOffset(networkdm, vto, ALL_COMPONENTS, &goffsetto));
126 
127           if (goffsetto < 0) goffsetto = -goffsetto - 1;
128 
129           thetaf  = xarr[offsetfrom];
130           Vmf     = xarr[offsetfrom + 1];
131           thetat  = xarr[offsetto];
132           Vmt     = xarr[offsetto + 1];
133           thetaft = thetaf - thetat;
134           thetatf = thetat - thetaf;
135 
136           PetscCall(DMNetworkGetComponent(networkdm, vfrom, 0, &keyf, (void **)&busf, NULL));
137           PetscCall(DMNetworkGetComponent(networkdm, vto, 0, &keyt, (void **)&bust, NULL));
138 
139           if (vfrom == vtx[v]) {
140             if (busf->ide != REF_BUS) {
141               /*    farr[offsetfrom]   += Gff*Vmf*Vmf + Vmf*Vmt*(Gft*PetscCosScalar(thetaft) + Bft*PetscSinScalar(thetaft));  */
142               row[0]    = goffsetfrom;
143               col[0]    = goffsetfrom;
144               col[1]    = goffsetfrom + 1;
145               col[2]    = goffsetto;
146               col[3]    = goffsetto + 1;
147               values[0] = Vmf * Vmt * (Gft * -PetscSinScalar(thetaft) + Bft * PetscCosScalar(thetaft));            /* df_dthetaf */
148               values[1] = 2.0 * Gff * Vmf + Vmt * (Gft * PetscCosScalar(thetaft) + Bft * PetscSinScalar(thetaft)); /* df_dVmf */
149               values[2] = Vmf * Vmt * (Gft * PetscSinScalar(thetaft) + Bft * -PetscCosScalar(thetaft));            /* df_dthetat */
150               values[3] = Vmf * (Gft * PetscCosScalar(thetaft) + Bft * PetscSinScalar(thetaft));                   /* df_dVmt */
151 
152               PetscCall(MatSetValues(J, 1, row, 4, col, values, ADD_VALUES));
153             }
154             if (busf->ide != PV_BUS && busf->ide != REF_BUS) {
155               row[0] = goffsetfrom + 1;
156               col[0] = goffsetfrom;
157               col[1] = goffsetfrom + 1;
158               col[2] = goffsetto;
159               col[3] = goffsetto + 1;
160               /*    farr[offsetfrom+1] += -Bff*Vmf*Vmf + Vmf*Vmt*(-Bft*PetscCosScalar(thetaft) + Gft*PetscSinScalar(thetaft)); */
161               values[0] = Vmf * Vmt * (Bft * PetscSinScalar(thetaft) + Gft * PetscCosScalar(thetaft));
162               values[1] = -2.0 * Bff * Vmf + Vmt * (-Bft * PetscCosScalar(thetaft) + Gft * PetscSinScalar(thetaft));
163               values[2] = Vmf * Vmt * (-Bft * PetscSinScalar(thetaft) + Gft * -PetscCosScalar(thetaft));
164               values[3] = Vmf * (-Bft * PetscCosScalar(thetaft) + Gft * PetscSinScalar(thetaft));
165 
166               PetscCall(MatSetValues(J, 1, row, 4, col, values, ADD_VALUES));
167             }
168           } else {
169             if (bust->ide != REF_BUS) {
170               row[0] = goffsetto;
171               col[0] = goffsetto;
172               col[1] = goffsetto + 1;
173               col[2] = goffsetfrom;
174               col[3] = goffsetfrom + 1;
175               /*    farr[offsetto]   += Gtt*Vmt*Vmt + Vmt*Vmf*(Gtf*PetscCosScalar(thetatf) + Btf*PetscSinScalar(thetatf)); */
176               values[0] = Vmt * Vmf * (Gtf * -PetscSinScalar(thetatf) + Btf * PetscCosScalar(thetaft));            /* df_dthetat */
177               values[1] = 2.0 * Gtt * Vmt + Vmf * (Gtf * PetscCosScalar(thetatf) + Btf * PetscSinScalar(thetatf)); /* df_dVmt */
178               values[2] = Vmt * Vmf * (Gtf * PetscSinScalar(thetatf) + Btf * -PetscCosScalar(thetatf));            /* df_dthetaf */
179               values[3] = Vmt * (Gtf * PetscCosScalar(thetatf) + Btf * PetscSinScalar(thetatf));                   /* df_dVmf */
180 
181               PetscCall(MatSetValues(J, 1, row, 4, col, values, ADD_VALUES));
182             }
183             if (bust->ide != PV_BUS && bust->ide != REF_BUS) {
184               row[0] = goffsetto + 1;
185               col[0] = goffsetto;
186               col[1] = goffsetto + 1;
187               col[2] = goffsetfrom;
188               col[3] = goffsetfrom + 1;
189               /*    farr[offsetto+1] += -Btt*Vmt*Vmt + Vmt*Vmf*(-Btf*PetscCosScalar(thetatf) + Gtf*PetscSinScalar(thetatf)); */
190               values[0] = Vmt * Vmf * (Btf * PetscSinScalar(thetatf) + Gtf * PetscCosScalar(thetatf));
191               values[1] = -2.0 * Btt * Vmt + Vmf * (-Btf * PetscCosScalar(thetatf) + Gtf * PetscSinScalar(thetatf));
192               values[2] = Vmt * Vmf * (-Btf * PetscSinScalar(thetatf) + Gtf * -PetscCosScalar(thetatf));
193               values[3] = Vmt * (-Btf * PetscCosScalar(thetatf) + Gtf * PetscSinScalar(thetatf));
194 
195               PetscCall(MatSetValues(J, 1, row, 4, col, values, ADD_VALUES));
196             }
197           }
198         }
199         if (!ghostvtex && bus->ide == PV_BUS) {
200           row[0]    = goffset + 1;
201           col[0]    = goffset + 1;
202           values[0] = 1.0;
203           if (user_power->jac_error) values[0] = 50.0;
204           PetscCall(MatSetValues(J, 1, row, 1, col, values, ADD_VALUES));
205         }
206       }
207     }
208   }
209 
210   PetscCall(VecRestoreArrayRead(localX, &xarr));
211   PetscFunctionReturn(PETSC_SUCCESS);
212 }
213 
214 PetscErrorCode FormJacobian_Power(SNES snes, Vec X, Mat J, Mat Jpre, void *appctx)
215 {
216   DM              networkdm;
217   Vec             localX;
218   PetscInt        nv, ne;
219   const PetscInt *vtx, *edges;
220 
221   PetscFunctionBegin;
222   PetscCall(MatZeroEntries(J));
223 
224   PetscCall(SNESGetDM(snes, &networkdm));
225   PetscCall(DMGetLocalVector(networkdm, &localX));
226 
227   PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX));
228   PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX));
229 
230   PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges));
231   PetscCall(FormJacobian_Power_private(networkdm, localX, J, nv, ne, vtx, edges, appctx));
232 
233   PetscCall(DMRestoreLocalVector(networkdm, &localX));
234 
235   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
236   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
237   PetscFunctionReturn(PETSC_SUCCESS);
238 }
239 
240 PetscErrorCode FormFunction_Power(DM networkdm, Vec localX, Vec localF, PetscInt nv, PetscInt ne, const PetscInt *vtx, const PetscInt *edges, void *appctx)
241 {
242   UserCtx_Power     *User = (UserCtx_Power *)appctx;
243   PetscInt           e, v, vfrom, vto;
244   const PetscScalar *xarr;
245   PetscScalar       *farr;
246   PetscInt           offsetfrom, offsetto, offset, i, j, key, numComps;
247   PetscScalar        Vm;
248   PetscScalar        Sbase = User->Sbase;
249   VERTEX_Power       bus   = NULL;
250   GEN                gen;
251   LOAD               load;
252   PetscBool          ghostvtex;
253   void              *component;
254 
255   PetscFunctionBegin;
256   PetscCall(VecGetArrayRead(localX, &xarr));
257   PetscCall(VecGetArray(localF, &farr));
258 
259   for (v = 0; v < nv; v++) {
260     PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[v], &ghostvtex));
261     PetscCall(DMNetworkGetNumComponents(networkdm, vtx[v], &numComps));
262     PetscCall(DMNetworkGetLocalVecOffset(networkdm, vtx[v], ALL_COMPONENTS, &offset));
263 
264     for (j = 0; j < numComps; j++) {
265       PetscCall(DMNetworkGetComponent(networkdm, vtx[v], j, &key, &component, NULL));
266       if (key == User->compkey_bus) {
267         PetscInt        nconnedges;
268         const PetscInt *connedges;
269 
270         bus = (VERTEX_Power)component;
271         /* Handle reference bus constrained dofs */
272         if (bus->ide == REF_BUS || bus->ide == ISOLATED_BUS) {
273           farr[offset]     = xarr[offset] - bus->va * PETSC_PI / 180.0;
274           farr[offset + 1] = xarr[offset + 1] - bus->vm;
275           break;
276         }
277 
278         if (!ghostvtex) {
279           Vm = xarr[offset + 1];
280 
281           /* Shunt injections */
282           farr[offset] += Vm * Vm * bus->gl / Sbase;
283           if (bus->ide != PV_BUS) farr[offset + 1] += -Vm * Vm * bus->bl / Sbase;
284         }
285 
286         PetscCall(DMNetworkGetSupportingEdges(networkdm, vtx[v], &nconnedges, &connedges));
287         for (i = 0; i < nconnedges; i++) {
288           EDGE_Power      branch;
289           PetscInt        keye;
290           PetscScalar     Gff, Bff, Gft, Bft, Gtf, Btf, Gtt, Btt;
291           const PetscInt *cone;
292           PetscScalar     Vmf, Vmt, thetaf, thetat, thetaft, thetatf;
293 
294           e = connedges[i];
295           PetscCall(DMNetworkGetComponent(networkdm, e, 0, &keye, (void **)&branch, NULL));
296           if (!branch->status) continue;
297           Gff = branch->yff[0];
298           Bff = branch->yff[1];
299           Gft = branch->yft[0];
300           Bft = branch->yft[1];
301           Gtf = branch->ytf[0];
302           Btf = branch->ytf[1];
303           Gtt = branch->ytt[0];
304           Btt = branch->ytt[1];
305 
306           PetscCall(DMNetworkGetConnectedVertices(networkdm, e, &cone));
307           vfrom = cone[0];
308           vto   = cone[1];
309 
310           PetscCall(DMNetworkGetLocalVecOffset(networkdm, vfrom, ALL_COMPONENTS, &offsetfrom));
311           PetscCall(DMNetworkGetLocalVecOffset(networkdm, vto, ALL_COMPONENTS, &offsetto));
312 
313           thetaf  = xarr[offsetfrom];
314           Vmf     = xarr[offsetfrom + 1];
315           thetat  = xarr[offsetto];
316           Vmt     = xarr[offsetto + 1];
317           thetaft = thetaf - thetat;
318           thetatf = thetat - thetaf;
319 
320           if (vfrom == vtx[v]) {
321             farr[offsetfrom] += Gff * Vmf * Vmf + Vmf * Vmt * (Gft * PetscCosScalar(thetaft) + Bft * PetscSinScalar(thetaft));
322             farr[offsetfrom + 1] += -Bff * Vmf * Vmf + Vmf * Vmt * (-Bft * PetscCosScalar(thetaft) + Gft * PetscSinScalar(thetaft));
323           } else {
324             farr[offsetto] += Gtt * Vmt * Vmt + Vmt * Vmf * (Gtf * PetscCosScalar(thetatf) + Btf * PetscSinScalar(thetatf));
325             farr[offsetto + 1] += -Btt * Vmt * Vmt + Vmt * Vmf * (-Btf * PetscCosScalar(thetatf) + Gtf * PetscSinScalar(thetatf));
326           }
327         }
328       } else if (key == User->compkey_gen) {
329         if (!ghostvtex) {
330           gen = (GEN)component;
331           if (!gen->status) continue;
332           farr[offset] += -gen->pg / Sbase;
333           farr[offset + 1] += -gen->qg / Sbase;
334         }
335       } else if (key == User->compkey_load) {
336         if (!ghostvtex) {
337           load = (LOAD)component;
338           farr[offset] += load->pl / Sbase;
339           farr[offset + 1] += load->ql / Sbase;
340         }
341       }
342     }
343     if (bus && bus->ide == PV_BUS) farr[offset + 1] = xarr[offset + 1] - bus->vm;
344   }
345   PetscCall(VecRestoreArrayRead(localX, &xarr));
346   PetscCall(VecRestoreArray(localF, &farr));
347   PetscFunctionReturn(PETSC_SUCCESS);
348 }
349 
350 PetscErrorCode SetInitialGuess_Power(DM networkdm, Vec localX, PetscInt nv, PetscInt ne, const PetscInt *vtx, const PetscInt *edges, void *appctx)
351 {
352   VERTEX_Power   bus;
353   PetscInt       i;
354   GEN            gen;
355   PetscBool      ghostvtex, sharedv;
356   PetscScalar   *xarr;
357   PetscInt       key, numComps, j, offset;
358   void          *component;
359   PetscMPIInt    rank;
360   MPI_Comm       comm;
361   UserCtx_Power *User = (UserCtx_Power *)appctx;
362 
363   PetscFunctionBegin;
364   PetscCall(PetscObjectGetComm((PetscObject)networkdm, &comm));
365   PetscCallMPI(MPI_Comm_rank(comm, &rank));
366   PetscCall(VecGetArray(localX, &xarr));
367   for (i = 0; i < nv; i++) {
368     PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghostvtex));
369     PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &sharedv));
370     if (ghostvtex || sharedv) continue;
371 
372     PetscCall(DMNetworkGetLocalVecOffset(networkdm, vtx[i], ALL_COMPONENTS, &offset));
373     PetscCall(DMNetworkGetNumComponents(networkdm, vtx[i], &numComps));
374     for (j = 0; j < numComps; j++) {
375       PetscCall(DMNetworkGetComponent(networkdm, vtx[i], j, &key, &component, NULL));
376       if (key == User->compkey_bus) {
377         bus              = (VERTEX_Power)component;
378         xarr[offset]     = bus->va * PETSC_PI / 180.0;
379         xarr[offset + 1] = bus->vm;
380       } else if (key == User->compkey_gen) {
381         gen = (GEN)component;
382         if (!gen->status) continue;
383         xarr[offset + 1] = gen->vs;
384         break;
385       }
386     }
387   }
388   PetscCall(VecRestoreArray(localX, &xarr));
389   PetscFunctionReturn(PETSC_SUCCESS);
390 }
391