xref: /petsc/src/snes/tutorials/network/power/power.c (revision 9566063d113dddea24716c546802770db7481bc0)
1c4762a1bSJed Brown static char help[] = "This example demonstrates the use of DMNetwork interface for solving a nonlinear electric power grid problem.\n\
2c4762a1bSJed Brown                       The available solver options are in the poweroptions file and the data files are in the datafiles directory.\n\
3c4762a1bSJed Brown                       See 'Evaluation of overlapping restricted additive schwarz preconditioning for parallel solution \n\
4c4762a1bSJed Brown                           of very large power flow problems' https://dl.acm.org/citation.cfm?id=2536784).\n\
5c4762a1bSJed Brown                       The data file format used is from the MatPower package (http://www.pserc.cornell.edu//matpower/).\n\
6c4762a1bSJed Brown                       Run this program: mpiexec -n <n> ./pf\n\
7c4762a1bSJed Brown                       mpiexec -n <n> ./pfc \n";
8c4762a1bSJed Brown 
9c4762a1bSJed Brown /* T
10c4762a1bSJed Brown    Concepts: DMNetwork
11c4762a1bSJed Brown    Concepts: PETSc SNES solver
12c4762a1bSJed Brown */
13c4762a1bSJed Brown 
14c4762a1bSJed Brown #include "power.h"
15c4762a1bSJed Brown #include <petscdmnetwork.h>
16c4762a1bSJed Brown 
17c4762a1bSJed Brown PetscErrorCode FormFunction(SNES snes,Vec X, Vec F,void *appctx)
18c4762a1bSJed Brown {
19c4762a1bSJed Brown   DM             networkdm;
20c4762a1bSJed Brown   UserCtx_Power  *User=(UserCtx_Power*)appctx;
21c4762a1bSJed Brown   Vec            localX,localF;
22c4762a1bSJed Brown   PetscInt       nv,ne;
23c4762a1bSJed Brown   const PetscInt *vtx,*edges;
24c4762a1bSJed Brown 
25c4762a1bSJed Brown   PetscFunctionBegin;
26*9566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes,&networkdm));
27*9566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(networkdm,&localX));
28*9566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(networkdm,&localF));
29*9566063dSJacob Faibussowitsch   PetscCall(VecSet(F,0.0));
30*9566063dSJacob Faibussowitsch   PetscCall(VecSet(localF,0.0));
31c4762a1bSJed Brown 
32*9566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX));
33*9566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX));
34c4762a1bSJed Brown 
35*9566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetSubnetwork(networkdm,0,&nv,&ne,&vtx,&edges));
36*9566063dSJacob Faibussowitsch   PetscCall(FormFunction_Power(networkdm,localX,localF,nv,ne,vtx,edges,User));
37c4762a1bSJed Brown 
38*9566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(networkdm,&localX));
39c4762a1bSJed Brown 
40*9566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(networkdm,localF,ADD_VALUES,F));
41*9566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(networkdm,localF,ADD_VALUES,F));
42*9566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(networkdm,&localF));
43c4762a1bSJed Brown   PetscFunctionReturn(0);
44c4762a1bSJed Brown }
45c4762a1bSJed Brown 
46c4762a1bSJed Brown PetscErrorCode SetInitialValues(DM networkdm,Vec X,void* appctx)
47c4762a1bSJed Brown {
48c4762a1bSJed Brown   PetscInt       vStart,vEnd,nv,ne;
49c4762a1bSJed Brown   const PetscInt *vtx,*edges;
50c4762a1bSJed Brown   Vec            localX;
51c4762a1bSJed Brown   UserCtx_Power  *user_power=(UserCtx_Power*)appctx;
52c4762a1bSJed Brown 
53c4762a1bSJed Brown   PetscFunctionBegin;
54*9566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetVertexRange(networkdm,&vStart, &vEnd));
55c4762a1bSJed Brown 
56*9566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(networkdm,&localX));
57c4762a1bSJed Brown 
58*9566063dSJacob Faibussowitsch   PetscCall(VecSet(X,0.0));
59*9566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX));
60*9566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX));
61c4762a1bSJed Brown 
62*9566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetSubnetwork(networkdm,0,&nv,&ne,&vtx,&edges));
63*9566063dSJacob Faibussowitsch   PetscCall(SetInitialGuess_Power(networkdm,localX,nv,ne,vtx,edges,user_power));
64c4762a1bSJed Brown 
65*9566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(networkdm,localX,ADD_VALUES,X));
66*9566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(networkdm,localX,ADD_VALUES,X));
67*9566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(networkdm,&localX));
68c4762a1bSJed Brown   PetscFunctionReturn(0);
69c4762a1bSJed Brown }
70c4762a1bSJed Brown 
71c4762a1bSJed Brown int main(int argc,char ** argv)
72c4762a1bSJed Brown {
73c4762a1bSJed Brown   char             pfdata_file[PETSC_MAX_PATH_LEN]="case9.m";
74c4762a1bSJed Brown   PFDATA           *pfdata;
75f11a936eSBarry Smith   PetscInt         numEdges=0;
76c4762a1bSJed Brown   PetscInt         *edges = NULL;
77c4762a1bSJed Brown   PetscInt         i;
78c4762a1bSJed Brown   DM               networkdm;
79c4762a1bSJed Brown   UserCtx_Power    User;
80956f8c0dSBarry Smith #if defined(PETSC_USE_LOG)
81c4762a1bSJed Brown   PetscLogStage    stage1,stage2;
82956f8c0dSBarry Smith #endif
83c4762a1bSJed Brown   PetscMPIInt      rank;
84c4762a1bSJed Brown   PetscInt         eStart, eEnd, vStart, vEnd,j;
85c4762a1bSJed Brown   PetscInt         genj,loadj;
86c4762a1bSJed Brown   Vec              X,F;
87c4762a1bSJed Brown   Mat              J;
88c4762a1bSJed Brown   SNES             snes;
89c4762a1bSJed Brown 
90*9566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc,&argv,"poweroptions",help));
91*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
92c4762a1bSJed Brown   {
93c4762a1bSJed Brown     /* introduce the const crank so the clang static analyzer realizes that if it enters any of the if (crank) then it must have entered the first */
94c4762a1bSJed Brown     /* this is an experiment to see how the analyzer reacts */
95c4762a1bSJed Brown     const PetscMPIInt crank = rank;
96c4762a1bSJed Brown 
97c4762a1bSJed Brown     /* Create an empty network object */
98*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkCreate(PETSC_COMM_WORLD,&networkdm));
99c4762a1bSJed Brown     /* Register the components in the network */
100*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkRegisterComponent(networkdm,"branchstruct",sizeof(struct _p_EDGE_Power),&User.compkey_branch));
101*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkRegisterComponent(networkdm,"busstruct",sizeof(struct _p_VERTEX_Power),&User.compkey_bus));
102*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkRegisterComponent(networkdm,"genstruct",sizeof(struct _p_GEN),&User.compkey_gen));
103*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkRegisterComponent(networkdm,"loadstruct",sizeof(struct _p_LOAD),&User.compkey_load));
104c4762a1bSJed Brown 
105*9566063dSJacob Faibussowitsch     PetscCall(PetscLogStageRegister("Read Data",&stage1));
106c4762a1bSJed Brown     PetscLogStagePush(stage1);
107c4762a1bSJed Brown     /* READ THE DATA */
108c4762a1bSJed Brown     if (!crank) {
109c4762a1bSJed Brown       /*    READ DATA */
110c4762a1bSJed Brown       /* Only rank 0 reads the data */
111*9566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetString(NULL,NULL,"-pfdata",pfdata_file,sizeof(pfdata_file),NULL));
112*9566063dSJacob Faibussowitsch       PetscCall(PetscNew(&pfdata));
113*9566063dSJacob Faibussowitsch       PetscCall(PFReadMatPowerData(pfdata,pfdata_file));
114c4762a1bSJed Brown       User.Sbase = pfdata->sbase;
115c4762a1bSJed Brown 
116c4762a1bSJed Brown       numEdges = pfdata->nbranch;
117*9566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(2*numEdges,&edges));
118*9566063dSJacob Faibussowitsch       PetscCall(GetListofEdges_Power(pfdata,edges));
119c4762a1bSJed Brown     }
120c4762a1bSJed Brown 
121c4762a1bSJed Brown     /* If external option activated. Introduce error in jacobian */
122*9566063dSJacob Faibussowitsch     PetscCall(PetscOptionsHasName(NULL,NULL, "-jac_error", &User.jac_error));
123c4762a1bSJed Brown 
124c4762a1bSJed Brown     PetscLogStagePop();
125*9566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
126*9566063dSJacob Faibussowitsch     PetscCall(PetscLogStageRegister("Create network",&stage2));
127c4762a1bSJed Brown     PetscLogStagePush(stage2);
128c4762a1bSJed Brown     /* Set number of nodes/edges */
129*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkSetNumSubNetworks(networkdm,PETSC_DECIDE,1));
130*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkAddSubnetwork(networkdm,"",numEdges,edges,NULL));
1312bf73ac6SHong Zhang 
132c4762a1bSJed Brown     /* Set up the network layout */
133*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkLayoutSetUp(networkdm));
134c4762a1bSJed Brown 
135c4762a1bSJed Brown     if (!crank) {
136*9566063dSJacob Faibussowitsch       PetscCall(PetscFree(edges));
137c4762a1bSJed Brown     }
138c4762a1bSJed Brown 
139c4762a1bSJed Brown     /* Add network components only process 0 has any data to add */
140c4762a1bSJed Brown     if (!crank) {
141c4762a1bSJed Brown       genj=0; loadj=0;
142*9566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetEdgeRange(networkdm,&eStart,&eEnd));
143c4762a1bSJed Brown       for (i = eStart; i < eEnd; i++) {
144*9566063dSJacob Faibussowitsch         PetscCall(DMNetworkAddComponent(networkdm,i,User.compkey_branch,&pfdata->branch[i-eStart],0));
145c4762a1bSJed Brown       }
146*9566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetVertexRange(networkdm,&vStart,&vEnd));
147c4762a1bSJed Brown       for (i = vStart; i < vEnd; i++) {
148*9566063dSJacob Faibussowitsch         PetscCall(DMNetworkAddComponent(networkdm,i,User.compkey_bus,&pfdata->bus[i-vStart],2));
149c4762a1bSJed Brown         if (pfdata->bus[i-vStart].ngen) {
150c4762a1bSJed Brown           for (j = 0; j < pfdata->bus[i-vStart].ngen; j++) {
151*9566063dSJacob Faibussowitsch             PetscCall(DMNetworkAddComponent(networkdm,i,User.compkey_gen,&pfdata->gen[genj++],0));
152c4762a1bSJed Brown           }
153c4762a1bSJed Brown         }
154c4762a1bSJed Brown         if (pfdata->bus[i-vStart].nload) {
155c4762a1bSJed Brown           for (j=0; j < pfdata->bus[i-vStart].nload; j++) {
156*9566063dSJacob Faibussowitsch             PetscCall(DMNetworkAddComponent(networkdm,i,User.compkey_load,&pfdata->load[loadj++],0));
157c4762a1bSJed Brown           }
158c4762a1bSJed Brown         }
159c4762a1bSJed Brown       }
160c4762a1bSJed Brown     }
161c4762a1bSJed Brown 
162c4762a1bSJed Brown     /* Set up DM for use */
163*9566063dSJacob Faibussowitsch     PetscCall(DMSetUp(networkdm));
164c4762a1bSJed Brown 
165c4762a1bSJed Brown     if (!crank) {
166*9566063dSJacob Faibussowitsch       PetscCall(PetscFree(pfdata->bus));
167*9566063dSJacob Faibussowitsch       PetscCall(PetscFree(pfdata->gen));
168*9566063dSJacob Faibussowitsch       PetscCall(PetscFree(pfdata->branch));
169*9566063dSJacob Faibussowitsch       PetscCall(PetscFree(pfdata->load));
170*9566063dSJacob Faibussowitsch       PetscCall(PetscFree(pfdata));
171c4762a1bSJed Brown     }
172c4762a1bSJed Brown 
173c4762a1bSJed Brown     /* Distribute networkdm to multiple processes */
174*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkDistribute(&networkdm,0));
175c4762a1bSJed Brown 
176c4762a1bSJed Brown     PetscLogStagePop();
177*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetEdgeRange(networkdm,&eStart,&eEnd));
178*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetVertexRange(networkdm,&vStart,&vEnd));
179c4762a1bSJed Brown 
180c4762a1bSJed Brown #if 0
181c4762a1bSJed Brown     EDGE_Power     edge;
182c4762a1bSJed Brown     PetscInt       key,kk,numComponents;
183c4762a1bSJed Brown     VERTEX_Power   bus;
184c4762a1bSJed Brown     GEN            gen;
185c4762a1bSJed Brown     LOAD           load;
186c4762a1bSJed Brown 
187c4762a1bSJed Brown     for (i = eStart; i < eEnd; i++) {
188*9566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetComponent(networkdm,i,0,&key,(void**)&edge));
189*9566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetNumComponents(networkdm,i,&numComponents));
190*9566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d ncomps = %d Line %d ---- %d\n",crank,numComponents,edge->internal_i,edge->internal_j));
191c4762a1bSJed Brown     }
192c4762a1bSJed Brown 
193c4762a1bSJed Brown     for (i = vStart; i < vEnd; i++) {
194*9566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetNumComponents(networkdm,i,&numComponents));
195c4762a1bSJed Brown       for (kk=0; kk < numComponents; kk++) {
196*9566063dSJacob Faibussowitsch         PetscCall(DMNetworkGetComponent(networkdm,i,kk,&key,&component));
197c4762a1bSJed Brown         if (key == 1) {
198c4762a1bSJed Brown           bus = (VERTEX_Power)(component);
199*9566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d ncomps = %d Bus %d\n",crank,numComponents,bus->internal_i));
200c4762a1bSJed Brown         } else if (key == 2) {
201c4762a1bSJed Brown           gen = (GEN)(component);
202*9566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d Gen pg = %f qg = %f\n",crank,gen->pg,gen->qg));
203c4762a1bSJed Brown         } else if (key == 3) {
204c4762a1bSJed Brown           load = (LOAD)(component);
205*9566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d Load pl = %f ql = %f\n",crank,load->pl,load->ql));
206c4762a1bSJed Brown         }
207c4762a1bSJed Brown       }
208c4762a1bSJed Brown     }
209c4762a1bSJed Brown #endif
210c4762a1bSJed Brown     /* Broadcast Sbase to all processors */
211*9566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(&User.Sbase,1,MPIU_SCALAR,0,PETSC_COMM_WORLD));
212c4762a1bSJed Brown 
213*9566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(networkdm,&X));
214*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(X,&F));
215c4762a1bSJed Brown 
216*9566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(networkdm,&J));
217*9566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE));
218c4762a1bSJed Brown 
219*9566063dSJacob Faibussowitsch     PetscCall(SetInitialValues(networkdm,X,&User));
220c4762a1bSJed Brown 
221c4762a1bSJed Brown     /* HOOK UP SOLVER */
222*9566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PETSC_COMM_WORLD,&snes));
223*9566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes,networkdm));
224*9566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes,F,FormFunction,&User));
225*9566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes,J,J,FormJacobian_Power,&User));
226*9566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes));
227c4762a1bSJed Brown 
228*9566063dSJacob Faibussowitsch     PetscCall(SNESSolve(snes,NULL,X));
229*9566063dSJacob Faibussowitsch     /* PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); */
230c4762a1bSJed Brown 
231*9566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&X));
232*9566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&F));
233*9566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
234c4762a1bSJed Brown 
235*9566063dSJacob Faibussowitsch     PetscCall(SNESDestroy(&snes));
236*9566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&networkdm));
237c4762a1bSJed Brown   }
238*9566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
239b122ec5aSJacob Faibussowitsch   return 0;
240c4762a1bSJed Brown }
241c4762a1bSJed Brown 
242c4762a1bSJed Brown /*TEST
243c4762a1bSJed Brown 
244c4762a1bSJed Brown    build:
245c4762a1bSJed Brown      depends: PFReadData.c pffunctions.c
246dfd57a17SPierre Jolivet      requires: !complex double defined(PETSC_HAVE_ATTRIBUTEALIGNED)
247c4762a1bSJed Brown 
248c4762a1bSJed Brown    test:
249c4762a1bSJed Brown      args: -snes_rtol 1.e-3
250c4762a1bSJed Brown      localrunfiles: poweroptions case9.m
251c4762a1bSJed Brown      output_file: output/power_1.out
252c4762a1bSJed Brown 
253c4762a1bSJed Brown    test:
254c4762a1bSJed Brown      suffix: 2
255c4762a1bSJed Brown      args: -snes_rtol 1.e-3 -petscpartitioner_type simple
256c4762a1bSJed Brown      nsize: 4
257c4762a1bSJed Brown      localrunfiles: poweroptions case9.m
258c4762a1bSJed Brown      output_file: output/power_1.out
259c4762a1bSJed Brown 
260c4762a1bSJed Brown TEST*/
261