1 static char help[] = "Using finite difference for the problem in ex9busopt.c \n\n"; 2 3 /* 4 Use finite difference approximations to solve the same optimization problem as in ex9busopt.c. 5 */ 6 7 #include <petsctao.h> 8 #include <petscts.h> 9 #include <petscdm.h> 10 #include <petscdmda.h> 11 #include <petscdmcomposite.h> 12 13 PetscErrorCode FormFunction(Tao,Vec,PetscReal*,void*); 14 15 #define freq 60 16 #define w_s (2*PETSC_PI*freq) 17 18 /* Sizes and indices */ 19 const PetscInt nbus = 9; /* Number of network buses */ 20 const PetscInt ngen = 3; /* Number of generators */ 21 const PetscInt nload = 3; /* Number of loads */ 22 const PetscInt gbus[3] = {0,1,2}; /* Buses at which generators are incident */ 23 const PetscInt lbus[3] = {4,5,7}; /* Buses at which loads are incident */ 24 25 /* Generator real and reactive powers (found via loadflow) */ 26 PetscScalar PG[3] = { 0.69,1.59,0.69}; 27 /* PetscScalar PG[3] = {0.716786142395021,1.630000000000000,0.850000000000000};*/ 28 const PetscScalar QG[3] = {0.270702180178785,0.066120127797275,-0.108402221791588}; 29 /* Generator constants */ 30 const PetscScalar H[3] = {23.64,6.4,3.01}; /* Inertia constant */ 31 const PetscScalar Rs[3] = {0.0,0.0,0.0}; /* Stator Resistance */ 32 const PetscScalar Xd[3] = {0.146,0.8958,1.3125}; /* d-axis reactance */ 33 const PetscScalar Xdp[3] = {0.0608,0.1198,0.1813}; /* d-axis transient reactance */ 34 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 */ 35 const PetscScalar Xqp[3] = {0.0969,0.1969,0.25}; /* q-axis transient reactance */ 36 const PetscScalar Td0p[3] = {8.96,6.0,5.89}; /* d-axis open circuit time constant */ 37 const PetscScalar Tq0p[3] = {0.31,0.535,0.6}; /* q-axis open circuit time constant */ 38 PetscScalar M[3]; /* M = 2*H/w_s */ 39 PetscScalar D[3]; /* D = 0.1*M */ 40 41 PetscScalar TM[3]; /* Mechanical Torque */ 42 /* Exciter system constants */ 43 const PetscScalar KA[3] = {20.0,20.0,20.0}; /* Voltage regulartor gain constant */ 44 const PetscScalar TA[3] = {0.2,0.2,0.2}; /* Voltage regulator time constant */ 45 const PetscScalar KE[3] = {1.0,1.0,1.0}; /* Exciter gain constant */ 46 const PetscScalar TE[3] = {0.314,0.314,0.314}; /* Exciter time constant */ 47 const PetscScalar KF[3] = {0.063,0.063,0.063}; /* Feedback stabilizer gain constant */ 48 const PetscScalar TF[3] = {0.35,0.35,0.35}; /* Feedback stabilizer time constant */ 49 const PetscScalar k1[3] = {0.0039,0.0039,0.0039}; 50 const PetscScalar k2[3] = {1.555,1.555,1.555}; /* k1 and k2 for calculating the saturation function SE = k1*exp(k2*Efd) */ 51 52 PetscScalar Vref[3]; 53 /* Load constants 54 We use a composite load model that describes the load and reactive powers at each time instant as follows 55 P(t) = \sum\limits_{i=0}^ld_nsegsp \ld_alphap_i*P_D0(\frac{V_m(t)}{V_m0})^\ld_betap_i 56 Q(t) = \sum\limits_{i=0}^ld_nsegsq \ld_alphaq_i*Q_D0(\frac{V_m(t)}{V_m0})^\ld_betaq_i 57 where 58 ld_nsegsp,ld_nsegsq - Number of individual load models for real and reactive power loads 59 ld_alphap,ld_alphap - Percentage contribution (weights) or loads 60 P_D0 - Real power load 61 Q_D0 - Reactive power load 62 V_m(t) - Voltage magnitude at time t 63 V_m0 - Voltage magnitude at t = 0 64 ld_betap, ld_betaq - exponents describing the load model for real and reactive part 65 66 Note: All loads have the same characteristic currently. 67 */ 68 const PetscScalar PD0[3] = {1.25,0.9,1.0}; 69 const PetscScalar QD0[3] = {0.5,0.3,0.35}; 70 const PetscInt ld_nsegsp[3] = {3,3,3}; 71 const PetscScalar ld_alphap[3] = {1.0,0.0,0.0}; 72 const PetscScalar ld_betap[3] = {2.0,1.0,0.0}; 73 const PetscInt ld_nsegsq[3] = {3,3,3}; 74 const PetscScalar ld_alphaq[3] = {1.0,0.0,0.0}; 75 const PetscScalar ld_betaq[3] = {2.0,1.0,0.0}; 76 77 typedef struct { 78 DM dmgen, dmnet; /* DMs to manage generator and network subsystem */ 79 DM dmpgrid; /* Composite DM to manage the entire power grid */ 80 Mat Ybus; /* Network admittance matrix */ 81 Vec V0; /* Initial voltage vector (Power flow solution) */ 82 PetscReal tfaulton,tfaultoff; /* Fault on and off times */ 83 PetscInt faultbus; /* Fault bus */ 84 PetscScalar Rfault; 85 PetscReal t0,tmax; 86 PetscInt neqs_gen,neqs_net,neqs_pgrid; 87 Mat Sol; /* Matrix to save solution at each time step */ 88 PetscInt stepnum; 89 PetscBool alg_flg; 90 PetscReal t; 91 IS is_diff; /* indices for differential equations */ 92 IS is_alg; /* indices for algebraic equations */ 93 PetscReal freq_u,freq_l; /* upper and lower frequency limit */ 94 PetscInt pow; /* power coefficient used in the cost function */ 95 Vec vec_q; 96 } Userctx; 97 98 99 /* Converts from machine frame (dq) to network (phase a real,imag) reference frame */ 100 PetscErrorCode dq2ri(PetscScalar Fd,PetscScalar Fq,PetscScalar delta,PetscScalar *Fr, PetscScalar *Fi) 101 { 102 PetscFunctionBegin; 103 *Fr = Fd*PetscSinScalar(delta) + Fq*PetscCosScalar(delta); 104 *Fi = -Fd*PetscCosScalar(delta) + Fq*PetscSinScalar(delta); 105 PetscFunctionReturn(0); 106 } 107 108 /* Converts from network frame ([phase a real,imag) to machine (dq) reference frame */ 109 PetscErrorCode ri2dq(PetscScalar Fr,PetscScalar Fi,PetscScalar delta,PetscScalar *Fd, PetscScalar *Fq) 110 { 111 PetscFunctionBegin; 112 *Fd = Fr*PetscSinScalar(delta) - Fi*PetscCosScalar(delta); 113 *Fq = Fr*PetscCosScalar(delta) + Fi*PetscSinScalar(delta); 114 PetscFunctionReturn(0); 115 } 116 117 PetscErrorCode SetInitialGuess(Vec X,Userctx *user) 118 { 119 PetscErrorCode ierr; 120 Vec Xgen,Xnet; 121 PetscScalar *xgen,*xnet; 122 PetscInt i,idx=0; 123 PetscScalar Vr,Vi,IGr,IGi,Vm,Vm2; 124 PetscScalar Eqp,Edp,delta; 125 PetscScalar Efd,RF,VR; /* Exciter variables */ 126 PetscScalar Id,Iq; /* Generator dq axis currents */ 127 PetscScalar theta,Vd,Vq,SE; 128 129 PetscFunctionBegin; 130 M[0] = 2*H[0]/w_s; M[1] = 2*H[1]/w_s; M[2] = 2*H[2]/w_s; 131 D[0] = 0.1*M[0]; D[1] = 0.1*M[1]; D[2] = 0.1*M[2]; 132 133 ierr = DMCompositeGetLocalVectors(user->dmpgrid,&Xgen,&Xnet);CHKERRQ(ierr); 134 135 /* Network subsystem initialization */ 136 ierr = VecCopy(user->V0,Xnet);CHKERRQ(ierr); 137 138 /* Generator subsystem initialization */ 139 ierr = VecGetArray(Xgen,&xgen);CHKERRQ(ierr); 140 ierr = VecGetArray(Xnet,&xnet);CHKERRQ(ierr); 141 142 for (i=0; i < ngen; i++) { 143 Vr = xnet[2*gbus[i]]; /* Real part of generator terminal voltage */ 144 Vi = xnet[2*gbus[i]+1]; /* Imaginary part of the generator terminal voltage */ 145 Vm = PetscSqrtScalar(Vr*Vr + Vi*Vi); Vm2 = Vm*Vm; 146 IGr = (Vr*PG[i] + Vi*QG[i])/Vm2; 147 IGi = (Vi*PG[i] - Vr*QG[i])/Vm2; 148 149 delta = PetscAtan2Real(Vi+Xq[i]*IGr,Vr-Xq[i]*IGi); /* Machine angle */ 150 151 theta = PETSC_PI/2.0 - delta; 152 153 Id = IGr*PetscCosScalar(theta) - IGi*PetscSinScalar(theta); /* d-axis stator current */ 154 Iq = IGr*PetscSinScalar(theta) + IGi*PetscCosScalar(theta); /* q-axis stator current */ 155 156 Vd = Vr*PetscCosScalar(theta) - Vi*PetscSinScalar(theta); 157 Vq = Vr*PetscSinScalar(theta) + Vi*PetscCosScalar(theta); 158 159 Edp = Vd + Rs[i]*Id - Xqp[i]*Iq; /* d-axis transient EMF */ 160 Eqp = Vq + Rs[i]*Iq + Xdp[i]*Id; /* q-axis transient EMF */ 161 162 TM[i] = PG[i]; 163 164 /* The generator variables are ordered as [Eqp,Edp,delta,w,Id,Iq] */ 165 xgen[idx] = Eqp; 166 xgen[idx+1] = Edp; 167 xgen[idx+2] = delta; 168 xgen[idx+3] = w_s; 169 170 idx = idx + 4; 171 172 xgen[idx] = Id; 173 xgen[idx+1] = Iq; 174 175 idx = idx + 2; 176 177 /* Exciter */ 178 Efd = Eqp + (Xd[i] - Xdp[i])*Id; 179 SE = k1[i]*PetscExpScalar(k2[i]*Efd); 180 VR = KE[i]*Efd + SE; 181 RF = KF[i]*Efd/TF[i]; 182 183 xgen[idx] = Efd; 184 xgen[idx+1] = RF; 185 xgen[idx+2] = VR; 186 187 Vref[i] = Vm + (VR/KA[i]); 188 189 idx = idx + 3; 190 } 191 192 ierr = VecRestoreArray(Xgen,&xgen);CHKERRQ(ierr); 193 ierr = VecRestoreArray(Xnet,&xnet);CHKERRQ(ierr); 194 195 /* ierr = VecView(Xgen,0);CHKERRQ(ierr); */ 196 ierr = DMCompositeGather(user->dmpgrid,INSERT_VALUES,X,Xgen,Xnet);CHKERRQ(ierr); 197 ierr = DMCompositeRestoreLocalVectors(user->dmpgrid,&Xgen,&Xnet);CHKERRQ(ierr); 198 PetscFunctionReturn(0); 199 } 200 201 /* Computes F = [-f(x,y);g(x,y)] */ 202 PetscErrorCode ResidualFunction(SNES snes,Vec X, Vec F, Userctx *user) 203 { 204 PetscErrorCode ierr; 205 Vec Xgen,Xnet,Fgen,Fnet; 206 PetscScalar *xgen,*xnet,*fgen,*fnet; 207 PetscInt i,idx=0; 208 PetscScalar Vr,Vi,Vm,Vm2; 209 PetscScalar Eqp,Edp,delta,w; /* Generator variables */ 210 PetscScalar Efd,RF,VR; /* Exciter variables */ 211 PetscScalar Id,Iq; /* Generator dq axis currents */ 212 PetscScalar Vd,Vq,SE; 213 PetscScalar IGr,IGi,IDr,IDi; 214 PetscScalar Zdq_inv[4],det; 215 PetscScalar PD,QD,Vm0,*v0; 216 PetscInt k; 217 218 PetscFunctionBegin; 219 ierr = VecZeroEntries(F);CHKERRQ(ierr); 220 ierr = DMCompositeGetLocalVectors(user->dmpgrid,&Xgen,&Xnet);CHKERRQ(ierr); 221 ierr = DMCompositeGetLocalVectors(user->dmpgrid,&Fgen,&Fnet);CHKERRQ(ierr); 222 ierr = DMCompositeScatter(user->dmpgrid,X,Xgen,Xnet);CHKERRQ(ierr); 223 ierr = DMCompositeScatter(user->dmpgrid,F,Fgen,Fnet);CHKERRQ(ierr); 224 225 /* Network current balance residual IG + Y*V + IL = 0. Only YV is added here. 226 The generator current injection, IG, and load current injection, ID are added later 227 */ 228 /* Note that the values in Ybus are stored assuming the imaginary current balance 229 equation is ordered first followed by real current balance equation for each bus. 230 Thus imaginary current contribution goes in location 2*i, and 231 real current contribution in 2*i+1 232 */ 233 ierr = MatMult(user->Ybus,Xnet,Fnet);CHKERRQ(ierr); 234 235 ierr = VecGetArray(Xgen,&xgen);CHKERRQ(ierr); 236 ierr = VecGetArray(Xnet,&xnet);CHKERRQ(ierr); 237 ierr = VecGetArray(Fgen,&fgen);CHKERRQ(ierr); 238 ierr = VecGetArray(Fnet,&fnet);CHKERRQ(ierr); 239 240 /* Generator subsystem */ 241 for (i=0; i < ngen; i++) { 242 Eqp = xgen[idx]; 243 Edp = xgen[idx+1]; 244 delta = xgen[idx+2]; 245 w = xgen[idx+3]; 246 Id = xgen[idx+4]; 247 Iq = xgen[idx+5]; 248 Efd = xgen[idx+6]; 249 RF = xgen[idx+7]; 250 VR = xgen[idx+8]; 251 252 /* Generator differential equations */ 253 fgen[idx] = (Eqp + (Xd[i] - Xdp[i])*Id - Efd)/Td0p[i]; 254 fgen[idx+1] = (Edp - (Xq[i] - Xqp[i])*Iq)/Tq0p[i]; 255 fgen[idx+2] = -w + w_s; 256 fgen[idx+3] = (-TM[i] + Edp*Id + Eqp*Iq + (Xqp[i] - Xdp[i])*Id*Iq + D[i]*(w - w_s))/M[i]; 257 258 Vr = xnet[2*gbus[i]]; /* Real part of generator terminal voltage */ 259 Vi = xnet[2*gbus[i]+1]; /* Imaginary part of the generator terminal voltage */ 260 261 ierr = ri2dq(Vr,Vi,delta,&Vd,&Vq);CHKERRQ(ierr); 262 /* Algebraic equations for stator currents */ 263 det = Rs[i]*Rs[i] + Xdp[i]*Xqp[i]; 264 265 Zdq_inv[0] = Rs[i]/det; 266 Zdq_inv[1] = Xqp[i]/det; 267 Zdq_inv[2] = -Xdp[i]/det; 268 Zdq_inv[3] = Rs[i]/det; 269 270 fgen[idx+4] = Zdq_inv[0]*(-Edp + Vd) + Zdq_inv[1]*(-Eqp + Vq) + Id; 271 fgen[idx+5] = Zdq_inv[2]*(-Edp + Vd) + Zdq_inv[3]*(-Eqp + Vq) + Iq; 272 273 /* Add generator current injection to network */ 274 ierr = dq2ri(Id,Iq,delta,&IGr,&IGi);CHKERRQ(ierr); 275 276 fnet[2*gbus[i]] -= IGi; 277 fnet[2*gbus[i]+1] -= IGr; 278 279 Vm = PetscSqrtScalar(Vd*Vd + Vq*Vq); 280 281 SE = k1[i]*PetscExpScalar(k2[i]*Efd); 282 283 /* Exciter differential equations */ 284 fgen[idx+6] = (KE[i]*Efd + SE - VR)/TE[i]; 285 fgen[idx+7] = (RF - KF[i]*Efd/TF[i])/TF[i]; 286 fgen[idx+8] = (VR - KA[i]*RF + KA[i]*KF[i]*Efd/TF[i] - KA[i]*(Vref[i] - Vm))/TA[i]; 287 288 idx = idx + 9; 289 } 290 291 ierr = VecGetArray(user->V0,&v0);CHKERRQ(ierr); 292 for (i=0; i < nload; i++) { 293 Vr = xnet[2*lbus[i]]; /* Real part of load bus voltage */ 294 Vi = xnet[2*lbus[i]+1]; /* Imaginary part of the load bus voltage */ 295 Vm = PetscSqrtScalar(Vr*Vr + Vi*Vi); Vm2 = Vm*Vm; 296 Vm0 = PetscSqrtScalar(v0[2*lbus[i]]*v0[2*lbus[i]] + v0[2*lbus[i]+1]*v0[2*lbus[i]+1]); 297 PD = QD = 0.0; 298 for (k=0; k < ld_nsegsp[i]; k++) PD += ld_alphap[k]*PD0[i]*PetscPowScalar((Vm/Vm0),ld_betap[k]); 299 for (k=0; k < ld_nsegsq[i]; k++) QD += ld_alphaq[k]*QD0[i]*PetscPowScalar((Vm/Vm0),ld_betaq[k]); 300 301 /* Load currents */ 302 IDr = (PD*Vr + QD*Vi)/Vm2; 303 IDi = (-QD*Vr + PD*Vi)/Vm2; 304 305 fnet[2*lbus[i]] += IDi; 306 fnet[2*lbus[i]+1] += IDr; 307 } 308 ierr = VecRestoreArray(user->V0,&v0);CHKERRQ(ierr); 309 310 ierr = VecRestoreArray(Xgen,&xgen);CHKERRQ(ierr); 311 ierr = VecRestoreArray(Xnet,&xnet);CHKERRQ(ierr); 312 ierr = VecRestoreArray(Fgen,&fgen);CHKERRQ(ierr); 313 ierr = VecRestoreArray(Fnet,&fnet);CHKERRQ(ierr); 314 315 ierr = DMCompositeGather(user->dmpgrid,INSERT_VALUES,F,Fgen,Fnet);CHKERRQ(ierr); 316 ierr = DMCompositeRestoreLocalVectors(user->dmpgrid,&Xgen,&Xnet);CHKERRQ(ierr); 317 ierr = DMCompositeRestoreLocalVectors(user->dmpgrid,&Fgen,&Fnet);CHKERRQ(ierr); 318 PetscFunctionReturn(0); 319 } 320 321 /* \dot{x} - f(x,y) 322 g(x,y) = 0 323 */ 324 PetscErrorCode IFunction(TS ts,PetscReal t, Vec X, Vec Xdot, Vec F, Userctx *user) 325 { 326 PetscErrorCode ierr; 327 SNES snes; 328 PetscScalar *f; 329 const PetscScalar *xdot; 330 PetscInt i; 331 332 PetscFunctionBegin; 333 user->t = t; 334 335 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 336 ierr = ResidualFunction(snes,X,F,user);CHKERRQ(ierr); 337 ierr = VecGetArray(F,&f);CHKERRQ(ierr); 338 ierr = VecGetArrayRead(Xdot,&xdot);CHKERRQ(ierr); 339 for (i=0;i < ngen;i++) { 340 f[9*i] += xdot[9*i]; 341 f[9*i+1] += xdot[9*i+1]; 342 f[9*i+2] += xdot[9*i+2]; 343 f[9*i+3] += xdot[9*i+3]; 344 f[9*i+6] += xdot[9*i+6]; 345 f[9*i+7] += xdot[9*i+7]; 346 f[9*i+8] += xdot[9*i+8]; 347 } 348 ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 349 ierr = VecRestoreArrayRead(Xdot,&xdot);CHKERRQ(ierr); 350 PetscFunctionReturn(0); 351 } 352 353 /* This function is used for solving the algebraic system only during fault on and 354 off times. It computes the entire F and then zeros out the part corresponding to 355 differential equations 356 F = [0;g(y)]; 357 */ 358 PetscErrorCode AlgFunction(SNES snes, Vec X, Vec F, void *ctx) 359 { 360 PetscErrorCode ierr; 361 Userctx *user=(Userctx*)ctx; 362 PetscScalar *f; 363 PetscInt i; 364 365 PetscFunctionBegin; 366 ierr = ResidualFunction(snes,X,F,user);CHKERRQ(ierr); 367 ierr = VecGetArray(F,&f);CHKERRQ(ierr); 368 for (i=0; i < ngen; i++) { 369 f[9*i] = 0; 370 f[9*i+1] = 0; 371 f[9*i+2] = 0; 372 f[9*i+3] = 0; 373 f[9*i+6] = 0; 374 f[9*i+7] = 0; 375 f[9*i+8] = 0; 376 } 377 ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 378 PetscFunctionReturn(0); 379 } 380 381 PetscErrorCode PreallocateJacobian(Mat J, Userctx *user) 382 { 383 PetscErrorCode ierr; 384 PetscInt *d_nnz; 385 PetscInt i,idx=0,start=0; 386 PetscInt ncols; 387 388 PetscFunctionBegin; 389 ierr = PetscMalloc1(user->neqs_pgrid,&d_nnz);CHKERRQ(ierr); 390 for (i=0; i<user->neqs_pgrid; i++) d_nnz[i] = 0; 391 /* Generator subsystem */ 392 for (i=0; i < ngen; i++) { 393 394 d_nnz[idx] += 3; 395 d_nnz[idx+1] += 2; 396 d_nnz[idx+2] += 2; 397 d_nnz[idx+3] += 5; 398 d_nnz[idx+4] += 6; 399 d_nnz[idx+5] += 6; 400 401 d_nnz[user->neqs_gen+2*gbus[i]] += 3; 402 d_nnz[user->neqs_gen+2*gbus[i]+1] += 3; 403 404 d_nnz[idx+6] += 2; 405 d_nnz[idx+7] += 2; 406 d_nnz[idx+8] += 5; 407 408 idx = idx + 9; 409 } 410 411 start = user->neqs_gen; 412 413 for (i=0; i < nbus; i++) { 414 ierr = MatGetRow(user->Ybus,2*i,&ncols,NULL,NULL);CHKERRQ(ierr); 415 d_nnz[start+2*i] += ncols; 416 d_nnz[start+2*i+1] += ncols; 417 ierr = MatRestoreRow(user->Ybus,2*i,&ncols,NULL,NULL);CHKERRQ(ierr); 418 } 419 420 ierr = MatSeqAIJSetPreallocation(J,0,d_nnz);CHKERRQ(ierr); 421 422 ierr = PetscFree(d_nnz);CHKERRQ(ierr); 423 PetscFunctionReturn(0); 424 } 425 426 /* 427 J = [-df_dx, -df_dy 428 dg_dx, dg_dy] 429 */ 430 PetscErrorCode ResidualJacobian(SNES snes,Vec X,Mat J,Mat B,void *ctx) 431 { 432 PetscErrorCode ierr; 433 Userctx *user=(Userctx*)ctx; 434 Vec Xgen,Xnet; 435 PetscScalar *xgen,*xnet; 436 PetscInt i,idx=0; 437 PetscScalar Vr,Vi,Vm,Vm2; 438 PetscScalar Eqp,Edp,delta; /* Generator variables */ 439 PetscScalar Efd; /* Exciter variables */ 440 PetscScalar Id,Iq; /* Generator dq axis currents */ 441 PetscScalar Vd,Vq; 442 PetscScalar val[10]; 443 PetscInt row[2],col[10]; 444 PetscInt net_start=user->neqs_gen; 445 PetscScalar Zdq_inv[4],det; 446 PetscScalar dVd_dVr,dVd_dVi,dVq_dVr,dVq_dVi,dVd_ddelta,dVq_ddelta; 447 PetscScalar dIGr_ddelta,dIGi_ddelta,dIGr_dId,dIGr_dIq,dIGi_dId,dIGi_dIq; 448 PetscScalar dSE_dEfd; 449 PetscScalar dVm_dVd,dVm_dVq,dVm_dVr,dVm_dVi; 450 PetscInt ncols; 451 const PetscInt *cols; 452 const PetscScalar *yvals; 453 PetscInt k; 454 PetscScalar PD,QD,Vm0,*v0,Vm4; 455 PetscScalar dPD_dVr,dPD_dVi,dQD_dVr,dQD_dVi; 456 PetscScalar dIDr_dVr,dIDr_dVi,dIDi_dVr,dIDi_dVi; 457 458 PetscFunctionBegin; 459 ierr = MatZeroEntries(B);CHKERRQ(ierr); 460 ierr = DMCompositeGetLocalVectors(user->dmpgrid,&Xgen,&Xnet);CHKERRQ(ierr); 461 ierr = DMCompositeScatter(user->dmpgrid,X,Xgen,Xnet);CHKERRQ(ierr); 462 463 ierr = VecGetArray(Xgen,&xgen);CHKERRQ(ierr); 464 ierr = VecGetArray(Xnet,&xnet);CHKERRQ(ierr); 465 466 /* Generator subsystem */ 467 for (i=0; i < ngen; i++) { 468 Eqp = xgen[idx]; 469 Edp = xgen[idx+1]; 470 delta = xgen[idx+2]; 471 Id = xgen[idx+4]; 472 Iq = xgen[idx+5]; 473 Efd = xgen[idx+6]; 474 475 /* fgen[idx] = (Eqp + (Xd[i] - Xdp[i])*Id - Efd)/Td0p[i]; */ 476 row[0] = idx; 477 col[0] = idx; col[1] = idx+4; col[2] = idx+6; 478 val[0] = 1/ Td0p[i]; val[1] = (Xd[i] - Xdp[i])/ Td0p[i]; val[2] = -1/Td0p[i]; 479 480 ierr = MatSetValues(J,1,row,3,col,val,INSERT_VALUES);CHKERRQ(ierr); 481 482 /* fgen[idx+1] = (Edp - (Xq[i] - Xqp[i])*Iq)/Tq0p[i]; */ 483 row[0] = idx + 1; 484 col[0] = idx + 1; col[1] = idx+5; 485 val[0] = 1/Tq0p[i]; val[1] = -(Xq[i] - Xqp[i])/Tq0p[i]; 486 ierr = MatSetValues(J,1,row,2,col,val,INSERT_VALUES);CHKERRQ(ierr); 487 488 /* fgen[idx+2] = - w + w_s; */ 489 row[0] = idx + 2; 490 col[0] = idx + 2; col[1] = idx + 3; 491 val[0] = 0; val[1] = -1; 492 ierr = MatSetValues(J,1,row,2,col,val,INSERT_VALUES);CHKERRQ(ierr); 493 494 /* fgen[idx+3] = (-TM[i] + Edp*Id + Eqp*Iq + (Xqp[i] - Xdp[i])*Id*Iq + D[i]*(w - w_s))/M[i]; */ 495 row[0] = idx + 3; 496 col[0] = idx; col[1] = idx + 1; col[2] = idx + 3; col[3] = idx + 4; col[4] = idx + 5; 497 val[0] = Iq/M[i]; val[1] = Id/M[i]; val[2] = D[i]/M[i]; val[3] = (Edp + (Xqp[i]-Xdp[i])*Iq)/M[i]; val[4] = (Eqp + (Xqp[i] - Xdp[i])*Id)/M[i]; 498 ierr = MatSetValues(J,1,row,5,col,val,INSERT_VALUES);CHKERRQ(ierr); 499 500 Vr = xnet[2*gbus[i]]; /* Real part of generator terminal voltage */ 501 Vi = xnet[2*gbus[i]+1]; /* Imaginary part of the generator terminal voltage */ 502 ierr = ri2dq(Vr,Vi,delta,&Vd,&Vq);CHKERRQ(ierr); 503 504 det = Rs[i]*Rs[i] + Xdp[i]*Xqp[i]; 505 506 Zdq_inv[0] = Rs[i]/det; 507 Zdq_inv[1] = Xqp[i]/det; 508 Zdq_inv[2] = -Xdp[i]/det; 509 Zdq_inv[3] = Rs[i]/det; 510 511 dVd_dVr = PetscSinScalar(delta); dVd_dVi = -PetscCosScalar(delta); 512 dVq_dVr = PetscCosScalar(delta); dVq_dVi = PetscSinScalar(delta); 513 dVd_ddelta = Vr*PetscCosScalar(delta) + Vi*PetscSinScalar(delta); 514 dVq_ddelta = -Vr*PetscSinScalar(delta) + Vi*PetscCosScalar(delta); 515 516 /* fgen[idx+4] = Zdq_inv[0]*(-Edp + Vd) + Zdq_inv[1]*(-Eqp + Vq) + Id; */ 517 row[0] = idx+4; 518 col[0] = idx; col[1] = idx+1; col[2] = idx + 2; 519 val[0] = -Zdq_inv[1]; val[1] = -Zdq_inv[0]; val[2] = Zdq_inv[0]*dVd_ddelta + Zdq_inv[1]*dVq_ddelta; 520 col[3] = idx + 4; col[4] = net_start+2*gbus[i]; col[5] = net_start + 2*gbus[i]+1; 521 val[3] = 1; val[4] = Zdq_inv[0]*dVd_dVr + Zdq_inv[1]*dVq_dVr; val[5] = Zdq_inv[0]*dVd_dVi + Zdq_inv[1]*dVq_dVi; 522 ierr = MatSetValues(J,1,row,6,col,val,INSERT_VALUES);CHKERRQ(ierr); 523 524 /* fgen[idx+5] = Zdq_inv[2]*(-Edp + Vd) + Zdq_inv[3]*(-Eqp + Vq) + Iq; */ 525 row[0] = idx+5; 526 col[0] = idx; col[1] = idx+1; col[2] = idx + 2; 527 val[0] = -Zdq_inv[3]; val[1] = -Zdq_inv[2]; val[2] = Zdq_inv[2]*dVd_ddelta + Zdq_inv[3]*dVq_ddelta; 528 col[3] = idx + 5; col[4] = net_start+2*gbus[i]; col[5] = net_start + 2*gbus[i]+1; 529 val[3] = 1; val[4] = Zdq_inv[2]*dVd_dVr + Zdq_inv[3]*dVq_dVr; val[5] = Zdq_inv[2]*dVd_dVi + Zdq_inv[3]*dVq_dVi; 530 ierr = MatSetValues(J,1,row,6,col,val,INSERT_VALUES);CHKERRQ(ierr); 531 532 dIGr_ddelta = Id*PetscCosScalar(delta) - Iq*PetscSinScalar(delta); 533 dIGi_ddelta = Id*PetscSinScalar(delta) + Iq*PetscCosScalar(delta); 534 dIGr_dId = PetscSinScalar(delta); dIGr_dIq = PetscCosScalar(delta); 535 dIGi_dId = -PetscCosScalar(delta); dIGi_dIq = PetscSinScalar(delta); 536 537 /* fnet[2*gbus[i]] -= IGi; */ 538 row[0] = net_start + 2*gbus[i]; 539 col[0] = idx+2; col[1] = idx + 4; col[2] = idx + 5; 540 val[0] = -dIGi_ddelta; val[1] = -dIGi_dId; val[2] = -dIGi_dIq; 541 ierr = MatSetValues(J,1,row,3,col,val,INSERT_VALUES);CHKERRQ(ierr); 542 543 /* fnet[2*gbus[i]+1] -= IGr; */ 544 row[0] = net_start + 2*gbus[i]+1; 545 col[0] = idx+2; col[1] = idx + 4; col[2] = idx + 5; 546 val[0] = -dIGr_ddelta; val[1] = -dIGr_dId; val[2] = -dIGr_dIq; 547 ierr = MatSetValues(J,1,row,3,col,val,INSERT_VALUES);CHKERRQ(ierr); 548 549 Vm = PetscSqrtScalar(Vd*Vd + Vq*Vq); 550 551 /* fgen[idx+6] = (KE[i]*Efd + SE - VR)/TE[i]; */ 552 /* SE = k1[i]*PetscExpScalar(k2[i]*Efd); */ 553 554 dSE_dEfd = k1[i]*k2[i]*PetscExpScalar(k2[i]*Efd); 555 556 row[0] = idx + 6; 557 col[0] = idx + 6; col[1] = idx + 8; 558 val[0] = (KE[i] + dSE_dEfd)/TE[i]; val[1] = -1/TE[i]; 559 ierr = MatSetValues(J,1,row,2,col,val,INSERT_VALUES);CHKERRQ(ierr); 560 561 /* Exciter differential equations */ 562 563 /* fgen[idx+7] = (RF - KF[i]*Efd/TF[i])/TF[i]; */ 564 row[0] = idx + 7; 565 col[0] = idx + 6; col[1] = idx + 7; 566 val[0] = (-KF[i]/TF[i])/TF[i]; val[1] = 1/TF[i]; 567 ierr = MatSetValues(J,1,row,2,col,val,INSERT_VALUES);CHKERRQ(ierr); 568 569 /* fgen[idx+8] = (VR - KA[i]*RF + KA[i]*KF[i]*Efd/TF[i] - KA[i]*(Vref[i] - Vm))/TA[i]; */ 570 /* Vm = (Vd^2 + Vq^2)^0.5; */ 571 dVm_dVd = Vd/Vm; dVm_dVq = Vq/Vm; 572 dVm_dVr = dVm_dVd*dVd_dVr + dVm_dVq*dVq_dVr; 573 dVm_dVi = dVm_dVd*dVd_dVi + dVm_dVq*dVq_dVi; 574 row[0] = idx + 8; 575 col[0] = idx + 6; col[1] = idx + 7; col[2] = idx + 8; 576 val[0] = (KA[i]*KF[i]/TF[i])/TA[i]; val[1] = -KA[i]/TA[i]; val[2] = 1/TA[i]; 577 col[3] = net_start + 2*gbus[i]; col[4] = net_start + 2*gbus[i]+1; 578 val[3] = KA[i]*dVm_dVr/TA[i]; val[4] = KA[i]*dVm_dVi/TA[i]; 579 ierr = MatSetValues(J,1,row,5,col,val,INSERT_VALUES);CHKERRQ(ierr); 580 idx = idx + 9; 581 } 582 583 584 for (i=0; i<nbus; i++) { 585 ierr = MatGetRow(user->Ybus,2*i,&ncols,&cols,&yvals);CHKERRQ(ierr); 586 row[0] = net_start + 2*i; 587 for (k=0; k<ncols; k++) { 588 col[k] = net_start + cols[k]; 589 val[k] = yvals[k]; 590 } 591 ierr = MatSetValues(J,1,row,ncols,col,val,INSERT_VALUES);CHKERRQ(ierr); 592 ierr = MatRestoreRow(user->Ybus,2*i,&ncols,&cols,&yvals);CHKERRQ(ierr); 593 594 ierr = MatGetRow(user->Ybus,2*i+1,&ncols,&cols,&yvals);CHKERRQ(ierr); 595 row[0] = net_start + 2*i+1; 596 for (k=0; k<ncols; k++) { 597 col[k] = net_start + cols[k]; 598 val[k] = yvals[k]; 599 } 600 ierr = MatSetValues(J,1,row,ncols,col,val,INSERT_VALUES);CHKERRQ(ierr); 601 ierr = MatRestoreRow(user->Ybus,2*i+1,&ncols,&cols,&yvals);CHKERRQ(ierr); 602 } 603 604 ierr = MatAssemblyBegin(J,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr); 605 ierr = MatAssemblyEnd(J,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr); 606 607 ierr = VecGetArray(user->V0,&v0);CHKERRQ(ierr); 608 for (i=0; i < nload; i++) { 609 Vr = xnet[2*lbus[i]]; /* Real part of load bus voltage */ 610 Vi = xnet[2*lbus[i]+1]; /* Imaginary part of the load bus voltage */ 611 Vm = PetscSqrtScalar(Vr*Vr + Vi*Vi); Vm2 = Vm*Vm; Vm4 = Vm2*Vm2; 612 Vm0 = PetscSqrtScalar(v0[2*lbus[i]]*v0[2*lbus[i]] + v0[2*lbus[i]+1]*v0[2*lbus[i]+1]); 613 PD = QD = 0.0; 614 dPD_dVr = dPD_dVi = dQD_dVr = dQD_dVi = 0.0; 615 for (k=0; k < ld_nsegsp[i]; k++) { 616 PD += ld_alphap[k]*PD0[i]*PetscPowScalar((Vm/Vm0),ld_betap[k]); 617 dPD_dVr += ld_alphap[k]*ld_betap[k]*PD0[i]*PetscPowScalar((1/Vm0),ld_betap[k])*Vr*PetscPowScalar(Vm,(ld_betap[k]-2)); 618 dPD_dVi += ld_alphap[k]*ld_betap[k]*PD0[i]*PetscPowScalar((1/Vm0),ld_betap[k])*Vi*PetscPowScalar(Vm,(ld_betap[k]-2)); 619 } 620 for (k=0; k < ld_nsegsq[i]; k++) { 621 QD += ld_alphaq[k]*QD0[i]*PetscPowScalar((Vm/Vm0),ld_betaq[k]); 622 dQD_dVr += ld_alphaq[k]*ld_betaq[k]*QD0[i]*PetscPowScalar((1/Vm0),ld_betaq[k])*Vr*PetscPowScalar(Vm,(ld_betaq[k]-2)); 623 dQD_dVi += ld_alphaq[k]*ld_betaq[k]*QD0[i]*PetscPowScalar((1/Vm0),ld_betaq[k])*Vi*PetscPowScalar(Vm,(ld_betaq[k]-2)); 624 } 625 626 /* IDr = (PD*Vr + QD*Vi)/Vm2; */ 627 /* IDi = (-QD*Vr + PD*Vi)/Vm2; */ 628 629 dIDr_dVr = (dPD_dVr*Vr + dQD_dVr*Vi + PD)/Vm2 - ((PD*Vr + QD*Vi)*2*Vr)/Vm4; 630 dIDr_dVi = (dPD_dVi*Vr + dQD_dVi*Vi + QD)/Vm2 - ((PD*Vr + QD*Vi)*2*Vi)/Vm4; 631 632 dIDi_dVr = (-dQD_dVr*Vr + dPD_dVr*Vi - QD)/Vm2 - ((-QD*Vr + PD*Vi)*2*Vr)/Vm4; 633 dIDi_dVi = (-dQD_dVi*Vr + dPD_dVi*Vi + PD)/Vm2 - ((-QD*Vr + PD*Vi)*2*Vi)/Vm4; 634 635 636 /* fnet[2*lbus[i]] += IDi; */ 637 row[0] = net_start + 2*lbus[i]; 638 col[0] = net_start + 2*lbus[i]; col[1] = net_start + 2*lbus[i]+1; 639 val[0] = dIDi_dVr; val[1] = dIDi_dVi; 640 ierr = MatSetValues(J,1,row,2,col,val,ADD_VALUES);CHKERRQ(ierr); 641 /* fnet[2*lbus[i]+1] += IDr; */ 642 row[0] = net_start + 2*lbus[i]+1; 643 col[0] = net_start + 2*lbus[i]; col[1] = net_start + 2*lbus[i]+1; 644 val[0] = dIDr_dVr; val[1] = dIDr_dVi; 645 ierr = MatSetValues(J,1,row,2,col,val,ADD_VALUES);CHKERRQ(ierr); 646 } 647 ierr = VecRestoreArray(user->V0,&v0);CHKERRQ(ierr); 648 649 ierr = VecRestoreArray(Xgen,&xgen);CHKERRQ(ierr); 650 ierr = VecRestoreArray(Xnet,&xnet);CHKERRQ(ierr); 651 652 ierr = DMCompositeRestoreLocalVectors(user->dmpgrid,&Xgen,&Xnet);CHKERRQ(ierr); 653 654 ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 655 ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 656 PetscFunctionReturn(0); 657 } 658 659 /* 660 J = [I, 0 661 dg_dx, dg_dy] 662 */ 663 PetscErrorCode AlgJacobian(SNES snes,Vec X,Mat A,Mat B,void *ctx) 664 { 665 PetscErrorCode ierr; 666 Userctx *user=(Userctx*)ctx; 667 668 PetscFunctionBegin; 669 ierr = ResidualJacobian(snes,X,A,B,ctx);CHKERRQ(ierr); 670 ierr = MatSetOption(A,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr); 671 ierr = MatZeroRowsIS(A,user->is_diff,1.0,NULL,NULL);CHKERRQ(ierr); 672 PetscFunctionReturn(0); 673 } 674 675 /* 676 J = [a*I-df_dx, -df_dy 677 dg_dx, dg_dy] 678 */ 679 680 PetscErrorCode IJacobian(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal a,Mat A,Mat B,Userctx *user) 681 { 682 PetscErrorCode ierr; 683 SNES snes; 684 PetscScalar atmp = (PetscScalar) a; 685 PetscInt i,row; 686 687 PetscFunctionBegin; 688 user->t = t; 689 690 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 691 ierr = ResidualJacobian(snes,X,A,B,user);CHKERRQ(ierr); 692 for (i=0;i < ngen;i++) { 693 row = 9*i; 694 ierr = MatSetValues(A,1,&row,1,&row,&atmp,ADD_VALUES);CHKERRQ(ierr); 695 row = 9*i+1; 696 ierr = MatSetValues(A,1,&row,1,&row,&atmp,ADD_VALUES);CHKERRQ(ierr); 697 row = 9*i+2; 698 ierr = MatSetValues(A,1,&row,1,&row,&atmp,ADD_VALUES);CHKERRQ(ierr); 699 row = 9*i+3; 700 ierr = MatSetValues(A,1,&row,1,&row,&atmp,ADD_VALUES);CHKERRQ(ierr); 701 row = 9*i+6; 702 ierr = MatSetValues(A,1,&row,1,&row,&atmp,ADD_VALUES);CHKERRQ(ierr); 703 row = 9*i+7; 704 ierr = MatSetValues(A,1,&row,1,&row,&atmp,ADD_VALUES);CHKERRQ(ierr); 705 row = 9*i+8; 706 ierr = MatSetValues(A,1,&row,1,&row,&atmp,ADD_VALUES);CHKERRQ(ierr); 707 } 708 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 709 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 710 PetscFunctionReturn(0); 711 } 712 713 static PetscErrorCode CostIntegrand(TS ts,PetscReal t,Vec U,Vec R,Userctx *user) 714 { 715 PetscErrorCode ierr; 716 PetscScalar *r; 717 const PetscScalar *u; 718 PetscInt idx; 719 Vec Xgen,Xnet; 720 PetscScalar *xgen; 721 PetscInt i; 722 723 PetscFunctionBegin; 724 ierr = DMCompositeGetLocalVectors(user->dmpgrid,&Xgen,&Xnet);CHKERRQ(ierr); 725 ierr = DMCompositeScatter(user->dmpgrid,U,Xgen,Xnet);CHKERRQ(ierr); 726 727 ierr = VecGetArray(Xgen,&xgen);CHKERRQ(ierr); 728 729 ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr); 730 ierr = VecGetArray(R,&r);CHKERRQ(ierr); 731 r[0] = 0.; 732 733 idx = 0; 734 for (i=0;i<ngen;i++) { 735 r[0] += PetscPowScalarInt(PetscMax(0.,PetscMax(xgen[idx+3]/(2.*PETSC_PI)-user->freq_u,user->freq_l-xgen[idx+3]/(2.*PETSC_PI))),user->pow); 736 idx += 9; 737 } 738 ierr = VecRestoreArray(R,&r);CHKERRQ(ierr); 739 ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr); 740 ierr = DMCompositeRestoreLocalVectors(user->dmpgrid,&Xgen,&Xnet);CHKERRQ(ierr); 741 PetscFunctionReturn(0); 742 } 743 744 static PetscErrorCode MonitorUpdateQ(TS ts,PetscInt stepnum,PetscReal time,Vec X,void *ctx0) 745 { 746 PetscErrorCode ierr; 747 Vec C,*Y; 748 PetscInt Nr; 749 PetscReal h,theta; 750 Userctx *ctx=(Userctx*)ctx0; 751 752 PetscFunctionBegin; 753 theta = 0.5; 754 ierr = TSGetStages(ts,&Nr,&Y);CHKERRQ(ierr); 755 ierr = TSGetTimeStep(ts,&h);CHKERRQ(ierr); 756 ierr = VecDuplicate(ctx->vec_q,&C);CHKERRQ(ierr); 757 /* compute integrals */ 758 if (stepnum>0) { 759 ierr = CostIntegrand(ts,time,X,C,ctx);CHKERRQ(ierr); 760 ierr = VecAXPY(ctx->vec_q,h*theta,C);CHKERRQ(ierr); 761 ierr = CostIntegrand(ts,time+h*theta,Y[0],C,ctx);CHKERRQ(ierr); 762 ierr = VecAXPY(ctx->vec_q,h*(1-theta),C);CHKERRQ(ierr); 763 } 764 ierr = VecDestroy(&C);CHKERRQ(ierr); 765 PetscFunctionReturn(0); 766 } 767 768 int main(int argc,char **argv) 769 { 770 Userctx user; 771 Vec p; 772 PetscScalar *x_ptr; 773 PetscErrorCode ierr; 774 PetscMPIInt size; 775 PetscInt i; 776 KSP ksp; 777 PC pc; 778 PetscInt *idx2; 779 Tao tao; 780 Vec lowerb,upperb; 781 782 PetscFunctionBeginUser; 783 ierr = PetscInitialize(&argc,&argv,"petscoptions",help);if (ierr) return ierr; 784 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); 785 if (size > 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Only for sequential runs"); 786 787 ierr = VecCreateSeq(PETSC_COMM_WORLD,1,&user.vec_q);CHKERRQ(ierr); 788 789 user.neqs_gen = 9*ngen; /* # eqs. for generator subsystem */ 790 user.neqs_net = 2*nbus; /* # eqs. for network subsystem */ 791 user.neqs_pgrid = user.neqs_gen + user.neqs_net; 792 793 /* Create indices for differential and algebraic equations */ 794 ierr = PetscMalloc1(7*ngen,&idx2);CHKERRQ(ierr); 795 for (i=0; i<ngen; i++) { 796 idx2[7*i] = 9*i; idx2[7*i+1] = 9*i+1; idx2[7*i+2] = 9*i+2; idx2[7*i+3] = 9*i+3; 797 idx2[7*i+4] = 9*i+6; idx2[7*i+5] = 9*i+7; idx2[7*i+6] = 9*i+8; 798 } 799 ierr = ISCreateGeneral(PETSC_COMM_WORLD,7*ngen,idx2,PETSC_COPY_VALUES,&user.is_diff);CHKERRQ(ierr); 800 ierr = ISComplement(user.is_diff,0,user.neqs_pgrid,&user.is_alg);CHKERRQ(ierr); 801 ierr = PetscFree(idx2);CHKERRQ(ierr); 802 803 /* Set run time options */ 804 ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Transient stability fault options","");CHKERRQ(ierr); 805 { 806 user.tfaulton = 1.0; 807 user.tfaultoff = 1.2; 808 user.Rfault = 0.0001; 809 user.faultbus = 8; 810 ierr = PetscOptionsReal("-tfaulton","","",user.tfaulton,&user.tfaulton,NULL);CHKERRQ(ierr); 811 ierr = PetscOptionsReal("-tfaultoff","","",user.tfaultoff,&user.tfaultoff,NULL);CHKERRQ(ierr); 812 ierr = PetscOptionsInt("-faultbus","","",user.faultbus,&user.faultbus,NULL);CHKERRQ(ierr); 813 user.t0 = 0.0; 814 user.tmax = 1.5; 815 ierr = PetscOptionsReal("-t0","","",user.t0,&user.t0,NULL);CHKERRQ(ierr); 816 ierr = PetscOptionsReal("-tmax","","",user.tmax,&user.tmax,NULL);CHKERRQ(ierr); 817 user.freq_u = 61.0; 818 user.freq_l = 59.0; 819 user.pow = 2; 820 ierr = PetscOptionsReal("-frequ","","",user.freq_u,&user.freq_u,NULL);CHKERRQ(ierr); 821 ierr = PetscOptionsReal("-freql","","",user.freq_l,&user.freq_l,NULL);CHKERRQ(ierr); 822 ierr = PetscOptionsInt("-pow","","",user.pow,&user.pow,NULL);CHKERRQ(ierr); 823 824 } 825 ierr = PetscOptionsEnd();CHKERRQ(ierr); 826 827 /* Create DMs for generator and network subsystems */ 828 ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,user.neqs_gen,1,1,NULL,&user.dmgen);CHKERRQ(ierr); 829 ierr = DMSetOptionsPrefix(user.dmgen,"dmgen_");CHKERRQ(ierr); 830 ierr = DMSetFromOptions(user.dmgen);CHKERRQ(ierr); 831 ierr = DMSetUp(user.dmgen);CHKERRQ(ierr); 832 ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,user.neqs_net,1,1,NULL,&user.dmnet);CHKERRQ(ierr); 833 ierr = DMSetOptionsPrefix(user.dmnet,"dmnet_");CHKERRQ(ierr); 834 ierr = DMSetFromOptions(user.dmnet);CHKERRQ(ierr); 835 ierr = DMSetUp(user.dmnet);CHKERRQ(ierr); 836 /* Create a composite DM packer and add the two DMs */ 837 ierr = DMCompositeCreate(PETSC_COMM_WORLD,&user.dmpgrid);CHKERRQ(ierr); 838 ierr = DMSetOptionsPrefix(user.dmpgrid,"pgrid_");CHKERRQ(ierr); 839 ierr = DMCompositeAddDM(user.dmpgrid,user.dmgen);CHKERRQ(ierr); 840 ierr = DMCompositeAddDM(user.dmpgrid,user.dmnet);CHKERRQ(ierr); 841 842 /* Create TAO solver and set desired solution method */ 843 ierr = TaoCreate(PETSC_COMM_WORLD,&tao);CHKERRQ(ierr); 844 ierr = TaoSetType(tao,TAOBLMVM);CHKERRQ(ierr); 845 /* 846 Optimization starts 847 */ 848 /* Set initial solution guess */ 849 ierr = VecCreateSeq(PETSC_COMM_WORLD,3,&p);CHKERRQ(ierr); 850 ierr = VecGetArray(p,&x_ptr);CHKERRQ(ierr); 851 x_ptr[0] = PG[0]; x_ptr[1] = PG[1]; x_ptr[2] = PG[2]; 852 ierr = VecRestoreArray(p,&x_ptr);CHKERRQ(ierr); 853 854 ierr = TaoSetInitialVector(tao,p);CHKERRQ(ierr); 855 /* Set routine for function and gradient evaluation */ 856 ierr = TaoSetObjectiveRoutine(tao,FormFunction,(void *)&user);CHKERRQ(ierr); 857 ierr = TaoSetGradientRoutine(tao,TaoDefaultComputeGradient,(void *)&user);CHKERRQ(ierr); 858 859 /* Set bounds for the optimization */ 860 ierr = VecDuplicate(p,&lowerb);CHKERRQ(ierr); 861 ierr = VecDuplicate(p,&upperb);CHKERRQ(ierr); 862 ierr = VecGetArray(lowerb,&x_ptr);CHKERRQ(ierr); 863 x_ptr[0] = 0.5; x_ptr[1] = 0.5; x_ptr[2] = 0.5; 864 ierr = VecRestoreArray(lowerb,&x_ptr);CHKERRQ(ierr); 865 ierr = VecGetArray(upperb,&x_ptr);CHKERRQ(ierr); 866 x_ptr[0] = 2.0; x_ptr[1] = 2.0; x_ptr[2] = 2.0; 867 ierr = VecRestoreArray(upperb,&x_ptr);CHKERRQ(ierr); 868 ierr = TaoSetVariableBounds(tao,lowerb,upperb);CHKERRQ(ierr); 869 870 /* Check for any TAO command line options */ 871 ierr = TaoSetFromOptions(tao);CHKERRQ(ierr); 872 ierr = TaoGetKSP(tao,&ksp);CHKERRQ(ierr); 873 if (ksp) { 874 ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 875 ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr); 876 } 877 878 /* SOLVE THE APPLICATION */ 879 ierr = TaoSolve(tao); CHKERRQ(ierr); 880 881 ierr = VecView(p,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 882 /* Free TAO data structures */ 883 ierr = TaoDestroy(&tao);CHKERRQ(ierr); 884 ierr = VecDestroy(&user.vec_q);CHKERRQ(ierr); 885 ierr = VecDestroy(&lowerb);CHKERRQ(ierr); 886 ierr = VecDestroy(&upperb);CHKERRQ(ierr); 887 ierr = VecDestroy(&p);CHKERRQ(ierr); 888 ierr = DMDestroy(&user.dmgen);CHKERRQ(ierr); 889 ierr = DMDestroy(&user.dmnet);CHKERRQ(ierr); 890 ierr = DMDestroy(&user.dmpgrid);CHKERRQ(ierr); 891 ierr = ISDestroy(&user.is_diff);CHKERRQ(ierr); 892 ierr = ISDestroy(&user.is_alg);CHKERRQ(ierr); 893 ierr = PetscFinalize(); 894 return ierr; 895 } 896 897 /* ------------------------------------------------------------------ */ 898 /* 899 FormFunction - Evaluates the function and corresponding gradient. 900 901 Input Parameters: 902 tao - the Tao context 903 X - the input vector 904 ptr - optional user-defined context, as set by TaoSetObjectiveAndGradientRoutine() 905 906 Output Parameters: 907 f - the newly evaluated function 908 */ 909 PetscErrorCode FormFunction(Tao tao,Vec P,PetscReal *f,void *ctx0) 910 { 911 TS ts; 912 SNES snes_alg; 913 PetscErrorCode ierr; 914 Userctx *ctx = (Userctx*)ctx0; 915 Vec X; 916 Mat J; 917 /* sensitivity context */ 918 PetscScalar *x_ptr; 919 PetscViewer Xview,Ybusview; 920 Vec F_alg; 921 Vec Xdot; 922 PetscInt row_loc,col_loc; 923 PetscScalar val; 924 925 ierr = VecGetArrayRead(P,(const PetscScalar**)&x_ptr);CHKERRQ(ierr); 926 PG[0] = x_ptr[0]; 927 PG[1] = x_ptr[1]; 928 PG[2] = x_ptr[2]; 929 ierr = VecRestoreArrayRead(P,(const PetscScalar**)&x_ptr);CHKERRQ(ierr); 930 931 ctx->stepnum = 0; 932 933 ierr = VecZeroEntries(ctx->vec_q);CHKERRQ(ierr); 934 935 /* Read initial voltage vector and Ybus */ 936 ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,"X.bin",FILE_MODE_READ,&Xview);CHKERRQ(ierr); 937 ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,"Ybus.bin",FILE_MODE_READ,&Ybusview);CHKERRQ(ierr); 938 939 ierr = VecCreate(PETSC_COMM_WORLD,&ctx->V0);CHKERRQ(ierr); 940 ierr = VecSetSizes(ctx->V0,PETSC_DECIDE,ctx->neqs_net);CHKERRQ(ierr); 941 ierr = VecLoad(ctx->V0,Xview);CHKERRQ(ierr); 942 943 ierr = MatCreate(PETSC_COMM_WORLD,&ctx->Ybus);CHKERRQ(ierr); 944 ierr = MatSetSizes(ctx->Ybus,PETSC_DECIDE,PETSC_DECIDE,ctx->neqs_net,ctx->neqs_net);CHKERRQ(ierr); 945 ierr = MatSetType(ctx->Ybus,MATBAIJ);CHKERRQ(ierr); 946 /* ierr = MatSetBlockSize(ctx->Ybus,2);CHKERRQ(ierr); */ 947 ierr = MatLoad(ctx->Ybus,Ybusview);CHKERRQ(ierr); 948 949 ierr = PetscViewerDestroy(&Xview);CHKERRQ(ierr); 950 ierr = PetscViewerDestroy(&Ybusview);CHKERRQ(ierr); 951 952 ierr = DMCreateGlobalVector(ctx->dmpgrid,&X);CHKERRQ(ierr); 953 954 ierr = MatCreate(PETSC_COMM_WORLD,&J);CHKERRQ(ierr); 955 ierr = MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,ctx->neqs_pgrid,ctx->neqs_pgrid);CHKERRQ(ierr); 956 ierr = MatSetFromOptions(J);CHKERRQ(ierr); 957 ierr = PreallocateJacobian(J,ctx);CHKERRQ(ierr); 958 959 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 960 Create timestepping solver context 961 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 962 ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr); 963 ierr = TSSetProblemType(ts,TS_NONLINEAR);CHKERRQ(ierr); 964 ierr = TSSetType(ts,TSCN);CHKERRQ(ierr); 965 ierr = TSSetIFunction(ts,NULL,(TSIFunction) IFunction,ctx);CHKERRQ(ierr); 966 ierr = TSSetIJacobian(ts,J,J,(TSIJacobian)IJacobian,ctx);CHKERRQ(ierr); 967 ierr = TSSetApplicationContext(ts,ctx);CHKERRQ(ierr); 968 969 ierr = TSMonitorSet(ts,MonitorUpdateQ,ctx,NULL);CHKERRQ(ierr); 970 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 971 Set initial conditions 972 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 973 ierr = SetInitialGuess(X,ctx);CHKERRQ(ierr); 974 975 ierr = VecDuplicate(X,&F_alg);CHKERRQ(ierr); 976 ierr = SNESCreate(PETSC_COMM_WORLD,&snes_alg);CHKERRQ(ierr); 977 ierr = SNESSetFunction(snes_alg,F_alg,AlgFunction,ctx);CHKERRQ(ierr); 978 ierr = MatZeroEntries(J);CHKERRQ(ierr); 979 ierr = SNESSetJacobian(snes_alg,J,J,AlgJacobian,ctx);CHKERRQ(ierr); 980 ierr = SNESSetOptionsPrefix(snes_alg,"alg_");CHKERRQ(ierr); 981 ierr = SNESSetFromOptions(snes_alg);CHKERRQ(ierr); 982 ctx->alg_flg = PETSC_TRUE; 983 /* Solve the algebraic equations */ 984 ierr = SNESSolve(snes_alg,NULL,X);CHKERRQ(ierr); 985 986 /* Just to set up the Jacobian structure */ 987 ierr = VecDuplicate(X,&Xdot);CHKERRQ(ierr); 988 ierr = IJacobian(ts,0.0,X,Xdot,0.0,J,J,ctx);CHKERRQ(ierr); 989 ierr = VecDestroy(&Xdot);CHKERRQ(ierr); 990 991 ctx->stepnum++; 992 993 ierr = TSSetTimeStep(ts,0.01);CHKERRQ(ierr); 994 ierr = TSSetMaxTime(ts,ctx->tmax);CHKERRQ(ierr); 995 ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP);CHKERRQ(ierr); 996 ierr = TSSetFromOptions(ts);CHKERRQ(ierr); 997 998 /* Prefault period */ 999 ctx->alg_flg = PETSC_FALSE; 1000 ierr = TSSetTime(ts,0.0);CHKERRQ(ierr); 1001 ierr = TSSetMaxTime(ts,ctx->tfaulton);CHKERRQ(ierr); 1002 ierr = TSSolve(ts,X);CHKERRQ(ierr); 1003 1004 /* Create the nonlinear solver for solving the algebraic system */ 1005 /* Note that although the algebraic system needs to be solved only for 1006 Idq and V, we reuse the entire system including xgen. The xgen 1007 variables are held constant by setting their residuals to 0 and 1008 putting a 1 on the Jacobian diagonal for xgen rows 1009 */ 1010 ierr = MatZeroEntries(J);CHKERRQ(ierr); 1011 1012 /* Apply disturbance - resistive fault at ctx->faultbus */ 1013 /* This is done by adding shunt conductance to the diagonal location 1014 in the Ybus matrix */ 1015 row_loc = 2*ctx->faultbus; col_loc = 2*ctx->faultbus+1; /* Location for G */ 1016 val = 1/ctx->Rfault; 1017 ierr = MatSetValues(ctx->Ybus,1,&row_loc,1,&col_loc,&val,ADD_VALUES);CHKERRQ(ierr); 1018 row_loc = 2*ctx->faultbus+1; col_loc = 2*ctx->faultbus; /* Location for G */ 1019 val = 1/ctx->Rfault; 1020 ierr = MatSetValues(ctx->Ybus,1,&row_loc,1,&col_loc,&val,ADD_VALUES);CHKERRQ(ierr); 1021 1022 ierr = MatAssemblyBegin(ctx->Ybus,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1023 ierr = MatAssemblyEnd(ctx->Ybus,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1024 1025 ctx->alg_flg = PETSC_TRUE; 1026 /* Solve the algebraic equations */ 1027 ierr = SNESSolve(snes_alg,NULL,X);CHKERRQ(ierr); 1028 1029 ctx->stepnum++; 1030 1031 /* Disturbance period */ 1032 ctx->alg_flg = PETSC_FALSE; 1033 ierr = TSSetTime(ts,ctx->tfaulton);CHKERRQ(ierr); 1034 ierr = TSSetMaxTime(ts,ctx->tfaultoff);CHKERRQ(ierr); 1035 ierr = TSSolve(ts,X);CHKERRQ(ierr); 1036 1037 /* Remove the fault */ 1038 row_loc = 2*ctx->faultbus; col_loc = 2*ctx->faultbus+1; 1039 val = -1/ctx->Rfault; 1040 ierr = MatSetValues(ctx->Ybus,1,&row_loc,1,&col_loc,&val,ADD_VALUES);CHKERRQ(ierr); 1041 row_loc = 2*ctx->faultbus+1; col_loc = 2*ctx->faultbus; 1042 val = -1/ctx->Rfault; 1043 ierr = MatSetValues(ctx->Ybus,1,&row_loc,1,&col_loc,&val,ADD_VALUES);CHKERRQ(ierr); 1044 1045 ierr = MatAssemblyBegin(ctx->Ybus,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1046 ierr = MatAssemblyEnd(ctx->Ybus,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1047 1048 ierr = MatZeroEntries(J);CHKERRQ(ierr); 1049 1050 ctx->alg_flg = PETSC_TRUE; 1051 1052 /* Solve the algebraic equations */ 1053 ierr = SNESSolve(snes_alg,NULL,X);CHKERRQ(ierr); 1054 1055 ctx->stepnum++; 1056 1057 /* Post-disturbance period */ 1058 ctx->alg_flg = PETSC_TRUE; 1059 ierr = TSSetTime(ts,ctx->tfaultoff);CHKERRQ(ierr); 1060 ierr = TSSetMaxTime(ts,ctx->tmax);CHKERRQ(ierr); 1061 ierr = TSSolve(ts,X);CHKERRQ(ierr); 1062 1063 ierr = VecGetArray(ctx->vec_q,&x_ptr);CHKERRQ(ierr); 1064 *f = x_ptr[0]; 1065 ierr = VecRestoreArray(ctx->vec_q,&x_ptr);CHKERRQ(ierr); 1066 1067 ierr = MatDestroy(&ctx->Ybus);CHKERRQ(ierr); 1068 ierr = VecDestroy(&ctx->V0);CHKERRQ(ierr); 1069 ierr = SNESDestroy(&snes_alg);CHKERRQ(ierr); 1070 ierr = VecDestroy(&F_alg);CHKERRQ(ierr); 1071 ierr = MatDestroy(&J);CHKERRQ(ierr); 1072 ierr = VecDestroy(&X);CHKERRQ(ierr); 1073 ierr = TSDestroy(&ts);CHKERRQ(ierr); 1074 1075 return 0; 1076 } 1077 1078 /*TEST 1079 1080 build: 1081 requires: double !complex !define(USE_64BIT_INDICES) 1082 1083 test: 1084 args: -viewer_binary_skip_info -tao_monitor -tao_gttol .2 1085 localrunfiles: petscoptions X.bin Ybus.bin 1086 1087 TEST*/ 1088