xref: /petsc/src/snes/tutorials/network/power/power.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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 #include "power.h"
10c4762a1bSJed Brown #include <petscdmnetwork.h>
11c4762a1bSJed Brown 
129371c9d4SSatish Balay PetscErrorCode FormFunction(SNES snes, Vec X, Vec F, void *appctx) {
13c4762a1bSJed Brown   DM              networkdm;
14c4762a1bSJed Brown   UserCtx_Power  *User = (UserCtx_Power *)appctx;
15c4762a1bSJed Brown   Vec             localX, localF;
16c4762a1bSJed Brown   PetscInt        nv, ne;
17c4762a1bSJed Brown   const PetscInt *vtx, *edges;
18c4762a1bSJed Brown 
19c4762a1bSJed Brown   PetscFunctionBegin;
209566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &networkdm));
219566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(networkdm, &localX));
229566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(networkdm, &localF));
239566063dSJacob Faibussowitsch   PetscCall(VecSet(F, 0.0));
249566063dSJacob Faibussowitsch   PetscCall(VecSet(localF, 0.0));
25c4762a1bSJed Brown 
269566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX));
279566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX));
28c4762a1bSJed Brown 
299566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges));
309566063dSJacob Faibussowitsch   PetscCall(FormFunction_Power(networkdm, localX, localF, nv, ne, vtx, edges, User));
31c4762a1bSJed Brown 
329566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(networkdm, &localX));
33c4762a1bSJed Brown 
349566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(networkdm, localF, ADD_VALUES, F));
359566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(networkdm, localF, ADD_VALUES, F));
369566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(networkdm, &localF));
37c4762a1bSJed Brown   PetscFunctionReturn(0);
38c4762a1bSJed Brown }
39c4762a1bSJed Brown 
409371c9d4SSatish Balay PetscErrorCode SetInitialValues(DM networkdm, Vec X, void *appctx) {
41c4762a1bSJed Brown   PetscInt        vStart, vEnd, nv, ne;
42c4762a1bSJed Brown   const PetscInt *vtx, *edges;
43c4762a1bSJed Brown   Vec             localX;
44c4762a1bSJed Brown   UserCtx_Power  *user_power = (UserCtx_Power *)appctx;
45c4762a1bSJed Brown 
46c4762a1bSJed Brown   PetscFunctionBegin;
479566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetVertexRange(networkdm, &vStart, &vEnd));
48c4762a1bSJed Brown 
499566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(networkdm, &localX));
50c4762a1bSJed Brown 
519566063dSJacob Faibussowitsch   PetscCall(VecSet(X, 0.0));
529566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX));
539566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX));
54c4762a1bSJed Brown 
559566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges));
569566063dSJacob Faibussowitsch   PetscCall(SetInitialGuess_Power(networkdm, localX, nv, ne, vtx, edges, user_power));
57c4762a1bSJed Brown 
589566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(networkdm, localX, ADD_VALUES, X));
599566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(networkdm, localX, ADD_VALUES, X));
609566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(networkdm, &localX));
61c4762a1bSJed Brown   PetscFunctionReturn(0);
62c4762a1bSJed Brown }
63c4762a1bSJed Brown 
649371c9d4SSatish Balay int main(int argc, char **argv) {
65c4762a1bSJed Brown   char          pfdata_file[PETSC_MAX_PATH_LEN] = "case9.m";
66c4762a1bSJed Brown   PFDATA       *pfdata;
67f11a936eSBarry Smith   PetscInt      numEdges = 0;
68c4762a1bSJed Brown   PetscInt     *edges    = NULL;
69c4762a1bSJed Brown   PetscInt      i;
70c4762a1bSJed Brown   DM            networkdm;
71c4762a1bSJed Brown   UserCtx_Power User;
72956f8c0dSBarry Smith #if defined(PETSC_USE_LOG)
73c4762a1bSJed Brown   PetscLogStage stage1, stage2;
74956f8c0dSBarry Smith #endif
75c4762a1bSJed Brown   PetscMPIInt rank;
76c4762a1bSJed Brown   PetscInt    eStart, eEnd, vStart, vEnd, j;
77c4762a1bSJed Brown   PetscInt    genj, loadj;
78c4762a1bSJed Brown   Vec         X, F;
79c4762a1bSJed Brown   Mat         J;
80c4762a1bSJed Brown   SNES        snes;
81c4762a1bSJed Brown 
82327415f7SBarry Smith   PetscFunctionBeginUser;
839566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, "poweroptions", help));
849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
85c4762a1bSJed Brown   {
86c4762a1bSJed 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 */
87c4762a1bSJed Brown     /* this is an experiment to see how the analyzer reacts */
88c4762a1bSJed Brown     const PetscMPIInt crank = rank;
89c4762a1bSJed Brown 
90c4762a1bSJed Brown     /* Create an empty network object */
919566063dSJacob Faibussowitsch     PetscCall(DMNetworkCreate(PETSC_COMM_WORLD, &networkdm));
92c4762a1bSJed Brown     /* Register the components in the network */
939566063dSJacob Faibussowitsch     PetscCall(DMNetworkRegisterComponent(networkdm, "branchstruct", sizeof(struct _p_EDGE_Power), &User.compkey_branch));
949566063dSJacob Faibussowitsch     PetscCall(DMNetworkRegisterComponent(networkdm, "busstruct", sizeof(struct _p_VERTEX_Power), &User.compkey_bus));
959566063dSJacob Faibussowitsch     PetscCall(DMNetworkRegisterComponent(networkdm, "genstruct", sizeof(struct _p_GEN), &User.compkey_gen));
969566063dSJacob Faibussowitsch     PetscCall(DMNetworkRegisterComponent(networkdm, "loadstruct", sizeof(struct _p_LOAD), &User.compkey_load));
97c4762a1bSJed Brown 
989566063dSJacob Faibussowitsch     PetscCall(PetscLogStageRegister("Read Data", &stage1));
99c4762a1bSJed Brown     PetscLogStagePush(stage1);
100c4762a1bSJed Brown     /* READ THE DATA */
101c4762a1bSJed Brown     if (!crank) {
102c4762a1bSJed Brown       /*    READ DATA */
103c4762a1bSJed Brown       /* Only rank 0 reads the data */
1049566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetString(NULL, NULL, "-pfdata", pfdata_file, sizeof(pfdata_file), NULL));
1059566063dSJacob Faibussowitsch       PetscCall(PetscNew(&pfdata));
1069566063dSJacob Faibussowitsch       PetscCall(PFReadMatPowerData(pfdata, pfdata_file));
107c4762a1bSJed Brown       User.Sbase = pfdata->sbase;
108c4762a1bSJed Brown 
109c4762a1bSJed Brown       numEdges = pfdata->nbranch;
1109566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(2 * numEdges, &edges));
1119566063dSJacob Faibussowitsch       PetscCall(GetListofEdges_Power(pfdata, edges));
112c4762a1bSJed Brown     }
113c4762a1bSJed Brown 
114c4762a1bSJed Brown     /* If external option activated. Introduce error in jacobian */
1159566063dSJacob Faibussowitsch     PetscCall(PetscOptionsHasName(NULL, NULL, "-jac_error", &User.jac_error));
116c4762a1bSJed Brown 
117c4762a1bSJed Brown     PetscLogStagePop();
1189566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
1199566063dSJacob Faibussowitsch     PetscCall(PetscLogStageRegister("Create network", &stage2));
120c4762a1bSJed Brown     PetscLogStagePush(stage2);
121c4762a1bSJed Brown     /* Set number of nodes/edges */
1229566063dSJacob Faibussowitsch     PetscCall(DMNetworkSetNumSubNetworks(networkdm, PETSC_DECIDE, 1));
1239566063dSJacob Faibussowitsch     PetscCall(DMNetworkAddSubnetwork(networkdm, "", numEdges, edges, NULL));
1242bf73ac6SHong Zhang 
125c4762a1bSJed Brown     /* Set up the network layout */
1269566063dSJacob Faibussowitsch     PetscCall(DMNetworkLayoutSetUp(networkdm));
127c4762a1bSJed Brown 
128*48a46eb9SPierre Jolivet     if (!crank) PetscCall(PetscFree(edges));
129c4762a1bSJed Brown 
130c4762a1bSJed Brown     /* Add network components only process 0 has any data to add */
131c4762a1bSJed Brown     if (!crank) {
1329371c9d4SSatish Balay       genj  = 0;
1339371c9d4SSatish Balay       loadj = 0;
1349566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetEdgeRange(networkdm, &eStart, &eEnd));
135*48a46eb9SPierre Jolivet       for (i = eStart; i < eEnd; i++) PetscCall(DMNetworkAddComponent(networkdm, i, User.compkey_branch, &pfdata->branch[i - eStart], 0));
1369566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetVertexRange(networkdm, &vStart, &vEnd));
137c4762a1bSJed Brown       for (i = vStart; i < vEnd; i++) {
1389566063dSJacob Faibussowitsch         PetscCall(DMNetworkAddComponent(networkdm, i, User.compkey_bus, &pfdata->bus[i - vStart], 2));
139c4762a1bSJed Brown         if (pfdata->bus[i - vStart].ngen) {
140*48a46eb9SPierre Jolivet           for (j = 0; j < pfdata->bus[i - vStart].ngen; j++) PetscCall(DMNetworkAddComponent(networkdm, i, User.compkey_gen, &pfdata->gen[genj++], 0));
141c4762a1bSJed Brown         }
142c4762a1bSJed Brown         if (pfdata->bus[i - vStart].nload) {
143*48a46eb9SPierre Jolivet           for (j = 0; j < pfdata->bus[i - vStart].nload; j++) PetscCall(DMNetworkAddComponent(networkdm, i, User.compkey_load, &pfdata->load[loadj++], 0));
144c4762a1bSJed Brown         }
145c4762a1bSJed Brown       }
146c4762a1bSJed Brown     }
147c4762a1bSJed Brown 
148c4762a1bSJed Brown     /* Set up DM for use */
1499566063dSJacob Faibussowitsch     PetscCall(DMSetUp(networkdm));
150c4762a1bSJed Brown 
151c4762a1bSJed Brown     if (!crank) {
1529566063dSJacob Faibussowitsch       PetscCall(PetscFree(pfdata->bus));
1539566063dSJacob Faibussowitsch       PetscCall(PetscFree(pfdata->gen));
1549566063dSJacob Faibussowitsch       PetscCall(PetscFree(pfdata->branch));
1559566063dSJacob Faibussowitsch       PetscCall(PetscFree(pfdata->load));
1569566063dSJacob Faibussowitsch       PetscCall(PetscFree(pfdata));
157c4762a1bSJed Brown     }
158c4762a1bSJed Brown 
159c4762a1bSJed Brown     /* Distribute networkdm to multiple processes */
1609566063dSJacob Faibussowitsch     PetscCall(DMNetworkDistribute(&networkdm, 0));
161c4762a1bSJed Brown 
162c4762a1bSJed Brown     PetscLogStagePop();
1639566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetEdgeRange(networkdm, &eStart, &eEnd));
1649566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetVertexRange(networkdm, &vStart, &vEnd));
165c4762a1bSJed Brown 
166c4762a1bSJed Brown #if 0
167c4762a1bSJed Brown     EDGE_Power     edge;
168c4762a1bSJed Brown     PetscInt       key,kk,numComponents;
169c4762a1bSJed Brown     VERTEX_Power   bus;
170c4762a1bSJed Brown     GEN            gen;
171c4762a1bSJed Brown     LOAD           load;
172c4762a1bSJed Brown 
173c4762a1bSJed Brown     for (i = eStart; i < eEnd; i++) {
1749566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetComponent(networkdm,i,0,&key,(void**)&edge));
1759566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetNumComponents(networkdm,i,&numComponents));
1769566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d ncomps = %d Line %d ---- %d\n",crank,numComponents,edge->internal_i,edge->internal_j));
177c4762a1bSJed Brown     }
178c4762a1bSJed Brown 
179c4762a1bSJed Brown     for (i = vStart; i < vEnd; i++) {
1809566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetNumComponents(networkdm,i,&numComponents));
181c4762a1bSJed Brown       for (kk=0; kk < numComponents; kk++) {
1829566063dSJacob Faibussowitsch         PetscCall(DMNetworkGetComponent(networkdm,i,kk,&key,&component));
183c4762a1bSJed Brown         if (key == 1) {
184c4762a1bSJed Brown           bus = (VERTEX_Power)(component);
1859566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d ncomps = %d Bus %d\n",crank,numComponents,bus->internal_i));
186c4762a1bSJed Brown         } else if (key == 2) {
187c4762a1bSJed Brown           gen = (GEN)(component);
18863a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d Gen pg = %f qg = %f\n",crank,(double)gen->pg,(double)gen->qg));
189c4762a1bSJed Brown         } else if (key == 3) {
190c4762a1bSJed Brown           load = (LOAD)(component);
19163a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d Load pl = %f ql = %f\n",crank,(double)load->pl,(double)load->ql));
192c4762a1bSJed Brown         }
193c4762a1bSJed Brown       }
194c4762a1bSJed Brown     }
195c4762a1bSJed Brown #endif
196c4762a1bSJed Brown     /* Broadcast Sbase to all processors */
1979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(&User.Sbase, 1, MPIU_SCALAR, 0, PETSC_COMM_WORLD));
198c4762a1bSJed Brown 
1999566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(networkdm, &X));
2009566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(X, &F));
201c4762a1bSJed Brown 
2029566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(networkdm, &J));
2039566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
204c4762a1bSJed Brown 
2059566063dSJacob Faibussowitsch     PetscCall(SetInitialValues(networkdm, X, &User));
206c4762a1bSJed Brown 
207c4762a1bSJed Brown     /* HOOK UP SOLVER */
2089566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));
2099566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes, networkdm));
2109566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes, F, FormFunction, &User));
2119566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, FormJacobian_Power, &User));
2129566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes));
213c4762a1bSJed Brown 
2149566063dSJacob Faibussowitsch     PetscCall(SNESSolve(snes, NULL, X));
2159566063dSJacob Faibussowitsch     /* PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); */
216c4762a1bSJed Brown 
2179566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&X));
2189566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&F));
2199566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
220c4762a1bSJed Brown 
2219566063dSJacob Faibussowitsch     PetscCall(SNESDestroy(&snes));
2229566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&networkdm));
223c4762a1bSJed Brown   }
2249566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
225b122ec5aSJacob Faibussowitsch   return 0;
226c4762a1bSJed Brown }
227c4762a1bSJed Brown 
228c4762a1bSJed Brown /*TEST
229c4762a1bSJed Brown 
230c4762a1bSJed Brown    build:
231c4762a1bSJed Brown      depends: PFReadData.c pffunctions.c
232dfd57a17SPierre Jolivet      requires: !complex double defined(PETSC_HAVE_ATTRIBUTEALIGNED)
233c4762a1bSJed Brown 
234c4762a1bSJed Brown    test:
235c4762a1bSJed Brown      args: -snes_rtol 1.e-3
236c4762a1bSJed Brown      localrunfiles: poweroptions case9.m
237c4762a1bSJed Brown      output_file: output/power_1.out
238c4762a1bSJed Brown 
239c4762a1bSJed Brown    test:
240c4762a1bSJed Brown      suffix: 2
241c4762a1bSJed Brown      args: -snes_rtol 1.e-3 -petscpartitioner_type simple
242c4762a1bSJed Brown      nsize: 4
243c4762a1bSJed Brown      localrunfiles: poweroptions case9.m
244c4762a1bSJed Brown      output_file: output/power_1.out
245c4762a1bSJed Brown 
246c4762a1bSJed Brown TEST*/
247