Actual source code: ex9busdmnetwork.c
petsc-3.11.4 2019-09-28
2: static char help[] = "Power grid stability analysis of a large power system.\n\
3: The base case is the WECC 9 bus system based on the example given in the book Power\n\
4: Systems Dynamics and Stability (Chapter 7) by P. Sauer and M. A. Pai.\n\
5: The base power grid in this example consists of 9 buses (nodes), 3 generators,\n\
6: 3 loads, and 9 transmission lines. The network equations are written\n\
7: in current balance form using rectangular coordiantes. \n\
8: DMNetwork is used to manage the variables and equations of the entire system.\n\
9: Input parameters include:\n\
10: -nc : number of copies of the base case\n\n" ;
12: /* T
13: Concepts: DMNetwork
14: Concepts: PETSc TS solver
16: This example was contributed by Bikiran Guha and Jianqiao Huang, Illinois Institute of Technology, 2017.
17: */
19: #include <petscts.h>
20: #include <petscdmnetwork.h>
22: #define FREQ 60
23: #define W_S (2*PETSC_PI*FREQ)
24: #define NGEN 3 /* No. of generators in the 9 bus system */
25: #define NLOAD 3 /* No. of loads in the 9 bus system */
26: #define NBUS 9 /* No. of buses in the 9 bus system */
27: #define NBRANCH 9 /* No. of branches in the 9 bus system */
29: typedef struct {
30: PetscInt id; /* Bus Number or extended bus name*/
31: PetscScalar mbase; /* MVA base of the machine */
32: PetscScalar PG; /* Generator active power output */
33: PetscScalar QG; /* Generator reactive power output */
35: /* Generator constants */
36: PetscScalar H; /* Inertia constant */
37: PetscScalar Rs; /* Stator Resistance */
38: PetscScalar Xd; /* d-axis reactance */
39: PetscScalar Xdp; /* d-axis transient reactance */
40: PetscScalar Xq; /* q-axis reactance Xq(1) set to 0.4360, value given in text 0.0969 */
41: PetscScalar Xqp; /* q-axis transient reactance */
42: PetscScalar Td0p; /* d-axis open circuit time constant */
43: PetscScalar Tq0p; /* q-axis open circuit time constant */
44: PetscScalar M; /* M = 2*H/W_S */
45: PetscScalar D; /* D = 0.1*M */
46: PetscScalar TM; /* Mechanical Torque */
48: /* Exciter system constants */
49: PetscScalar KA ; /* Voltage regulator gain constant */
50: PetscScalar TA; /* Voltage regulator time constant */
51: PetscScalar KE; /* Exciter gain constant */
52: PetscScalar TE; /* Exciter time constant */
53: PetscScalar KF; /* Feedback stabilizer gain constant */
54: PetscScalar TF; /* Feedback stabilizer time constant */
55: PetscScalar k1,k2; /* calculating the saturation function SE = k1*exp(k2*Efd) */
56: PetscScalar Vref; /* Voltage regulator voltage setpoint */
57: } Gen;
59: typedef struct {
60: PetscInt id; /* node id */
61: PetscInt nofgen; /* Number of generators at the bus*/
62: PetscInt nofload; /* Number of load at the bus*/
63: PetscScalar yff[2]; /* yff[0]= imaginary part of admittance, yff[1]=real part of admittance*/
64: PetscScalar vr; /* Real component of bus voltage */
65: PetscScalar vi; /* Imaginary component of bus voltage */
66: } Bus;
68: /* Load constants
69: We use a composite load model that describes the load and reactive powers at each time instant as follows
70: P(t) = \sum\limits_{i=0}^ld_nsegsp \ld_alphap_i*P_D0(\frac{V_m(t)}{V_m0})^\ld_betap_i
71: Q(t) = \sum\limits_{i=0}^ld_nsegsq \ld_alphaq_i*Q_D0(\frac{V_m(t)}{V_m0})^\ld_betaq_i
72: where
73: id - index of the load
74: ld_nsegsp,ld_nsegsq - Number of individual load models for real and reactive power loads
75: ld_alphap,ld_alphap - Percentage contribution (weights) or loads
76: P_D0 - Real power load
77: Q_D0 - Reactive power load
78: Vm(t) - Voltage magnitude at time t
79: Vm0 - Voltage magnitude at t = 0
80: ld_betap, ld_betaq - exponents describing the load model for real and reactive part
82: Note: All loads have the same characteristic currently.
83: */
84: typedef struct {
85: PetscInt id; /* bus id */
86: PetscInt ld_nsegsp,ld_nsegsq;
87: PetscScalar PD0, QD0;
88: PetscScalar ld_alphap[3]; /* ld_alphap=[1,0,0], an array, not a value, so use *ld_alphap; */
89: PetscScalar ld_betap[3],ld_alphaq[3],ld_betaq[3];
90: } Load;
92: typedef struct {
93: PetscInt id; /* node id */
94: PetscScalar yft[2]; /* yft[0]= imaginary part of admittance, yft[1]=real part of admittance*/
95: } Branch;
97: typedef struct {
98: PetscReal tfaulton,tfaultoff; /* Fault on and off times */
99: PetscReal t;
100: PetscReal t0,tmax; /* initial time and final time */
101: PetscInt faultbus; /* Fault bus */
102: PetscScalar Rfault; /* Fault resistance (pu) */
103: PetscScalar *ybusfault;
104: PetscBool alg_flg;
105: } Userctx;
107: /* Used to read data into the DMNetwork components */
108: PetscErrorCode read_data(PetscInt nc, Gen **pgen,Load **pload,Bus **pbus, Branch **pbranch, PetscInt **pedgelist)
109: {
110: PetscErrorCode ierr;
111: PetscInt i,j,row[1],col[2];
112: PetscInt *edgelist;
113: PetscInt nofgen[9] = {1,1,1,0,0,0,0,0,0}; /* Buses at which generators are incident */
114: PetscInt nofload[9] = {0,0,0,0,1,1,0,1,0}; /* Buses at which loads are incident */
115: PetscScalar *varr,M[3],D[3];
116: Bus *bus;
117: Branch *branch;
118: Gen *gen;
119: Load *load;
120: Mat Ybus;
121: Vec V0;
123: /*10 parameters*/
124: /* Generator real and reactive powers (found via loadflow) */
125: static const PetscScalar PG[3] = {0.716786142395021,1.630000000000000,0.850000000000000};
126: static const PetscScalar QG[3] = {0.270702180178785,0.066120127797275,-0.108402221791588};
128: /* Generator constants */
129: static const PetscScalar H[3] = {23.64,6.4,3.01}; /* Inertia constant */
130: static const PetscScalar Rs[3] = {0.0,0.0,0.0}; /* Stator Resistance */
131: static const PetscScalar Xd[3] = {0.146,0.8958,1.3125}; /* d-axis reactance */
132: static const PetscScalar Xdp[3] = {0.0608,0.1198,0.1813}; /* d-axis transient reactance */
133: static const PetscScalar Xq[3] = {0.4360,0.8645,1.2578}; /* q-axis reactance Xq(1) set to 0.4360, value given in text 0.0969 */
134: static const PetscScalar Xqp[3] = {0.0969,0.1969,0.25}; /* q-axis transient reactance */
135: static const PetscScalar Td0p[3] = {8.96,6.0,5.89}; /* d-axis open circuit time constant */
136: static const PetscScalar Tq0p[3] = {0.31,0.535,0.6}; /* q-axis open circuit time constant */
138: /* Exciter system constants (8 parameters)*/
139: static const PetscScalar KA[3] = {20.0,20.0,20.0}; /* Voltage regulartor gain constant */
140: static const PetscScalar TA[3] = {0.2,0.2,0.2}; /* Voltage regulator time constant */
141: static const PetscScalar KE[3] = {1.0,1.0,1.0}; /* Exciter gain constant */
142: static const PetscScalar TE[3] = {0.314,0.314,0.314}; /* Exciter time constant */
143: static const PetscScalar KF[3] = {0.063,0.063,0.063}; /* Feedback stabilizer gain constant */
144: static const PetscScalar TF[3] = {0.35,0.35,0.35}; /* Feedback stabilizer time constant */
145: static const PetscScalar k1[3] = {0.0039,0.0039,0.0039};
146: static const PetscScalar k2[3] = {1.555,1.555,1.555}; /* k1 and k2 for calculating the saturation function SE = k1*exp(k2*Efd) */
148: /* Load constants */
149: static const PetscScalar PD0[3] = {1.25,0.9,1.0};
150: static const PetscScalar QD0[3] = {0.5,0.3,0.35};
151: static const PetscScalar ld_alphaq[3] = {1,0,0};
152: static const PetscScalar ld_betaq[3] = {2,1,0};
153: static const PetscScalar ld_betap[3] = {2,1,0};
154: static const PetscScalar ld_alphap[3] = {1,0,0};
155: PetscInt ld_nsegsp[3] = {3,3,3};
156: PetscInt ld_nsegsq[3] = {3,3,3};
157: PetscViewer Xview,Ybusview;
158: PetscInt neqs_net,m,n;
161: /* Read V0 and Ybus from files */
162: PetscViewerBinaryOpen (PETSC_COMM_SELF ,"X.bin" ,FILE_MODE_READ ,&Xview);
163: PetscViewerBinaryOpen (PETSC_COMM_SELF ,"Ybus.bin" ,FILE_MODE_READ ,&Ybusview);
164: VecCreate (PETSC_COMM_SELF ,&V0);
165: VecLoad (V0,Xview);
167: MatCreate (PETSC_COMM_SELF ,&Ybus);
168: MatSetType (Ybus,MATBAIJ );
169: MatLoad (Ybus,Ybusview);
171: /* Destroy unnecessary stuff */
172: PetscViewerDestroy (&Xview);
173: PetscViewerDestroy (&Ybusview);
175: MatGetLocalSize (Ybus,&m,&n);
176: neqs_net = 2*NBUS; /* # eqs. for network subsystem */
177: if (m != neqs_net || n != neqs_net) SETERRQ (PETSC_COMM_SELF ,0,"matrix Ybus is in wrong sizes" );
179: M[0] = 2*H[0]/W_S;
180: M[1] = 2*H[1]/W_S;
181: M[2] = 2*H[2]/W_S;
182: D[0] = 0.1*M[0];
183: D[1] = 0.1*M[1];
184: D[2] = 0.1*M[2];
186: /* Alocate memory for total number of buses, generators, loads and branches */
187: PetscCalloc4 (NBUS*nc,&bus,NGEN*nc,&gen,NLOAD*nc,&load,NBRANCH*nc+(nc-1),&branch);
189: VecGetArray (V0,&varr);
191: /* read bus data */
192: for (i = 0; i < nc; i++) {
193: for (j = 0; j < NBUS; j++) {
194: bus[i*9+j].id = i*9+j;
195: bus[i*9+j].nofgen = nofgen[j];
196: bus[i*9+j].nofload = nofload[j];
197: bus[i*9+j].vr = varr[2*j];
198: bus[i*9+j].vi = varr[2*j+1];
199: row[0] = 2*j;
200: col[0] = 2*j;
201: col[1] = 2*j+1;
202: /* real and imaginary part of admittance from Ybus into yff */
203: MatGetValues (Ybus,1,row,2,col,bus[i*9+j].yff);
204: }
205: }
207: /* read generator data */
208: for (i = 0; i<nc; i++){
209: for (j = 0; j < NGEN; j++) {
210: gen[i*3+j].id = i*3+j;
211: gen[i*3+j].PG = PG[j];
212: gen[i*3+j].QG = QG[j];
213: gen[i*3+j].H = H[j];
214: gen[i*3+j].Rs = Rs[j];
215: gen[i*3+j].Xd = Xd[j];
216: gen[i*3+j].Xdp = Xdp[j];
217: gen[i*3+j].Xq = Xq[j];
218: gen[i*3+j].Xqp = Xqp[j];
219: gen[i*3+j].Td0p = Td0p[j];
220: gen[i*3+j].Tq0p = Tq0p[j];
221: gen[i*3+j].M = M[j];
222: gen[i*3+j].D = D[j];
224: /* exciter system */
225: gen[i*3+j].KA = KA[j];
226: gen[i*3+j].TA = TA[j];
227: gen[i*3+j].KE = KE[j];
228: gen[i*3+j].TE = TE[j];
229: gen[i*3+j].KF = KF[j];
230: gen[i*3+j].TF = TF[j];
231: gen[i*3+j].k1 = k1[j];
232: gen[i*3+j].k2 = k2[j];
233: }
234: }
236: /* read load data */
237: for (i = 0; i<nc; i++){
238: for (j = 0; j < NLOAD; j++) {
239: load[i*3+j].id = i*3+j;
240: load[i*3+j].PD0 = PD0[j];
241: load[i*3+j].QD0 = QD0[j];
242: load[i*3+j].ld_nsegsp = ld_nsegsp[j];
244: load[i*3+j].ld_alphap[0] = ld_alphap[0];
245: load[i*3+j].ld_alphap[1] = ld_alphap[1];
246: load[i*3+j].ld_alphap[2] = ld_alphap[2];
248: load[i*3+j].ld_alphaq[0] = ld_alphaq[0];
249: load[i*3+j].ld_alphaq[1] = ld_alphaq[1];
250: load[i*3+j].ld_alphaq[2] = ld_alphaq[2];
252: load[i*3+j].ld_betap[0] = ld_betap[0];
253: load[i*3+j].ld_betap[1] = ld_betap[1];
254: load[i*3+j].ld_betap[2] = ld_betap[2];
255: load[i*3+j].ld_nsegsq = ld_nsegsq[j];
257: load[i*3+j].ld_betaq[0] = ld_betaq[0];
258: load[i*3+j].ld_betaq[1] = ld_betaq[1];
259: load[i*3+j].ld_betaq[2] = ld_betaq[2];
260: }
261: }
262: PetscCalloc1 (2*NBRANCH*nc+2*(nc-1),&edgelist);
264: /* read edgelist */
265: for (i = 0; i<nc; i++){
266: for (j = 0; j < NBRANCH; j++) {
267: switch (j) {
268: case 0:
269: edgelist[i*18+2*j] = 0+9*i;
270: edgelist[i*18+2*j+1] = 3+9*i;
271: break ;
272: case 1:
273: edgelist[i*18+2*j] = 1+9*i;
274: edgelist[i*18+2*j+1] = 6+9*i;
275: break ;
276: case 2:
277: edgelist[i*18+2*j] = 2+9*i;
278: edgelist[i*18+2*j+1] = 8+9*i;
279: break ;
280: case 3:
281: edgelist[i*18+2*j] = 3+9*i;
282: edgelist[i*18+2*j+1] = 4+9*i;
283: break ;
284: case 4:
285: edgelist[i*18+2*j] = 3+9*i;
286: edgelist[i*18+2*j+1] = 5+9*i;
287: break ;
288: case 5:
289: edgelist[i*18+2*j] = 4+9*i;
290: edgelist[i*18+2*j+1] = 6+9*i;
291: break ;
292: case 6:
293: edgelist[i*18+2*j] = 5+9*i;
294: edgelist[i*18+2*j+1] = 8+9*i;
295: break ;
296: case 7:
297: edgelist[i*18+2*j] = 6+9*i;
298: edgelist[i*18+2*j+1] = 7+9*i;
299: break ;
300: case 8:
301: edgelist[i*18+2*j] = 7+9*i;
302: edgelist[i*18+2*j+1] = 8+9*i;
303: break ;
304: default:
305: break ;
306: }
307: }
308: }
310: /* for connecting last bus of previous network(9*i-1) to first bus of next network(9*i), the branch admittance=-0.0301407+j17.3611 */
311: for (i = 1; i<nc; i++){
312: edgelist[18*nc+2*(i-1)] = 8+(i-1)*9;
313: edgelist[18*nc+2*(i-1)+1] = 9*i;
315: /* adding admittances to the off-diagonal elements */
316: branch[9*nc+(i-1)].id = 9*nc+(i-1);
317: branch[9*nc+(i-1)].yft[0] = 17.3611;
318: branch[9*nc+(i-1)].yft[1] = -0.0301407;
320: /* subtracting admittances from the diagonal elements */
321: bus[9*i-1].yff[0] -= 17.3611;
322: bus[9*i-1].yff[1] -= -0.0301407;
324: bus[9*i].yff[0] -= 17.3611;
325: bus[9*i].yff[1] -= -0.0301407;
326: }
328: /* read branch data */
329: for (i = 0; i<nc; i++){
330: for (j = 0; j < NBRANCH; j++) {
331: branch[i*9+j].id = i*9+j;
333: row[0] = edgelist[2*j]*2;
334: col[0] = edgelist[2*j+1]*2;
335: col[1] = edgelist[2*j+1]*2+1;
336: MatGetValues (Ybus,1,row,2,col,branch[i*9+j].yft);/*imaginary part of admittance*/
337: }
338: }
340: *pgen = gen;
341: *pload = load;
342: *pbus = bus;
343: *pbranch = branch;
344: *pedgelist = edgelist;
346: VecRestoreArray (V0,&varr);
348: /* Destroy unnecessary stuff */
349: MatDestroy (&Ybus);
350: VecDestroy (&V0);
351: return (0);
352: }
354: PetscErrorCode SetInitialGuess(DM networkdm, Vec X)
355: {
357: Bus *bus;
358: Gen *gen;
359: PetscInt v,vStart,vEnd,offset;
360: PetscInt key,numComps,j;
361: PetscInt idx=0;
362: PetscBool ghostvtex;
363: Vec localX;
364: PetscScalar *xarr;
365: PetscScalar Vr=0,Vi=0,Vm,Vm2; /* Terminal voltage variables */
366: PetscScalar IGr, IGi; /* Generator real and imaginary current */
367: PetscScalar Eqp,Edp,delta; /* Generator variables */
368: PetscScalar Efd,RF,VR; /* Exciter variables */
369: PetscScalar Vd,Vq; /* Generator dq axis voltages */
370: PetscScalar Id,Iq; /* Generator dq axis currents */
371: PetscScalar theta; /* Generator phase angle */
372: PetscScalar SE;
373: void* component;
376: DMNetworkGetVertexRange (networkdm,&vStart,&vEnd);
377: DMGetLocalVector (networkdm,&localX);
379: VecSet (X,0.0);
380: DMGlobalToLocalBegin (networkdm,X,INSERT_VALUES ,localX);
381: DMGlobalToLocalEnd (networkdm,X,INSERT_VALUES ,localX);
383: VecGetArray (localX,&xarr);
385: for (v = vStart; v < vEnd; v++) {
386: DMNetworkIsGhostVertex (networkdm,v,&ghostvtex);
387: if (ghostvtex) continue ;
389: DMNetworkGetVariableOffset (networkdm,v,&offset);
390: DMNetworkGetNumComponents (networkdm,v,&numComps);
391: for (j=0; j < numComps; j++) {
392: DMNetworkGetComponent (networkdm,v,j,&key,&component);
393: if (key == 1) {
394: bus = (Bus*)(component);
396: xarr[offset] = bus->vr;
397: xarr[offset+1] = bus->vi;
399: Vr = bus->vr;
400: Vi = bus->vi;
401: } else if (key == 2) {
402: gen = (Gen*)(component);
404: Vm = PetscSqrtScalar(Vr*Vr + Vi*Vi);
405: Vm2 = Vm*Vm;
406: /* Real part of gen current */
407: IGr = (Vr*gen->PG + Vi*gen->QG)/Vm2;
408: /* Imaginary part of gen current */
409: IGi = (Vi*gen->PG - Vr*gen->QG)/Vm2;
411: /* Machine angle */
412: delta = atan2(Vi+gen->Xq*IGr,Vr-gen->Xq*IGi);
413: theta = PETSC_PI/2.0 - delta;
415: /* d-axis stator current */
416: Id = IGr*PetscCosScalar(theta) - IGi*PetscSinScalar(theta);
418: /* q-axis stator current */
419: Iq = IGr*PetscSinScalar(theta) + IGi*PetscCosScalar(theta);
421: Vd = Vr*PetscCosScalar(theta) - Vi*PetscSinScalar(theta);
422: Vq = Vr*PetscSinScalar(theta) + Vi*PetscCosScalar(theta);
424: /* d-axis transient EMF */
425: Edp = Vd + gen->Rs*Id - gen->Xqp*Iq;
427: /* q-axis transient EMF */
428: Eqp = Vq + gen->Rs*Iq + gen->Xdp*Id;
430: gen->TM = gen->PG;
431: idx = offset+2;
433: xarr[idx] = Eqp;
434: xarr[idx+1] = Edp;
435: xarr[idx+2] = delta;
436: xarr[idx+3] = W_S;
437: xarr[idx+4] = Id;
438: xarr[idx+5] = Iq;
440: /* Exciter */
441: Efd = Eqp + (gen->Xd - gen->Xdp)*Id;
442: SE = gen->k1*PetscExpScalar(gen->k2*Efd);
443: VR = gen->KE*Efd + SE;
444: RF = gen->KF*Efd/gen->TF;
446: xarr[idx+6] = Efd;
447: xarr[idx+7] = RF;
448: xarr[idx+8] = VR;
450: gen->Vref = Vm + (VR/gen->KA);
451: }
452: }
453: }
454: VecRestoreArray (localX,&xarr);
455: DMLocalToGlobalBegin (networkdm,localX,ADD_VALUES ,X);
456: DMLocalToGlobalEnd (networkdm,localX,ADD_VALUES ,X);
457: DMRestoreLocalVector (networkdm,&localX);
458: return (0);
459: }
461: /* Converts from machine frame (dq) to network (phase a real,imag) reference frame */
462: PetscErrorCode dq2ri(PetscScalar Fd,PetscScalar Fq,PetscScalar delta,PetscScalar *Fr,PetscScalar *Fi)
463: {
465: *Fr = Fd*PetscSinScalar(delta) + Fq*PetscCosScalar(delta);
466: *Fi = -Fd*PetscCosScalar(delta) + Fq*PetscSinScalar(delta);
467: return (0);
468: }
470: /* Converts from network frame ([phase a real,imag) to machine (dq) reference frame */
471: PetscErrorCode ri2dq(PetscScalar Fr,PetscScalar Fi,PetscScalar delta,PetscScalar *Fd,PetscScalar *Fq)
472: {
474: *Fd = Fr*PetscSinScalar(delta) - Fi*PetscCosScalar(delta);
475: *Fq = Fr*PetscCosScalar(delta) + Fi*PetscSinScalar(delta);
476: return (0);
477: }
479: /* Computes F(t,U,U_t) where F() = 0 is the DAE to be solved. */
480: PetscErrorCode FormIFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,Userctx *user)
481: {
482: PetscErrorCode ierr;
483: DM networkdm;
484: Vec localX,localXdot,localF;
485: PetscInt vfrom,vto,offsetfrom,offsetto;
486: PetscInt v,vStart,vEnd,e;
487: PetscScalar *farr;
488: PetscScalar Vd,Vq,SE;
489: const PetscScalar *xarr,*xdotarr;
490: void* component;
493: VecSet (F,0.0);
495: TSGetDM (ts,&networkdm);
496: DMGetLocalVector (networkdm,&localF);
497: DMGetLocalVector (networkdm,&localX);
498: DMGetLocalVector (networkdm,&localXdot);
499: VecSet (localF,0.0);
501: /* update ghost values of localX and localXdot */
502: DMGlobalToLocalBegin (networkdm,X,INSERT_VALUES ,localX);
503: DMGlobalToLocalEnd (networkdm,X,INSERT_VALUES ,localX);
505: DMGlobalToLocalBegin (networkdm,Xdot,INSERT_VALUES ,localXdot);
506: DMGlobalToLocalEnd (networkdm,Xdot,INSERT_VALUES ,localXdot);
508: VecGetArrayRead (localX,&xarr);
509: VecGetArrayRead (localXdot,&xdotarr);
510: VecGetArray (localF,&farr);
512: DMNetworkGetVertexRange (networkdm,&vStart,&vEnd);
514: for (v=vStart; v < vEnd; v++) {
515: PetscInt i,j,offset,key;
516: PetscScalar Vr, Vi;
517: Bus *bus;
518: Gen *gen;
519: Load *load;
520: PetscBool ghostvtex;
521: PetscInt numComps;
522: PetscScalar Yffr,Yffi; /* Real and imaginary fault admittances */
523: PetscScalar Vm,Vm2,Vm0;
524: PetscScalar Vr0=0,Vi0=0;
525: PetscScalar PD,QD;
527: DMNetworkIsGhostVertex (networkdm,v,&ghostvtex);
528: DMNetworkGetNumComponents (networkdm,v,&numComps);
529: DMNetworkGetVariableOffset (networkdm,v,&offset);
531: for (j = 0; j < numComps; j++) {
532: DMNetworkGetComponent (networkdm,v,j,&key,&component);
533: if (key == 1) {
534: PetscInt nconnedges;
535: const PetscInt *connedges;
537: bus = (Bus*)(component);
538: if (!ghostvtex) {
539: Vr = xarr[offset];
540: Vi = xarr[offset+1];
542: Yffr = bus->yff[1];
543: Yffi = bus->yff[0];
545: if (user->alg_flg){
546: Yffr += user->ybusfault[bus->id*2+1];
547: Yffi += user->ybusfault[bus->id*2];
548: }
549: Vr0 = bus->vr;
550: Vi0 = bus->vi;
552: /* Network current balance residual IG + Y*V + IL = 0. Only YV is added here.
553: The generator current injection, IG, and load current injection, ID are added later
554: */
555: farr[offset] += Yffi*Vr + Yffr*Vi; /* imaginary current due to diagonal elements */
556: farr[offset+1] += Yffr*Vr - Yffi*Vi; /* real current due to diagonal elements */
557: }
559: DMNetworkGetSupportingEdges(networkdm,v,&nconnedges,&connedges);
561: for (i=0; i < nconnedges; i++) {
562: Branch *branch;
563: PetscInt keye;
564: PetscScalar Yfti, Yftr, Vfr, Vfi, Vtr, Vti;
565: const PetscInt *cone;
567: e = connedges[i];
568: DMNetworkGetComponent (networkdm,e,0,&keye,(void**)&branch);
570: Yfti = branch->yft[0];
571: Yftr = branch->yft[1];
573: DMNetworkGetConnectedVertices (networkdm,e,&cone);
575: vfrom = cone[0];
576: vto = cone[1];
578: DMNetworkGetVariableOffset (networkdm,vfrom,&offsetfrom);
579: DMNetworkGetVariableOffset (networkdm,vto,&offsetto);
581: /* From bus and to bus real and imaginary voltages */
582: Vfr = xarr[offsetfrom];
583: Vfi = xarr[offsetfrom+1];
584: Vtr = xarr[offsetto];
585: Vti = xarr[offsetto+1];
587: if (vfrom == v) {
588: farr[offsetfrom] += Yftr*Vti + Yfti*Vtr;
589: farr[offsetfrom+1] += Yftr*Vtr - Yfti*Vti;
590: } else {
591: farr[offsetto] += Yftr*Vfi + Yfti*Vfr;
592: farr[offsetto+1] += Yftr*Vfr - Yfti*Vfi;
593: }
594: }
595: } else if (key == 2){
596: if (!ghostvtex) {
597: PetscScalar Eqp,Edp,delta,w; /* Generator variables */
598: PetscScalar Efd,RF,VR; /* Exciter variables */
599: PetscScalar Id,Iq; /* Generator dq axis currents */
600: PetscScalar IGr,IGi,Zdq_inv[4],det;
601: PetscScalar Xd,Xdp,Td0p,Xq,Xqp,Tq0p,TM,D,M,Rs; /* Generator parameters */
602: PetscScalar k1,k2,KE,TE,TF,KA,KF,Vref,TA; /* Generator parameters */
603: PetscInt idx;
605: gen = (Gen*)(component);
606: idx = offset + 2;
608: /* Generator state variables */
609: Eqp = xarr[idx];
610: Edp = xarr[idx+1];
611: delta = xarr[idx+2];
612: w = xarr[idx+3];
613: Id = xarr[idx+4];
614: Iq = xarr[idx+5];
615: Efd = xarr[idx+6];
616: RF = xarr[idx+7];
617: VR = xarr[idx+8];
619: /* Generator parameters */
620: Xd = gen->Xd;
621: Xdp = gen->Xdp;
622: Td0p = gen->Td0p;
623: Xq = gen->Xq;
624: Xqp = gen->Xqp;
625: Tq0p = gen->Tq0p;
626: TM = gen->TM;
627: D = gen->D;
628: M = gen->M;
629: Rs = gen->Rs;
630: k1 = gen->k1;
631: k2 = gen->k2;
632: KE = gen->KE;
633: TE = gen->TE;
634: TF = gen->TF;
635: KA = gen->KA;
636: KF = gen->KF;
637: Vref = gen->Vref;
638: TA = gen->TA;
640: /* Generator differential equations */
641: farr[idx] = (Eqp + (Xd - Xdp)*Id - Efd)/Td0p + xdotarr[idx];
642: farr[idx+1] = (Edp - (Xq - Xqp)*Iq)/Tq0p + xdotarr[idx+1];
643: farr[idx+2] = -w + W_S + xdotarr[idx+2];
644: farr[idx+3] = (-TM + Edp*Id + Eqp*Iq + (Xqp - Xdp)*Id*Iq + D*(w - W_S))/M + xdotarr[idx+3];
646: Vr = xarr[offset]; /* Real part of generator terminal voltage */
647: Vi = xarr[offset+1]; /* Imaginary part of the generator terminal voltage */
649: ri2dq(Vr,Vi,delta,&Vd,&Vq);
651: /* Algebraic equations for stator currents */
652: det = Rs*Rs + Xdp*Xqp;
654: Zdq_inv[0] = Rs/det;
655: Zdq_inv[1] = Xqp/det;
656: Zdq_inv[2] = -Xdp/det;
657: Zdq_inv[3] = Rs/det;
659: farr[idx+4] = Zdq_inv[0]*(-Edp + Vd) + Zdq_inv[1]*(-Eqp + Vq) + Id;
660: farr[idx+5] = Zdq_inv[2]*(-Edp + Vd) + Zdq_inv[3]*(-Eqp + Vq) + Iq;
662: /* Add generator current injection to network */
663: dq2ri(Id,Iq,delta,&IGr,&IGi);
665: farr[offset] -= IGi;
666: farr[offset+1] -= IGr;
668: Vm = PetscSqrtScalar(Vd*Vd + Vq*Vq);
669: SE = k1*PetscExpScalar(k2*Efd);
671: /* Exciter differential equations */
672: farr[idx+6] = (KE*Efd + SE - VR)/TE + xdotarr[idx+6];
673: farr[idx+7] = (RF - KF*Efd/TF)/TF + xdotarr[idx+7];
674: farr[idx+8] = (VR - KA*RF + KA*KF*Efd/TF - KA*(Vref - Vm))/TA + xdotarr[idx+8];
675: }
676: } else if (key ==3){
677: if (!ghostvtex) {
678: PetscInt k;
679: PetscInt ld_nsegsp;
680: PetscInt ld_nsegsq;
681: PetscScalar *ld_alphap;
682: PetscScalar *ld_betap,*ld_alphaq,*ld_betaq,PD0, QD0, IDr,IDi;
684: load = (Load*)(component);
686: /* Load Parameters */
687: ld_nsegsp = load->ld_nsegsp;
688: ld_alphap = load->ld_alphap;
689: ld_betap = load->ld_betap;
690: ld_nsegsq = load->ld_nsegsq;
691: ld_alphaq = load->ld_alphaq;
692: ld_betaq = load->ld_betaq;
693: PD0 = load->PD0;
694: QD0 = load->QD0;
696: Vr = xarr[offset]; /* Real part of generator terminal voltage */
697: Vi = xarr[offset+1]; /* Imaginary part of the generator terminal voltage */
698: Vm = PetscSqrtScalar(Vr*Vr + Vi*Vi);
699: Vm2 = Vm*Vm;
700: Vm0 = PetscSqrtScalar(Vr0*Vr0 + Vi0*Vi0);
701: PD = QD = 0.0;
702: for (k=0; k < ld_nsegsp; k++) PD += ld_alphap[k]*PD0*PetscPowScalar((Vm/Vm0),ld_betap[k]);
703: for (k=0; k < ld_nsegsq; k++) QD += ld_alphaq[k]*QD0*PetscPowScalar((Vm/Vm0),ld_betaq[k]);
705: /* Load currents */
706: IDr = (PD*Vr + QD*Vi)/Vm2;
707: IDi = (-QD*Vr + PD*Vi)/Vm2;
709: farr[offset] += IDi;
710: farr[offset+1] += IDr;
711: }
712: }
713: }
714: }
716: VecRestoreArrayRead (localX,&xarr);
717: VecRestoreArrayRead (localXdot,&xdotarr);
718: VecRestoreArray (localF,&farr);
719: DMRestoreLocalVector (networkdm,&localX);
720: DMRestoreLocalVector (networkdm,&localXdot);
722: DMLocalToGlobalBegin (networkdm,localF,ADD_VALUES ,F);
723: DMLocalToGlobalEnd (networkdm,localF,ADD_VALUES ,F);
724: DMRestoreLocalVector (networkdm,&localF);
725: return (0);
726: }
728: /* This function is used for solving the algebraic system only during fault on and
729: off times. It computes the entire F and then zeros out the part corresponding to
730: differential equations
731: F = [0;g(y)];
732: */
733: PetscErrorCode AlgFunction (SNES snes, Vec X, Vec F, void *ctx)
734: {
736: DM networkdm;
737: Vec localX,localF;
738: PetscInt vfrom,vto,offsetfrom,offsetto;
739: PetscInt v,vStart,vEnd,e;
740: PetscScalar *farr;
741: Userctx *user=(Userctx*)ctx;
742: const PetscScalar *xarr;
743: void* component;
746: VecSet (F,0.0);
747: SNESGetDM (snes,&networkdm);
748: DMGetLocalVector (networkdm,&localF);
749: DMGetLocalVector (networkdm,&localX);
750: VecSet (localF,0.0);
752: /* update ghost values of locaX and locaXdot */
753: DMGlobalToLocalBegin (networkdm,X,INSERT_VALUES ,localX);
754: DMGlobalToLocalEnd (networkdm,X,INSERT_VALUES ,localX);
756: VecGetArrayRead (localX,&xarr);
757: VecGetArray (localF,&farr);
759: DMNetworkGetVertexRange (networkdm,&vStart,&vEnd);
761: for (v=vStart; v < vEnd; v++) {
762: PetscInt i,j,offset,key,numComps;
763: PetscScalar Vr, Vi, Yffr, Yffi, Vm, Vm2, Vm0, Vr0=0, Vi0=0, PD, QD;
764: Bus *bus;
765: Gen *gen;
766: Load *load;
767: PetscBool ghostvtex;
769: DMNetworkIsGhostVertex (networkdm,v,&ghostvtex);
770: DMNetworkGetNumComponents (networkdm,v,&numComps);
771: DMNetworkGetVariableOffset (networkdm,v,&offset);
773: for (j = 0; j < numComps; j++) {
774: DMNetworkGetComponent (networkdm,v,j,&key,&component);
775: if (key == 1) {
776: PetscInt nconnedges;
777: const PetscInt *connedges;
779: bus = (Bus*)(component);
780: if (!ghostvtex) {
781: Vr = xarr[offset];
782: Vi = xarr[offset+1];
784: Yffr = bus->yff[1];
785: Yffi = bus->yff[0];
786: if (user->alg_flg){
787: Yffr += user->ybusfault[bus->id*2+1];
788: Yffi += user->ybusfault[bus->id*2];
789: }
790: Vr0 = bus->vr;
791: Vi0 = bus->vi;
793: farr[offset] += Yffi*Vr + Yffr*Vi;
794: farr[offset+1] += Yffr*Vr - Yffi*Vi;
795: }
796: DMNetworkGetSupportingEdges(networkdm,v,&nconnedges,&connedges);
798: for (i=0; i < nconnedges; i++) {
799: Branch *branch;
800: PetscInt keye;
801: PetscScalar Yfti, Yftr, Vfr, Vfi, Vtr, Vti;
802: const PetscInt *cone;
804: e = connedges[i];
805: DMNetworkGetComponent (networkdm,e,0,&keye,(void**)&branch);
807: Yfti = branch->yft[0];
808: Yftr = branch->yft[1];
810: DMNetworkGetConnectedVertices (networkdm,e,&cone);
811: vfrom = cone[0];
812: vto = cone[1];
814: DMNetworkGetVariableOffset (networkdm,vfrom,&offsetfrom);
815: DMNetworkGetVariableOffset (networkdm,vto,&offsetto);
line818">818: Vfr = xarr[offse
line819">819: Vfi = xarr[offsetf
line820">820: Vtr = xarr[off
line821">821: Vti = xarr[offse
line823">823: if (vfrom
line824">824: farr[offsetfrom] += Yftr*Vti + Yf
line825">825: farr[offsetfrom+1] += Yftr*Vtr - Yf
line826">826: } else
line827">827: farr[offsetto] += Yftr*Vfi + Yf
line828">828: farr[offsetto+1] += Yftr*Vfr - Yf
line829">829:
line830">830:
line831">831: } else if (key
line832">832: if (!ghost
/* Generator variables */
/* Generator dq axis currents */
line835">835: PetscScalar Vd,Vq,IGr,IGi,Zdq_inv[
line836">836: PetscInt
/* Generator parameters */
line839">839: gen = (Gen*)(comp
line840">840: idx = offs
/* Generator state variables */
line843">843: Eqp = xar
line844">844: Edp = xarr[
line845">845: delta = xarr[
/* w = xarr[idx+3]; not being used */
line847">847: Id = xarr[
line848">848: Iq = xarr[
/* Generator parameters */
line851">851: Xdp = gen-&
line852">852: Xqp = gen-&
line853">853: Rs = gen-
/* Set generator differential equation residual functions to zero */
line856">856: farr[idx]
line857">857: farr[idx+
line858">858: farr[idx+
line859">859: farr[idx+
/* Real part of generator terminal voltage */
/* Imaginary part of the generator terminal voltage */
line864">864: ri2dq(Vr,Vi,delta,&Vd,&a
/* Algebraic equations for stator currents */
line867">867: det = Rs*Rs + X
line869">869: Zdq_inv[0] =
line870">870: Zdq_inv[1] = X
line871">871: Zdq_inv[2] = -X
line872">872: Zdq_inv[3] =
line874">874: farr[idx+4] = Zdq_inv[0]*(-Edp + Vd) + Zdq_inv[1]*(-Eqp + Vq
line875">875: farr[idx+5] = Zdq_inv[2]*(-Edp + Vd) + Zdq_inv[3]*(-Eqp + Vq
/* Add generator current injection to network */
line878">878: dq2ri(Id,Iq,delta,&IGr,&am
line880">880: farr[offset]
line881">881: farr[offset+1]
/* Vm = PetscSqrtScalar(Vd*Vd + Vq*Vq);*/ /* a compiler warning: "Value stored to 'Vm' is never read" - comment out by Hong Zhang */
/* Set exciter differential equation residual functions equal to zero*/
line886">886: farr[idx+
line887">887: farr[idx+
line888">888: farr[idx+
line889">889:
line890">890: } else if (ke
line891">891: if (!ghost
line892">892: PetscInt k,ld_nsegsp,ld_
line893">893: PetscScalar *ld_alphap,*ld_betap,*ld_alphaq,*ld_betaq,PD0,QD0,I
line895">895: load = (Load*)(comp
/* Load Parameters */
line898">898: ld_nsegsp = load->ld_
line899">899: ld_alphap = load->ld_
line900">900: ld_betap = load->ld
line901">901: ld_nsegsq = load->ld_
line902">902: ld_alphaq = load->ld_
line903">903: ld_betaq = load->ld
line905">905: PD0 = load-&
line906">906: QD0 = load-&
/* Real part of generator terminal voltage */
/* Imaginary part of the generator terminal voltage */
line910">910: Vm = PetscSqrtScalar(Vr*Vr +
line911">911: Vm2 =
line912">912: Vm0 = PetscSqrtScalar(Vr0*Vr0 + Vi
line913">913: PD = QD
line914">914: for (k=0; k < ld_nsegsp; k++) PD += ld_alphap[k]*PD0*PetscPowScalar((Vm/Vm0),ld_bet
line915">915: for (k=0; k < ld_nsegsq; k++) QD += ld_alphaq[k]*QD0*PetscPowScalar((Vm/Vm0),ld_bet
/* Load currents */
line918">918: IDr = (PD*Vr + QD*V
line919">919: IDi = (-QD*Vr + PD*V
line921">921: farr[offset]
line922">922: farr[offset+1]
line923">923:
line924">924:
line925">925:
line926">926:
line928">928: VecRestoreArrayRead (localX,&
line929">929: VecRestoreArray (localF,&
line930">930: DMRestoreLocalVector (networkdm,&l
line932">932: DMLocalToGlobalBegin (networkdm,localF,ADD_VALUES<
line933">933: DMLocalToGlobalEnd (networkdm,localF,ADD_VALUES<
line934">934: DMRestoreLocalVector (networkdm,&l
line935">935: return
line936">936
line938">938: int main(int argc,char ** argv)
line939">939
line941">941: PetscInt i,j,*edgelist= NULL,eStart,eEnd,vStar
line942">942: PetscInt genj,loadj,component
/* No. of copies (default = 1) */
line944">944: PetscMPIInt siz
line945">945: Vec X
line946">946: TS
line947">947: SNES snes_al
line948">948: Bus
line949">949: Branch *
line950">950: Gen
line951">951: Load
line952">952: DM net
line953">953: PetscLogStage
line954">954: Userctx
line955">955: KSP
line956">956: PC
line957">957: PetscInt numEdges=0,numVertices=0,NumEdges=PETSC_DETERMINE ,NumVertices=PETSC_DETERMI
line959">959: PetscInitialize (&argc,&argv,"ex9busnetworkops" ,help);if (ierr) return
line960">960: PetscOptionsGetInt (NULL,NULL,"-nc" ,&nc
line961">961: MPI_Comm_size (PETSC_COMM_WORLD ,&
line962">962: MPI_Comm_rank (PETSC_COMM_WORLD ,&
/* Read initial voltage vector and Ybus */
line965">965: if (!
line966">966: read_data(nc,&gen,&load,&bus,&branch,&edg
line967">967:
line969">969: DMNetworkCreate (PETSC_COMM_WORLD ,&netw
line970">970: DMNetworkRegisterComponent (networkdm,"branchstruct" ,sizeof (Branch),&componentk
line971">971: DMNetworkRegisterComponent (networkdm,"busstruct" ,sizeof (Bus),&componentk
line972">972: DMNetworkRegisterComponent (networkdm,"genstruct" ,sizeof (Gen),&componentk
line973">973: DMNetworkRegisterComponent (networkdm,"loadstruct" ,sizeof (Load),&componentk
line975">975: PetscLogStageRegister ("Create network" ,&s
line976">976: PetscLogStagePush (s
/* Set local number of nodes and edges */
line979">979: if (
line980">980: numVertices = NBUS*nc; numEdges = NBRANCH*nc+
line981">981:
line982">982: DMNetworkSetSizes (networkdm,1,0,&numVertices,&numEdges,&NumVertices,&Num
/* Add edge connectivity */
line985">985: DMNetworkSetEdgeList (networkdm,&edgelist
/* Set up the network layout */
line988">988: DMNetworkLayoutSetUp (netw
line990">990: if (!
line991">991: PetscFree (edg
line992">992:
/* Add network components: physical parameters of nodes and branches */
line995">995: if (!
line996">996: DMNetworkGetEdgeRange (networkdm,&eStart,&
line997">997: genj=0; l
line998">998: for (i = eStart; i < eEnd;
line999">999: DMNetworkAddComponent (networkdm,i,componentkey[0],&branch[i-eS
line1000">1000:
line1002">1002: DMNetworkGetVertexRange (networkdm,&vStart,&
line1004">1004: for (i = vStart; i < vEnd;
line1005">1005: DMNetworkAddComponent (networkdm,i,componentkey[1],&bus[i-vS
/* Add number of variables */
line1007">1007: DMNetworkAddNumVariables (networkd
line1008">1008: if (bus[i-vStart].no
line1009">1009: for (j = 0; j < bus[i-vStart].nofgen;
line1010">1010: DMNetworkAddComponent (networkdm,i,componentkey[2],&gen[ge
line1011">1011: DMNetworkAddNumVariables (networkd
line1012">1012:
line1013">1013:
line1014">1014: if (bus[i-vStart].nof
line1015">1015: for (j=0; j < bus[i-vStart].nofload;
line1016">1016: DMNetworkAddComponent (networkdm,i,componentkey[3],&load[loa
line1017">1017:
line1018">1018:
line1019">1019:
line1020">1020:
line1022">1022: DMSetUp (netw
line1024">1024: if (!
line1025">1025: PetscFree4 (bus,gen,load,b
line1026">1026:
/* for parallel options: Network partitioning and distribution of data */
line1029">1029: if (size &g
line1030">1030: DMNetworkDistribute (&networ
line1031">1031:
line1032">1032: PetscLogStagePop
line1034">1034: DMCreateGlobalVector (networkdm,&
line1036">1036: SetInitialGuess(networ
/* Options for fault simulation */
line1039">1039: PetscOptionsBegin (PETSC_COMM_WORLD ,NULL,"Transient stability fault options" ,""
line1040">1040: user.tfaulton
line1041">1041: user.tfaultoff
line1042">1042: user.Rfault =
line1043">1043: user.faultbu
line1044">1044: PetscOptionsReal ("-tfaulton" ,"" ,"" ,user.tfaulton,&user.tfaulton
line1045">1045: PetscOptionsReal ("-tfaultoff" ,"" ,"" ,user.tfaultoff,&user.tfaultoff
line1046">1046: PetscOptionsInt ("-faultbus" ,"" ,"" ,user.faultbus,&user.faultbus
line1047">1047: user.t0
line1048">1048: user.tmax
line1049">1049: PetscOptionsReal ("-t0" ,"" ,"" ,user.t0,&user.t0
line1050">1050: PetscOptionsReal ("-tmax" ,"" ,"" ,user.tmax,&user.tmax
line1052">1052: PetscMalloc1 (18*nc,&user.ybus
line1053">1053: for (i = 0; i < 18*nc;
line1054">1054: user.ybusfault[
line1055">1055:
line1056">1056: user.ybusfault[user.faultbus*2+1] = 1/user.
line1057">1057: PetscOptionsEnd
/* Setup TS solver */
/*--------------------------------------------------------*/
line1061">1061: TSCreate (PETSC_COMM_WORLD ,&a
line1062">1062: TSSetDM (ts,(DM )netw
line1063">1063: TSSetType (ts,TSC
line1065">1065: TSGetSNES (ts,&
line1066">1066: SNESGetKSP (snes,&am
line1067">1067: KSPGetPC (ksp,&a
line1068">1068: PCSetType (pc,PCBJACOB
line1070">1070: TSSetIFunction (ts,NULL,(TSIFunction) FormIFunction,&
line1071">1071: TSSetMaxTime (ts,user.tfa
line1072">1072: TSSetExactFinalTime (ts,TS_EXACTFINALTIME_STEPOVE
line1073">1073: TSSetTimeStep (ts
line1074">1074: TSSetFromOptions
/*user.alg_flg = PETSC_TRUE is the period when fault exists. We add fault admittance to Ybus matrix.
eg, fault bus is 8. Y88(new)=Y88(old)+Yfault. */
line1078">1078: user.alg_flg = PETSC_FAL
/* Prefault period */
line1081">1081: if (!
line1082">1082: PetscPrintf (PETSC_COMM_SELF ,"... (1) Prefault period ... \n"
line1083">1083:
line1085">1085: TSSetSolution
line1086">1086: TSSetUp
line1087">1087: TSSolve
/* Create the nonlinear solver for solving the algebraic system */
line1090">1090: VecDuplicate (X,&
line1092">1092: SNESCreate (PETSC_COMM_WORLD ,&sne
line1093">1093: SNESSetDM (snes_alg,(DM )netw
line1094">1094: SNESSetFunction (snes_alg,F_alg,AlgFunction,&
line1095">1095: SNESSetOptionsPrefix (snes_alg,"alg_"
line1096">1096: SNESSetFromOptions (sne
/* Apply disturbance - resistive fault at user.faultbus */
/* This is done by adding shunt conductance to the diagonal location
in the Ybus matrix */
line1101">1101: user.alg_flg = PETSC_TR
/* Solve the algebraic equations */
line1104">1104: if (!
line1105">1105: PetscPrintf (PETSC_COMM_SELF ,"\n... (2) Apply disturbance, solve algebraic equations ... \n"
line1106">1106:
line1107">1107: SNESSolve (snes_alg,N
/* Disturbance period */
line1110">1110: TSSetTime (ts,user.tfa
line1111">1111: TSSetMaxTime (ts,user.tfau
line1112">1112: TSSetExactFinalTime (ts,TS_EXACTFINALTIME_STEPOVE
line1113">1113: TSSetIFunction (ts,NULL,(TSIFunction) FormIFunction,&
line1115">1115: user.alg_flg = PETSC_TR
line1116">1116: if (!
line1117">1117: PetscPrintf (PETSC_COMM_SELF ,"\n... (3) Disturbance period ... \n"
line1118">1118:
line1119">1119: TSSolve
/* Remove the fault */
line1122">1122: SNESSetFunction (snes_alg,F_alg,AlgFunction,&
line1124">1124: user.alg_flg = PETSC_FAL
/* Solve the algebraic equations */
line1126">1126: if (!
line1127">1127: PetscPrintf (PETSC_COMM_SELF ,"\n... (4) Remove fault, solve algebraic equations ... \n"
line1128">1128:
line1129">1129: SNESSolve (snes_alg,N
line1130">1130: SNESDestroy (&sne
/* Post-disturbance period */
line1133">1133: TSSetTime (ts,user.tfau
line1134">1134: TSSetMaxTime (ts,user
line1135">1135: TSSetExactFinalTime (ts,TS_EXACTFINALTIME_STEPOVE
line1136">1136: TSSetIFunction (ts,NULL,(TSIFunction) FormIFunction,&
line1138">1138: user.alg_flg = PETSC_FAL
line1139">1139: if (!
line1140">1140: PetscPrintf (PETSC_COMM_SELF ,"\n... (5) Post-disturbance period ... \n"
line1141">1141:
line1142">1142: TSSolve
line1144">1144: PetscFree (user.ybus
line1145">1145: VecDestroy (&
line1146">1146: VecDestroy (&
line1147">1147: DMDestroy (&netw
line1148">1148: TSDestroy (&a
line1149">1149: PetscFinalize
line1150">1150: return
line1151">1151:
/*TEST
build:
requires: double !complex !define(PETSC_USE_64BIT_INDICES)
test:
args: -ts_monitor -snes_converged_reason -alg_snes_converged_reason
localrunfiles: X.bin Ybus.bin ex9busnetworkops
test:
suffix: 2
nsize: 2
args: -ts_monitor -snes_converged_reason -alg_snes_converged_reason
localrunfiles: X.bin Ybus.bin ex9busnetworkops
TEST*/