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 12d71ae5a4SJacob Faibussowitsch PetscErrorCode FormFunction(SNES snes, Vec X, Vec F, void *appctx) 13d71ae5a4SJacob Faibussowitsch { 14c4762a1bSJed Brown DM networkdm; 15c4762a1bSJed Brown UserCtx_Power *User = (UserCtx_Power *)appctx; 16c4762a1bSJed Brown Vec localX, localF; 17c4762a1bSJed Brown PetscInt nv, ne; 18c4762a1bSJed Brown const PetscInt *vtx, *edges; 19c4762a1bSJed Brown 20c4762a1bSJed Brown PetscFunctionBegin; 219566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &networkdm)); 229566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localX)); 239566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localF)); 249566063dSJacob Faibussowitsch PetscCall(VecSet(F, 0.0)); 259566063dSJacob Faibussowitsch PetscCall(VecSet(localF, 0.0)); 26c4762a1bSJed Brown 279566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX)); 289566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX)); 29c4762a1bSJed Brown 309566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 319566063dSJacob Faibussowitsch PetscCall(FormFunction_Power(networkdm, localX, localF, nv, ne, vtx, edges, User)); 32c4762a1bSJed Brown 339566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localX)); 34c4762a1bSJed Brown 359566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localF, ADD_VALUES, F)); 369566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localF, ADD_VALUES, F)); 379566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localF)); 38*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39c4762a1bSJed Brown } 40c4762a1bSJed Brown 41d71ae5a4SJacob Faibussowitsch PetscErrorCode SetInitialValues(DM networkdm, Vec X, void *appctx) 42d71ae5a4SJacob Faibussowitsch { 43c4762a1bSJed Brown PetscInt vStart, vEnd, nv, ne; 44c4762a1bSJed Brown const PetscInt *vtx, *edges; 45c4762a1bSJed Brown Vec localX; 46c4762a1bSJed Brown UserCtx_Power *user_power = (UserCtx_Power *)appctx; 47c4762a1bSJed Brown 48c4762a1bSJed Brown PetscFunctionBegin; 499566063dSJacob Faibussowitsch PetscCall(DMNetworkGetVertexRange(networkdm, &vStart, &vEnd)); 50c4762a1bSJed Brown 519566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localX)); 52c4762a1bSJed Brown 539566063dSJacob Faibussowitsch PetscCall(VecSet(X, 0.0)); 549566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX)); 559566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX)); 56c4762a1bSJed Brown 579566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 589566063dSJacob Faibussowitsch PetscCall(SetInitialGuess_Power(networkdm, localX, nv, ne, vtx, edges, user_power)); 59c4762a1bSJed Brown 609566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localX, ADD_VALUES, X)); 619566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localX, ADD_VALUES, X)); 629566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localX)); 63*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64c4762a1bSJed Brown } 65c4762a1bSJed Brown 66d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 67d71ae5a4SJacob Faibussowitsch { 68c4762a1bSJed Brown char pfdata_file[PETSC_MAX_PATH_LEN] = "case9.m"; 69c4762a1bSJed Brown PFDATA *pfdata; 70f11a936eSBarry Smith PetscInt numEdges = 0; 71c4762a1bSJed Brown PetscInt *edges = NULL; 72c4762a1bSJed Brown PetscInt i; 73c4762a1bSJed Brown DM networkdm; 74c4762a1bSJed Brown UserCtx_Power User; 75956f8c0dSBarry Smith #if defined(PETSC_USE_LOG) 76c4762a1bSJed Brown PetscLogStage stage1, stage2; 77956f8c0dSBarry Smith #endif 78c4762a1bSJed Brown PetscMPIInt rank; 79c4762a1bSJed Brown PetscInt eStart, eEnd, vStart, vEnd, j; 80c4762a1bSJed Brown PetscInt genj, loadj; 81c4762a1bSJed Brown Vec X, F; 82c4762a1bSJed Brown Mat J; 83c4762a1bSJed Brown SNES snes; 84c4762a1bSJed Brown 85327415f7SBarry Smith PetscFunctionBeginUser; 869566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, "poweroptions", help)); 879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 88c4762a1bSJed Brown { 89c4762a1bSJed 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 */ 90c4762a1bSJed Brown /* this is an experiment to see how the analyzer reacts */ 91c4762a1bSJed Brown const PetscMPIInt crank = rank; 92c4762a1bSJed Brown 93c4762a1bSJed Brown /* Create an empty network object */ 949566063dSJacob Faibussowitsch PetscCall(DMNetworkCreate(PETSC_COMM_WORLD, &networkdm)); 95c4762a1bSJed Brown /* Register the components in the network */ 969566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "branchstruct", sizeof(struct _p_EDGE_Power), &User.compkey_branch)); 979566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "busstruct", sizeof(struct _p_VERTEX_Power), &User.compkey_bus)); 989566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "genstruct", sizeof(struct _p_GEN), &User.compkey_gen)); 999566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "loadstruct", sizeof(struct _p_LOAD), &User.compkey_load)); 100c4762a1bSJed Brown 1019566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Read Data", &stage1)); 102*3ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePush(stage1)); 103c4762a1bSJed Brown /* READ THE DATA */ 104c4762a1bSJed Brown if (!crank) { 105c4762a1bSJed Brown /* READ DATA */ 106c4762a1bSJed Brown /* Only rank 0 reads the data */ 1079566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-pfdata", pfdata_file, sizeof(pfdata_file), NULL)); 1089566063dSJacob Faibussowitsch PetscCall(PetscNew(&pfdata)); 1099566063dSJacob Faibussowitsch PetscCall(PFReadMatPowerData(pfdata, pfdata_file)); 110c4762a1bSJed Brown User.Sbase = pfdata->sbase; 111c4762a1bSJed Brown 112c4762a1bSJed Brown numEdges = pfdata->nbranch; 1139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * numEdges, &edges)); 1149566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Power(pfdata, edges)); 115c4762a1bSJed Brown } 116c4762a1bSJed Brown 117c4762a1bSJed Brown /* If external option activated. Introduce error in jacobian */ 1189566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-jac_error", &User.jac_error)); 119c4762a1bSJed Brown 120*3ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePop()); 1219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 1229566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Create network", &stage2)); 123*3ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePush(stage2)); 124c4762a1bSJed Brown /* Set number of nodes/edges */ 1259566063dSJacob Faibussowitsch PetscCall(DMNetworkSetNumSubNetworks(networkdm, PETSC_DECIDE, 1)); 1269566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, "", numEdges, edges, NULL)); 1272bf73ac6SHong Zhang 128c4762a1bSJed Brown /* Set up the network layout */ 1299566063dSJacob Faibussowitsch PetscCall(DMNetworkLayoutSetUp(networkdm)); 130c4762a1bSJed Brown 13148a46eb9SPierre Jolivet if (!crank) PetscCall(PetscFree(edges)); 132c4762a1bSJed Brown 133c4762a1bSJed Brown /* Add network components only process 0 has any data to add */ 134c4762a1bSJed Brown if (!crank) { 1359371c9d4SSatish Balay genj = 0; 1369371c9d4SSatish Balay loadj = 0; 1379566063dSJacob Faibussowitsch PetscCall(DMNetworkGetEdgeRange(networkdm, &eStart, &eEnd)); 13848a46eb9SPierre Jolivet for (i = eStart; i < eEnd; i++) PetscCall(DMNetworkAddComponent(networkdm, i, User.compkey_branch, &pfdata->branch[i - eStart], 0)); 1399566063dSJacob Faibussowitsch PetscCall(DMNetworkGetVertexRange(networkdm, &vStart, &vEnd)); 140c4762a1bSJed Brown for (i = vStart; i < vEnd; i++) { 1419566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, i, User.compkey_bus, &pfdata->bus[i - vStart], 2)); 142c4762a1bSJed Brown if (pfdata->bus[i - vStart].ngen) { 14348a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i - vStart].ngen; j++) PetscCall(DMNetworkAddComponent(networkdm, i, User.compkey_gen, &pfdata->gen[genj++], 0)); 144c4762a1bSJed Brown } 145c4762a1bSJed Brown if (pfdata->bus[i - vStart].nload) { 14648a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i - vStart].nload; j++) PetscCall(DMNetworkAddComponent(networkdm, i, User.compkey_load, &pfdata->load[loadj++], 0)); 147c4762a1bSJed Brown } 148c4762a1bSJed Brown } 149c4762a1bSJed Brown } 150c4762a1bSJed Brown 151c4762a1bSJed Brown /* Set up DM for use */ 1529566063dSJacob Faibussowitsch PetscCall(DMSetUp(networkdm)); 153c4762a1bSJed Brown 154c4762a1bSJed Brown if (!crank) { 1559566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->bus)); 1569566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->gen)); 1579566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->branch)); 1589566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->load)); 1599566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata)); 160c4762a1bSJed Brown } 161c4762a1bSJed Brown 162c4762a1bSJed Brown /* Distribute networkdm to multiple processes */ 1639566063dSJacob Faibussowitsch PetscCall(DMNetworkDistribute(&networkdm, 0)); 164c4762a1bSJed Brown 165*3ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePop()); 1669566063dSJacob Faibussowitsch PetscCall(DMNetworkGetEdgeRange(networkdm, &eStart, &eEnd)); 1679566063dSJacob Faibussowitsch PetscCall(DMNetworkGetVertexRange(networkdm, &vStart, &vEnd)); 168c4762a1bSJed Brown 169c4762a1bSJed Brown #if 0 170c4762a1bSJed Brown EDGE_Power edge; 171c4762a1bSJed Brown PetscInt key,kk,numComponents; 172c4762a1bSJed Brown VERTEX_Power bus; 173c4762a1bSJed Brown GEN gen; 174c4762a1bSJed Brown LOAD load; 175c4762a1bSJed Brown 176c4762a1bSJed Brown for (i = eStart; i < eEnd; i++) { 1779566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm,i,0,&key,(void**)&edge)); 1789566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm,i,&numComponents)); 1799566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d ncomps = %d Line %d ---- %d\n",crank,numComponents,edge->internal_i,edge->internal_j)); 180c4762a1bSJed Brown } 181c4762a1bSJed Brown 182c4762a1bSJed Brown for (i = vStart; i < vEnd; i++) { 1839566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm,i,&numComponents)); 184c4762a1bSJed Brown for (kk=0; kk < numComponents; kk++) { 1859566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm,i,kk,&key,&component)); 186c4762a1bSJed Brown if (key == 1) { 187c4762a1bSJed Brown bus = (VERTEX_Power)(component); 1889566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d ncomps = %d Bus %d\n",crank,numComponents,bus->internal_i)); 189c4762a1bSJed Brown } else if (key == 2) { 190c4762a1bSJed Brown gen = (GEN)(component); 19163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d Gen pg = %f qg = %f\n",crank,(double)gen->pg,(double)gen->qg)); 192c4762a1bSJed Brown } else if (key == 3) { 193c4762a1bSJed Brown load = (LOAD)(component); 19463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"Rank %d Load pl = %f ql = %f\n",crank,(double)load->pl,(double)load->ql)); 195c4762a1bSJed Brown } 196c4762a1bSJed Brown } 197c4762a1bSJed Brown } 198c4762a1bSJed Brown #endif 199c4762a1bSJed Brown /* Broadcast Sbase to all processors */ 2009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&User.Sbase, 1, MPIU_SCALAR, 0, PETSC_COMM_WORLD)); 201c4762a1bSJed Brown 2029566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(networkdm, &X)); 2039566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X, &F)); 204c4762a1bSJed Brown 2059566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(networkdm, &J)); 2069566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 207c4762a1bSJed Brown 2089566063dSJacob Faibussowitsch PetscCall(SetInitialValues(networkdm, X, &User)); 209c4762a1bSJed Brown 210c4762a1bSJed Brown /* HOOK UP SOLVER */ 2119566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes)); 2129566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, networkdm)); 2139566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, F, FormFunction, &User)); 2149566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, FormJacobian_Power, &User)); 2159566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes)); 216c4762a1bSJed Brown 2179566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes, NULL, X)); 2189566063dSJacob Faibussowitsch /* PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); */ 219c4762a1bSJed Brown 2209566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X)); 2219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&F)); 2229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 223c4762a1bSJed Brown 2249566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes)); 2259566063dSJacob Faibussowitsch PetscCall(DMDestroy(&networkdm)); 226c4762a1bSJed Brown } 2279566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 228b122ec5aSJacob Faibussowitsch return 0; 229c4762a1bSJed Brown } 230c4762a1bSJed Brown 231c4762a1bSJed Brown /*TEST 232c4762a1bSJed Brown 233c4762a1bSJed Brown build: 234c4762a1bSJed Brown depends: PFReadData.c pffunctions.c 235dfd57a17SPierre Jolivet requires: !complex double defined(PETSC_HAVE_ATTRIBUTEALIGNED) 236c4762a1bSJed Brown 237c4762a1bSJed Brown test: 238c4762a1bSJed Brown args: -snes_rtol 1.e-3 239c4762a1bSJed Brown localrunfiles: poweroptions case9.m 240c4762a1bSJed Brown output_file: output/power_1.out 241c4762a1bSJed Brown 242c4762a1bSJed Brown test: 243c4762a1bSJed Brown suffix: 2 244c4762a1bSJed Brown args: -snes_rtol 1.e-3 -petscpartitioner_type simple 245c4762a1bSJed Brown nsize: 4 246c4762a1bSJed Brown localrunfiles: poweroptions case9.m 247c4762a1bSJed Brown output_file: output/power_1.out 248c4762a1bSJed Brown 249c4762a1bSJed Brown TEST*/ 250