xref: /petsc/src/snes/tutorials/network/power/power.c (revision 589a23caa660d2a5f330cc8d1ed213e9cfaf51a7)
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   PetscErrorCode ierr;
20c4762a1bSJed Brown   DM             networkdm;
21c4762a1bSJed Brown   UserCtx_Power  *User=(UserCtx_Power*)appctx;
22c4762a1bSJed Brown   Vec            localX,localF;
23c4762a1bSJed Brown   PetscInt       nv,ne;
24c4762a1bSJed Brown   const PetscInt *vtx,*edges;
25c4762a1bSJed Brown 
26c4762a1bSJed Brown   PetscFunctionBegin;
27c4762a1bSJed Brown   ierr = SNESGetDM(snes,&networkdm);CHKERRQ(ierr);
28c4762a1bSJed Brown   ierr = DMGetLocalVector(networkdm,&localX);CHKERRQ(ierr);
29c4762a1bSJed Brown   ierr = DMGetLocalVector(networkdm,&localF);CHKERRQ(ierr);
30c4762a1bSJed Brown   ierr = VecSet(F,0.0);CHKERRQ(ierr);
31c4762a1bSJed Brown   ierr = VecSet(localF,0.0);CHKERRQ(ierr);
32c4762a1bSJed Brown 
33c4762a1bSJed Brown   ierr = DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr);
34c4762a1bSJed Brown   ierr = DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr);
35c4762a1bSJed Brown 
36c4762a1bSJed Brown   ierr = DMNetworkGetSubnetworkInfo(networkdm,0,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
37c4762a1bSJed Brown   ierr = FormFunction_Power(networkdm,localX,localF,nv,ne,vtx,edges,User);CHKERRQ(ierr);
38c4762a1bSJed Brown 
39c4762a1bSJed Brown   ierr = DMRestoreLocalVector(networkdm,&localX);CHKERRQ(ierr);
40c4762a1bSJed Brown 
41c4762a1bSJed Brown   ierr = DMLocalToGlobalBegin(networkdm,localF,ADD_VALUES,F);CHKERRQ(ierr);
42c4762a1bSJed Brown   ierr = DMLocalToGlobalEnd(networkdm,localF,ADD_VALUES,F);CHKERRQ(ierr);
43c4762a1bSJed Brown   ierr = DMRestoreLocalVector(networkdm,&localF);CHKERRQ(ierr);
44c4762a1bSJed Brown   PetscFunctionReturn(0);
45c4762a1bSJed Brown }
46c4762a1bSJed Brown 
47c4762a1bSJed Brown PetscErrorCode SetInitialValues(DM networkdm,Vec X,void* appctx)
48c4762a1bSJed Brown {
49c4762a1bSJed Brown   PetscErrorCode ierr;
50c4762a1bSJed Brown   PetscInt       vStart,vEnd,nv,ne;
51c4762a1bSJed Brown   const PetscInt *vtx,*edges;
52c4762a1bSJed Brown   Vec            localX;
53c4762a1bSJed Brown   UserCtx_Power  *user_power=(UserCtx_Power*)appctx;
54c4762a1bSJed Brown 
55c4762a1bSJed Brown   PetscFunctionBegin;
56c4762a1bSJed Brown   ierr = DMNetworkGetVertexRange(networkdm,&vStart, &vEnd);CHKERRQ(ierr);
57c4762a1bSJed Brown 
58c4762a1bSJed Brown   ierr = DMGetLocalVector(networkdm,&localX);CHKERRQ(ierr);
59c4762a1bSJed Brown 
60c4762a1bSJed Brown   ierr = VecSet(X,0.0);CHKERRQ(ierr);
61c4762a1bSJed Brown   ierr = DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr);
62c4762a1bSJed Brown   ierr = DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr);
63c4762a1bSJed Brown 
64c4762a1bSJed Brown   ierr = DMNetworkGetSubnetworkInfo(networkdm,0,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
65c4762a1bSJed Brown   ierr = SetInitialGuess_Power(networkdm,localX,nv,ne,vtx,edges,user_power);CHKERRQ(ierr);
66c4762a1bSJed Brown 
67c4762a1bSJed Brown   ierr = DMLocalToGlobalBegin(networkdm,localX,ADD_VALUES,X);CHKERRQ(ierr);
68c4762a1bSJed Brown   ierr = DMLocalToGlobalEnd(networkdm,localX,ADD_VALUES,X);CHKERRQ(ierr);
69c4762a1bSJed Brown   ierr = DMRestoreLocalVector(networkdm,&localX);CHKERRQ(ierr);
70c4762a1bSJed Brown   PetscFunctionReturn(0);
71c4762a1bSJed Brown }
72c4762a1bSJed Brown 
73c4762a1bSJed Brown int main(int argc,char ** argv)
74c4762a1bSJed Brown {
75c4762a1bSJed Brown   PetscErrorCode   ierr;
76c4762a1bSJed Brown   char             pfdata_file[PETSC_MAX_PATH_LEN]="case9.m";
77c4762a1bSJed Brown   PFDATA           *pfdata;
78c4762a1bSJed Brown   PetscInt         numEdges=0,numVertices=0;
79c4762a1bSJed Brown   PetscInt         *edges = NULL;
80c4762a1bSJed Brown   PetscInt         i;
81c4762a1bSJed Brown   DM               networkdm;
82c4762a1bSJed Brown   UserCtx_Power    User;
83c4762a1bSJed Brown   PetscLogStage    stage1,stage2;
84c4762a1bSJed Brown   PetscMPIInt      rank;
85c4762a1bSJed Brown   PetscInt         eStart, eEnd, vStart, vEnd,j;
86c4762a1bSJed Brown   PetscInt         genj,loadj;
87c4762a1bSJed Brown   Vec              X,F;
88c4762a1bSJed Brown   Mat              J;
89c4762a1bSJed Brown   SNES             snes;
90c4762a1bSJed Brown 
91c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,"poweroptions",help);if (ierr) return ierr;
92c4762a1bSJed Brown   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
93c4762a1bSJed Brown   {
94c4762a1bSJed 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 */
95c4762a1bSJed Brown     /* this is an experiment to see how the analyzer reacts */
96c4762a1bSJed Brown     const PetscMPIInt crank = rank;
97c4762a1bSJed Brown 
98c4762a1bSJed Brown     /* Create an empty network object */
99c4762a1bSJed Brown     ierr = DMNetworkCreate(PETSC_COMM_WORLD,&networkdm);CHKERRQ(ierr);
100c4762a1bSJed Brown     /* Register the components in the network */
101c4762a1bSJed Brown     ierr = DMNetworkRegisterComponent(networkdm,"branchstruct",sizeof(struct _p_EDGE_Power),&User.compkey_branch);CHKERRQ(ierr);
102c4762a1bSJed Brown     ierr = DMNetworkRegisterComponent(networkdm,"busstruct",sizeof(struct _p_VERTEX_Power),&User.compkey_bus);CHKERRQ(ierr);
103c4762a1bSJed Brown     ierr = DMNetworkRegisterComponent(networkdm,"genstruct",sizeof(struct _p_GEN),&User.compkey_gen);CHKERRQ(ierr);
104c4762a1bSJed Brown     ierr = DMNetworkRegisterComponent(networkdm,"loadstruct",sizeof(struct _p_LOAD),&User.compkey_load);CHKERRQ(ierr);
105c4762a1bSJed Brown 
106c4762a1bSJed Brown     ierr = PetscLogStageRegister("Read Data",&stage1);CHKERRQ(ierr);
107c4762a1bSJed Brown     PetscLogStagePush(stage1);
108c4762a1bSJed Brown     /* READ THE DATA */
109c4762a1bSJed Brown     if (!crank) {
110c4762a1bSJed Brown       /*    READ DATA */
111c4762a1bSJed Brown       /* Only rank 0 reads the data */
112*589a23caSBarry Smith       ierr = PetscOptionsGetString(NULL,NULL,"-pfdata",pfdata_file,sizeof(pfdata_file),NULL);CHKERRQ(ierr);
113c4762a1bSJed Brown       ierr = PetscNew(&pfdata);CHKERRQ(ierr);
114c4762a1bSJed Brown       ierr = PFReadMatPowerData(pfdata,pfdata_file);CHKERRQ(ierr);
115c4762a1bSJed Brown       User.Sbase = pfdata->sbase;
116c4762a1bSJed Brown 
117c4762a1bSJed Brown       numEdges = pfdata->nbranch;
118c4762a1bSJed Brown       numVertices = pfdata->nbus;
119c4762a1bSJed Brown 
120c4762a1bSJed Brown       ierr = PetscMalloc1(2*numEdges,&edges);CHKERRQ(ierr);
121c4762a1bSJed Brown       ierr = GetListofEdges_Power(pfdata,edges);CHKERRQ(ierr);
122c4762a1bSJed Brown     }
123c4762a1bSJed Brown 
124c4762a1bSJed Brown     /* If external option activated. Introduce error in jacobian */
125c4762a1bSJed Brown     ierr = PetscOptionsHasName(NULL,NULL, "-jac_error", &User.jac_error);CHKERRQ(ierr);
126c4762a1bSJed Brown 
127c4762a1bSJed Brown     PetscLogStagePop();
128c4762a1bSJed Brown     ierr = MPI_Barrier(PETSC_COMM_WORLD);CHKERRQ(ierr);
129c4762a1bSJed Brown     ierr = PetscLogStageRegister("Create network",&stage2);CHKERRQ(ierr);
130c4762a1bSJed Brown     PetscLogStagePush(stage2);
131c4762a1bSJed Brown     /* Set number of nodes/edges */
132c4762a1bSJed Brown     ierr = DMNetworkSetSizes(networkdm,1,&numVertices,&numEdges,0,NULL);CHKERRQ(ierr);
133c4762a1bSJed Brown     /* Add edge connectivity */
134c4762a1bSJed Brown     ierr = DMNetworkSetEdgeList(networkdm,&edges,NULL);CHKERRQ(ierr);
135c4762a1bSJed Brown     /* Set up the network layout */
136c4762a1bSJed Brown     ierr = DMNetworkLayoutSetUp(networkdm);CHKERRQ(ierr);
137c4762a1bSJed Brown 
138c4762a1bSJed Brown     if (!crank) {
139c4762a1bSJed Brown       ierr = PetscFree(edges);CHKERRQ(ierr);
140c4762a1bSJed Brown     }
141c4762a1bSJed Brown 
142c4762a1bSJed Brown     /* Add network components only process 0 has any data to add*/
143c4762a1bSJed Brown     if (!crank) {
144c4762a1bSJed Brown       genj=0; loadj=0;
145c4762a1bSJed Brown       ierr = DMNetworkGetEdgeRange(networkdm,&eStart,&eEnd);CHKERRQ(ierr);
146c4762a1bSJed Brown       for (i = eStart; i < eEnd; i++) {
147c4762a1bSJed Brown         ierr = DMNetworkAddComponent(networkdm,i,User.compkey_branch,&pfdata->branch[i-eStart]);CHKERRQ(ierr);
148c4762a1bSJed Brown       }
149c4762a1bSJed Brown       ierr = DMNetworkGetVertexRange(networkdm,&vStart,&vEnd);CHKERRQ(ierr);
150c4762a1bSJed Brown       for (i = vStart; i < vEnd; i++) {
151c4762a1bSJed Brown         ierr = DMNetworkAddComponent(networkdm,i,User.compkey_bus,&pfdata->bus[i-vStart]);CHKERRQ(ierr);
152c4762a1bSJed Brown         if (pfdata->bus[i-vStart].ngen) {
153c4762a1bSJed Brown           for (j = 0; j < pfdata->bus[i-vStart].ngen; j++) {
154c4762a1bSJed Brown             ierr = DMNetworkAddComponent(networkdm,i,User.compkey_gen,&pfdata->gen[genj++]);CHKERRQ(ierr);
155c4762a1bSJed Brown           }
156c4762a1bSJed Brown         }
157c4762a1bSJed Brown         if (pfdata->bus[i-vStart].nload) {
158c4762a1bSJed Brown           for (j=0; j < pfdata->bus[i-vStart].nload; j++) {
159c4762a1bSJed Brown             ierr = DMNetworkAddComponent(networkdm,i,User.compkey_load,&pfdata->load[loadj++]);CHKERRQ(ierr);
160c4762a1bSJed Brown           }
161c4762a1bSJed Brown         }
162c4762a1bSJed Brown         /* Add number of variables */
163c4762a1bSJed Brown         ierr = DMNetworkAddNumVariables(networkdm,i,2);CHKERRQ(ierr);
164c4762a1bSJed Brown       }
165c4762a1bSJed Brown     }
166c4762a1bSJed Brown 
167c4762a1bSJed Brown     /* Set up DM for use */
168c4762a1bSJed Brown     ierr = DMSetUp(networkdm);CHKERRQ(ierr);
169c4762a1bSJed Brown 
170c4762a1bSJed Brown     if (!crank) {
171c4762a1bSJed Brown       ierr = PetscFree(pfdata->bus);CHKERRQ(ierr);
172c4762a1bSJed Brown       ierr = PetscFree(pfdata->gen);CHKERRQ(ierr);
173c4762a1bSJed Brown       ierr = PetscFree(pfdata->branch);CHKERRQ(ierr);
174c4762a1bSJed Brown       ierr = PetscFree(pfdata->load);CHKERRQ(ierr);
175c4762a1bSJed Brown       ierr = PetscFree(pfdata);CHKERRQ(ierr);
176c4762a1bSJed Brown     }
177c4762a1bSJed Brown 
178c4762a1bSJed Brown     /* Distribute networkdm to multiple processes */
179c4762a1bSJed Brown     ierr = DMNetworkDistribute(&networkdm,0);CHKERRQ(ierr);
180c4762a1bSJed Brown 
181c4762a1bSJed Brown     PetscLogStagePop();
182c4762a1bSJed Brown     ierr = DMNetworkGetEdgeRange(networkdm,&eStart,&eEnd);CHKERRQ(ierr);
183c4762a1bSJed Brown     ierr = DMNetworkGetVertexRange(networkdm,&vStart,&vEnd);CHKERRQ(ierr);
184c4762a1bSJed Brown 
185c4762a1bSJed Brown #if 0
186c4762a1bSJed Brown     EDGE_Power     edge;
187c4762a1bSJed Brown     PetscInt       key,kk,numComponents;
188c4762a1bSJed Brown     VERTEX_Power   bus;
189c4762a1bSJed Brown     GEN            gen;
190c4762a1bSJed Brown     LOAD           load;
191c4762a1bSJed Brown 
192c4762a1bSJed Brown     for (i = eStart; i < eEnd; i++) {
193c4762a1bSJed Brown       ierr = DMNetworkGetComponent(networkdm,i,0,&key,(void**)&edge);CHKERRQ(ierr);
194c4762a1bSJed Brown       ierr = DMNetworkGetNumComponents(networkdm,i,&numComponents);CHKERRQ(ierr);
195c4762a1bSJed Brown       ierr = PetscPrintf(PETSC_COMM_SELF,"Rank %d ncomps = %d Line %d ---- %d\n",crank,numComponents,edge->internal_i,edge->internal_j);CHKERRQ(ierr);
196c4762a1bSJed Brown     }
197c4762a1bSJed Brown 
198c4762a1bSJed Brown     for (i = vStart; i < vEnd; i++) {
199c4762a1bSJed Brown       ierr = DMNetworkGetNumComponents(networkdm,i,&numComponents);CHKERRQ(ierr);
200c4762a1bSJed Brown       for (kk=0; kk < numComponents; kk++) {
201c4762a1bSJed Brown         ierr = DMNetworkGetComponent(networkdm,i,kk,&key,&component);CHKERRQ(ierr);
202c4762a1bSJed Brown         if (key == 1) {
203c4762a1bSJed Brown           bus = (VERTEX_Power)(component);
204c4762a1bSJed Brown           ierr = PetscPrintf(PETSC_COMM_SELF,"Rank %d ncomps = %d Bus %d\n",crank,numComponents,bus->internal_i);CHKERRQ(ierr);
205c4762a1bSJed Brown         } else if (key == 2) {
206c4762a1bSJed Brown           gen = (GEN)(component);
207c4762a1bSJed Brown           ierr = PetscPrintf(PETSC_COMM_SELF,"Rank %d Gen pg = %f qg = %f\n",crank,gen->pg,gen->qg);CHKERRQ(ierr);
208c4762a1bSJed Brown         } else if (key == 3) {
209c4762a1bSJed Brown           load = (LOAD)(component);
210c4762a1bSJed Brown           ierr = PetscPrintf(PETSC_COMM_SELF,"Rank %d Load pl = %f ql = %f\n",crank,load->pl,load->ql);CHKERRQ(ierr);
211c4762a1bSJed Brown         }
212c4762a1bSJed Brown       }
213c4762a1bSJed Brown     }
214c4762a1bSJed Brown #endif
215c4762a1bSJed Brown     /* Broadcast Sbase to all processors */
216c4762a1bSJed Brown     ierr = MPI_Bcast(&User.Sbase,1,MPIU_SCALAR,0,PETSC_COMM_WORLD);CHKERRQ(ierr);
217c4762a1bSJed Brown 
218c4762a1bSJed Brown     ierr = DMCreateGlobalVector(networkdm,&X);CHKERRQ(ierr);
219c4762a1bSJed Brown     ierr = VecDuplicate(X,&F);CHKERRQ(ierr);
220c4762a1bSJed Brown 
221c4762a1bSJed Brown     ierr = DMCreateMatrix(networkdm,&J);CHKERRQ(ierr);
222c4762a1bSJed Brown     ierr = MatSetOption(J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
223c4762a1bSJed Brown 
224c4762a1bSJed Brown     ierr = SetInitialValues(networkdm,X,&User);CHKERRQ(ierr);
225c4762a1bSJed Brown 
226c4762a1bSJed Brown     /* HOOK UP SOLVER */
227c4762a1bSJed Brown     ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr);
228c4762a1bSJed Brown     ierr = SNESSetDM(snes,networkdm);CHKERRQ(ierr);
229c4762a1bSJed Brown     ierr = SNESSetFunction(snes,F,FormFunction,&User);CHKERRQ(ierr);
230c4762a1bSJed Brown     ierr = SNESSetJacobian(snes,J,J,FormJacobian_Power,&User);CHKERRQ(ierr);
231c4762a1bSJed Brown     ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
232c4762a1bSJed Brown 
233c4762a1bSJed Brown     ierr = SNESSolve(snes,NULL,X);CHKERRQ(ierr);
234c4762a1bSJed Brown     /* ierr = VecView(X,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */
235c4762a1bSJed Brown 
236c4762a1bSJed Brown     ierr = VecDestroy(&X);CHKERRQ(ierr);
237c4762a1bSJed Brown     ierr = VecDestroy(&F);CHKERRQ(ierr);
238c4762a1bSJed Brown     ierr = MatDestroy(&J);CHKERRQ(ierr);
239c4762a1bSJed Brown 
240c4762a1bSJed Brown     ierr = SNESDestroy(&snes);CHKERRQ(ierr);
241c4762a1bSJed Brown     ierr = DMDestroy(&networkdm);CHKERRQ(ierr);
242c4762a1bSJed Brown   }
243c4762a1bSJed Brown   ierr = PetscFinalize();
244c4762a1bSJed Brown   return ierr;
245c4762a1bSJed Brown }
246c4762a1bSJed Brown 
247c4762a1bSJed Brown /*TEST
248c4762a1bSJed Brown 
249c4762a1bSJed Brown    build:
250c4762a1bSJed Brown      depends: PFReadData.c pffunctions.c
251c4762a1bSJed Brown      requires: !complex double define(PETSC_HAVE_ATTRIBUTEALIGNED)
252c4762a1bSJed Brown 
253c4762a1bSJed Brown 
254c4762a1bSJed Brown    test:
255c4762a1bSJed Brown      args: -snes_rtol 1.e-3
256c4762a1bSJed Brown      localrunfiles: poweroptions case9.m
257c4762a1bSJed Brown      output_file: output/power_1.out
258c4762a1bSJed Brown      requires: double !complex define(PETSC_HAVE_ATTRIBUTEALIGNED)
259c4762a1bSJed Brown 
260c4762a1bSJed Brown    test:
261c4762a1bSJed Brown      suffix: 2
262c4762a1bSJed Brown      args: -snes_rtol 1.e-3 -petscpartitioner_type simple
263c4762a1bSJed Brown      nsize: 4
264c4762a1bSJed Brown      localrunfiles: poweroptions case9.m
265c4762a1bSJed Brown      output_file: output/power_1.out
266c4762a1bSJed Brown      requires: double !complex define(PETSC_HAVE_ATTRIBUTEALIGNED)
267c4762a1bSJed Brown 
268c4762a1bSJed Brown TEST*/
269