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