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