1*5f25b224SDuncan Campbell static char help[] = "This example demonstrates the use of DMNetwork with subnetworks for solving a coupled nonlinear \n\ 2c4762a1bSJed Brown electric power grid and water pipe problem.\n\ 3c4762a1bSJed Brown The available solver options are in the ex1options file \n\ 4c4762a1bSJed Brown and the data files are in the datafiles of subdirectories.\n\ 5c4762a1bSJed Brown Run this program: mpiexec -n <n> ./ex1 \n\\n"; 6c4762a1bSJed Brown 7*5f25b224SDuncan Campbell /* 8*5f25b224SDuncan Campbell Example: 9*5f25b224SDuncan Campbell mpiexec -n 3 ./ex1 -petscpartitioner_type parmetis -dmnetwork_view draw -dmnetwork_view_distributed draw -dmnetwork_view_rank_range 0,1,2 10*5f25b224SDuncan Campbell */ 11*5f25b224SDuncan Campbell 12c4762a1bSJed Brown #include "power/power.h" 13c4762a1bSJed Brown #include "water/water.h" 14c4762a1bSJed Brown 15c4762a1bSJed Brown typedef struct { 16c4762a1bSJed Brown UserCtx_Power appctx_power; 17c4762a1bSJed Brown AppCtx_Water appctx_water; 18c4762a1bSJed Brown PetscInt subsnes_id; /* snes solver id */ 19c4762a1bSJed Brown PetscInt it; /* iteration number */ 20c4762a1bSJed Brown Vec localXold; /* store previous solution, used by FormFunction_Dummy() */ 21c4762a1bSJed Brown } UserCtx; 22c4762a1bSJed Brown 23d71ae5a4SJacob Faibussowitsch PetscErrorCode UserMonitor(SNES snes, PetscInt its, PetscReal fnorm, void *appctx) 24d71ae5a4SJacob Faibussowitsch { 25c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 26c4762a1bSJed Brown Vec X, localXold = user->localXold; 27c4762a1bSJed Brown DM networkdm; 28c4762a1bSJed Brown PetscMPIInt rank; 29c4762a1bSJed Brown MPI_Comm comm; 30c4762a1bSJed Brown 31c4762a1bSJed Brown PetscFunctionBegin; 329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 34c4762a1bSJed Brown #if 0 35dd400576SPatrick Sanan if (rank == 0) { 36c4762a1bSJed Brown PetscInt subsnes_id = user->subsnes_id; 37c4762a1bSJed Brown if (subsnes_id == 2) { 3863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF," it %" PetscInt_FMT ", subsnes_id %" PetscInt_FMT ", fnorm %g\n",user->it,user->subsnes_id,(double)fnorm)); 39c4762a1bSJed Brown } else { 4063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF," subsnes_id %" PetscInt_FMT ", fnorm %g\n",user->subsnes_id,(double)fnorm)); 41c4762a1bSJed Brown } 42c4762a1bSJed Brown } 43c4762a1bSJed Brown #endif 449566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &X)); 459566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &networkdm)); 469566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localXold)); 479566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localXold)); 483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49c4762a1bSJed Brown } 50c4762a1bSJed Brown 51d71ae5a4SJacob Faibussowitsch PetscErrorCode FormJacobian_subPower(SNES snes, Vec X, Mat J, Mat Jpre, void *appctx) 52d71ae5a4SJacob Faibussowitsch { 53c4762a1bSJed Brown DM networkdm; 54c4762a1bSJed Brown Vec localX; 55c4762a1bSJed Brown PetscInt nv, ne, i, j, offset, nvar, row; 56c4762a1bSJed Brown const PetscInt *vtx, *edges; 57c4762a1bSJed Brown PetscBool ghostvtex; 58c4762a1bSJed Brown PetscScalar one = 1.0; 59c4762a1bSJed Brown PetscMPIInt rank; 60c4762a1bSJed Brown MPI_Comm comm; 61c4762a1bSJed Brown 62c4762a1bSJed Brown PetscFunctionBegin; 639566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &networkdm)); 649566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localX)); 65c4762a1bSJed Brown 669566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)networkdm, &comm)); 679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 68c4762a1bSJed Brown 699566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX)); 709566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX)); 71c4762a1bSJed Brown 729566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(J)); 73c4762a1bSJed Brown 74c4762a1bSJed Brown /* Power subnetwork: copied from power/FormJacobian_Power() */ 759566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 769566063dSJacob Faibussowitsch PetscCall(FormJacobian_Power_private(networkdm, localX, J, nv, ne, vtx, edges, appctx)); 77c4762a1bSJed Brown 78c4762a1bSJed Brown /* Water subnetwork: Identity */ 799566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 1, &nv, &ne, &vtx, &edges)); 80c4762a1bSJed Brown for (i = 0; i < nv; i++) { 819566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghostvtex)); 82c4762a1bSJed Brown if (ghostvtex) continue; 83c4762a1bSJed Brown 849566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVecOffset(networkdm, vtx[i], ALL_COMPONENTS, &offset)); 859566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[i], ALL_COMPONENTS, NULL, NULL, &nvar)); 86c4762a1bSJed Brown for (j = 0; j < nvar; j++) { 87c4762a1bSJed Brown row = offset + j; 889566063dSJacob Faibussowitsch PetscCall(MatSetValues(J, 1, &row, 1, &row, &one, ADD_VALUES)); 89c4762a1bSJed Brown } 90c4762a1bSJed Brown } 919566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 929566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 93c4762a1bSJed Brown 949566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localX)); 953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 96c4762a1bSJed Brown } 97c4762a1bSJed Brown 98c4762a1bSJed Brown /* Dummy equation localF(X) = localX - localXold */ 99d71ae5a4SJacob Faibussowitsch PetscErrorCode FormFunction_Dummy(DM networkdm, Vec localX, Vec localF, PetscInt nv, PetscInt ne, const PetscInt *vtx, const PetscInt *edges, void *appctx) 100d71ae5a4SJacob Faibussowitsch { 101c4762a1bSJed Brown const PetscScalar *xarr, *xoldarr; 102c4762a1bSJed Brown PetscScalar *farr; 103c4762a1bSJed Brown PetscInt i, j, offset, nvar; 104c4762a1bSJed Brown PetscBool ghostvtex; 105c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 106c4762a1bSJed Brown Vec localXold = user->localXold; 107c4762a1bSJed Brown 108c4762a1bSJed Brown PetscFunctionBegin; 1099566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localX, &xarr)); 1109566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localXold, &xoldarr)); 1119566063dSJacob Faibussowitsch PetscCall(VecGetArray(localF, &farr)); 112c4762a1bSJed Brown 113c4762a1bSJed Brown for (i = 0; i < nv; i++) { 1149566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghostvtex)); 115c4762a1bSJed Brown if (ghostvtex) continue; 116c4762a1bSJed Brown 1179566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vtx[i], ALL_COMPONENTS, &offset)); 1189566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[i], ALL_COMPONENTS, NULL, NULL, &nvar)); 119ad540459SPierre Jolivet for (j = 0; j < nvar; j++) farr[offset + j] = xarr[offset + j] - xoldarr[offset + j]; 120c4762a1bSJed Brown } 121c4762a1bSJed Brown 1229566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localX, &xarr)); 1239566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localXold, &xoldarr)); 1249566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localF, &farr)); 1253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 126c4762a1bSJed Brown } 127c4762a1bSJed Brown 128d71ae5a4SJacob Faibussowitsch PetscErrorCode FormFunction(SNES snes, Vec X, Vec F, void *appctx) 129d71ae5a4SJacob Faibussowitsch { 130c4762a1bSJed Brown DM networkdm; 131c4762a1bSJed Brown Vec localX, localF; 1322bf73ac6SHong Zhang PetscInt nv, ne, v; 133c4762a1bSJed Brown const PetscInt *vtx, *edges; 134c4762a1bSJed Brown PetscMPIInt rank; 135c4762a1bSJed Brown MPI_Comm comm; 136c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 137c4762a1bSJed Brown UserCtx_Power appctx_power = (*user).appctx_power; 1382bf73ac6SHong Zhang AppCtx_Water appctx_water = (*user).appctx_water; 139c4762a1bSJed Brown 140c4762a1bSJed Brown PetscFunctionBegin; 1419566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &networkdm)); 1429566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)networkdm, &comm)); 1439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 144c4762a1bSJed Brown 1459566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localX)); 1469566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localF)); 1479566063dSJacob Faibussowitsch PetscCall(VecSet(F, 0.0)); 1489566063dSJacob Faibussowitsch PetscCall(VecSet(localF, 0.0)); 149c4762a1bSJed Brown 1509566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX)); 1519566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX)); 152c4762a1bSJed Brown 153c4762a1bSJed Brown /* Form Function for power subnetwork */ 1549566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 155c4762a1bSJed Brown if (user->subsnes_id == 1) { /* snes_water only */ 1569566063dSJacob Faibussowitsch PetscCall(FormFunction_Dummy(networkdm, localX, localF, nv, ne, vtx, edges, user)); 157c4762a1bSJed Brown } else { 1589566063dSJacob Faibussowitsch PetscCall(FormFunction_Power(networkdm, localX, localF, nv, ne, vtx, edges, &appctx_power)); 159c4762a1bSJed Brown } 160c4762a1bSJed Brown 161c4762a1bSJed Brown /* Form Function for water subnetwork */ 1629566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 1, &nv, &ne, &vtx, &edges)); 163c4762a1bSJed Brown if (user->subsnes_id == 0) { /* snes_power only */ 1649566063dSJacob Faibussowitsch PetscCall(FormFunction_Dummy(networkdm, localX, localF, nv, ne, vtx, edges, user)); 165c4762a1bSJed Brown } else { 1669566063dSJacob Faibussowitsch PetscCall(FormFunction_Water(networkdm, localX, localF, nv, ne, vtx, edges, NULL)); 167c4762a1bSJed Brown } 168c4762a1bSJed Brown 1692bf73ac6SHong Zhang /* Illustrate how to access the coupling vertex of the subnetworks without doing anything to F yet */ 1709566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 1712bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 1722bf73ac6SHong Zhang PetscInt key, ncomp, nvar, nconnedges, k, e, keye, goffset[3]; 173c4762a1bSJed Brown void *component; 1742bf73ac6SHong Zhang const PetscInt *connedges; 175c4762a1bSJed Brown 1769566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[v], ALL_COMPONENTS, NULL, NULL, &nvar)); 1779566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, vtx[v], &ncomp)); 17863a3b9bcSJacob Faibussowitsch /* printf(" [%d] coupling vertex[%" PetscInt_FMT "]: v %" PetscInt_FMT ", ncomp %" PetscInt_FMT "; nvar %" PetscInt_FMT "\n",rank,v,vtx[v], ncomp,nvar); */ 179c4762a1bSJed Brown 1802bf73ac6SHong Zhang for (k = 0; k < ncomp; k++) { 1819566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[v], k, &key, &component, &nvar)); 1829566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVecOffset(networkdm, vtx[v], k, &goffset[k])); 183c4762a1bSJed Brown 1842bf73ac6SHong Zhang /* Verify the coupling vertex is a powernet load vertex or a water vertex */ 1852bf73ac6SHong Zhang switch (k) { 186d71ae5a4SJacob Faibussowitsch case 0: 187d71ae5a4SJacob Faibussowitsch PetscCheck(key == appctx_power.compkey_bus && nvar == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "key %" PetscInt_FMT " not a power bus vertex or nvar %" PetscInt_FMT " != 2", key, nvar); 188d71ae5a4SJacob Faibussowitsch break; 189d71ae5a4SJacob Faibussowitsch case 1: 190d71ae5a4SJacob Faibussowitsch PetscCheck(key == appctx_power.compkey_load && nvar == 0 && goffset[1] == goffset[0] + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not a power load vertex"); 191d71ae5a4SJacob Faibussowitsch break; 192d71ae5a4SJacob Faibussowitsch case 2: 193d71ae5a4SJacob Faibussowitsch PetscCheck(key == appctx_water.compkey_vtx && nvar == 1 && goffset[2] == goffset[1], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not a water vertex"); 194d71ae5a4SJacob Faibussowitsch break; 195d71ae5a4SJacob Faibussowitsch default: 196d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "k %" PetscInt_FMT " is wrong", k); 1972bf73ac6SHong Zhang } 19863a3b9bcSJacob Faibussowitsch /* printf(" [%d] coupling vertex[%" PetscInt_FMT "]: key %" PetscInt_FMT "; nvar %" PetscInt_FMT ", goffset %" PetscInt_FMT "\n",rank,v,key,nvar,goffset[k]); */ 1992bf73ac6SHong Zhang } 200c4762a1bSJed Brown 2012bf73ac6SHong Zhang /* Get its supporting edges */ 2029566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSupportingEdges(networkdm, vtx[v], &nconnedges, &connedges)); 20363a3b9bcSJacob Faibussowitsch /* printf("\n[%d] coupling vertex: nconnedges %" PetscInt_FMT "\n",rank,nconnedges); */ 204c4762a1bSJed Brown for (k = 0; k < nconnedges; k++) { 205c4762a1bSJed Brown e = connedges[k]; 2069566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, e, &ncomp)); 20763a3b9bcSJacob Faibussowitsch /* printf("\n [%d] connected edge[%" PetscInt_FMT "]=%" PetscInt_FMT " has ncomp %" PetscInt_FMT "\n",rank,k,e,ncomp); */ 2089566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, e, 0, &keye, &component, NULL)); 209ad540459SPierre Jolivet if (keye != appctx_water.compkey_edge) PetscCheck(keye == appctx_power.compkey_branch, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not a power branch"); 210c4762a1bSJed Brown } 211c4762a1bSJed Brown } 212c4762a1bSJed Brown 2139566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localX)); 214c4762a1bSJed Brown 2159566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localF, ADD_VALUES, F)); 2169566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localF, ADD_VALUES, F)); 2179566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localF)); 2182bf73ac6SHong Zhang #if 0 219dd400576SPatrick Sanan if (rank == 0) printf("F:\n"); 2209566063dSJacob Faibussowitsch PetscCall(VecView(F,PETSC_VIEWER_STDOUT_WORLD)); 2212bf73ac6SHong Zhang #endif 2223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 223c4762a1bSJed Brown } 224c4762a1bSJed Brown 225d71ae5a4SJacob Faibussowitsch PetscErrorCode SetInitialGuess(DM networkdm, Vec X, void *appctx) 226d71ae5a4SJacob Faibussowitsch { 2272bf73ac6SHong Zhang PetscInt nv, ne, i, j, ncomp, offset, key; 228c4762a1bSJed Brown const PetscInt *vtx, *edges; 229c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 230c4762a1bSJed Brown Vec localX = user->localXold; 231c4762a1bSJed Brown UserCtx_Power appctx_power = (*user).appctx_power; 2322bf73ac6SHong Zhang AppCtx_Water appctx_water = (*user).appctx_water; 2332bf73ac6SHong Zhang PetscBool ghost; 2342bf73ac6SHong Zhang PetscScalar *xarr; 2352bf73ac6SHong Zhang VERTEX_Power bus; 2362bf73ac6SHong Zhang VERTEX_Water vertex; 2372bf73ac6SHong Zhang void *component; 2382bf73ac6SHong Zhang GEN gen; 239c4762a1bSJed Brown 240c4762a1bSJed Brown PetscFunctionBegin; 2419566063dSJacob Faibussowitsch PetscCall(VecSet(X, 0.0)); 2429566063dSJacob Faibussowitsch PetscCall(VecSet(localX, 0.0)); 243c4762a1bSJed Brown 244c4762a1bSJed Brown /* Set initial guess for power subnetwork */ 2459566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 2469566063dSJacob Faibussowitsch PetscCall(SetInitialGuess_Power(networkdm, localX, nv, ne, vtx, edges, &appctx_power)); 247c4762a1bSJed Brown 248c4762a1bSJed Brown /* Set initial guess for water subnetwork */ 2499566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 1, &nv, &ne, &vtx, &edges)); 2509566063dSJacob Faibussowitsch PetscCall(SetInitialGuess_Water(networkdm, localX, nv, ne, vtx, edges, NULL)); 251c4762a1bSJed Brown 2522bf73ac6SHong Zhang /* Set initial guess at the coupling vertex */ 2539566063dSJacob Faibussowitsch PetscCall(VecGetArray(localX, &xarr)); 2549566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 2552bf73ac6SHong Zhang for (i = 0; i < nv; i++) { 2569566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghost)); 2572bf73ac6SHong Zhang if (ghost) continue; 2582bf73ac6SHong Zhang 2599566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, vtx[i], &ncomp)); 2602bf73ac6SHong Zhang for (j = 0; j < ncomp; j++) { 2619566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vtx[i], j, &offset)); 2629566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[i], j, &key, (void **)&component, NULL)); 2632bf73ac6SHong Zhang if (key == appctx_power.compkey_bus) { 2642bf73ac6SHong Zhang bus = (VERTEX_Power)(component); 2652bf73ac6SHong Zhang xarr[offset] = bus->va * PETSC_PI / 180.0; 2662bf73ac6SHong Zhang xarr[offset + 1] = bus->vm; 2672bf73ac6SHong Zhang } else if (key == appctx_power.compkey_gen) { 2682bf73ac6SHong Zhang gen = (GEN)(component); 2692bf73ac6SHong Zhang if (!gen->status) continue; 2702bf73ac6SHong Zhang xarr[offset + 1] = gen->vs; 2712bf73ac6SHong Zhang } else if (key == appctx_water.compkey_vtx) { 2722bf73ac6SHong Zhang vertex = (VERTEX_Water)(component); 2732bf73ac6SHong Zhang if (vertex->type == VERTEX_TYPE_JUNCTION) { 2742bf73ac6SHong Zhang xarr[offset] = 100; 2752bf73ac6SHong Zhang } else if (vertex->type == VERTEX_TYPE_RESERVOIR) { 2762bf73ac6SHong Zhang xarr[offset] = vertex->res.head; 2772bf73ac6SHong Zhang } else { 2782bf73ac6SHong Zhang xarr[offset] = vertex->tank.initlvl + vertex->tank.elev; 279c4762a1bSJed Brown } 2802bf73ac6SHong Zhang } 2812bf73ac6SHong Zhang } 2822bf73ac6SHong Zhang } 2839566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localX, &xarr)); 284c4762a1bSJed Brown 2859566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localX, ADD_VALUES, X)); 2869566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localX, ADD_VALUES, X)); 2873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 288c4762a1bSJed Brown } 289c4762a1bSJed Brown 290cc13d412SHong Zhang /* Set coordinates */ 291cc13d412SHong Zhang static PetscErrorCode CoordinateVecSetUp(DM dm, Vec coords) 292cc13d412SHong Zhang { 293cc13d412SHong Zhang DM dmclone; 294cc13d412SHong Zhang PetscInt i, gidx, offset, v, nv, Nsubnet; 295cc13d412SHong Zhang const PetscInt *vtx; 296cc13d412SHong Zhang PetscScalar *carray; 297cc13d412SHong Zhang 298cc13d412SHong Zhang PetscFunctionBeginUser; 299cc13d412SHong Zhang PetscCall(DMGetCoordinateDM(dm, &dmclone)); 300cc13d412SHong Zhang PetscCall(VecGetArrayWrite(coords, &carray)); 301cc13d412SHong Zhang PetscCall(DMNetworkGetNumSubNetworks(dm, NULL, &Nsubnet)); 302cc13d412SHong Zhang for (i = 0; i < Nsubnet; i++) { 303cc13d412SHong Zhang PetscCall(DMNetworkGetSubnetwork(dm, i, &nv, NULL, &vtx, NULL)); 304cc13d412SHong Zhang for (v = 0; v < nv; v++) { 305cc13d412SHong Zhang PetscCall(DMNetworkGetGlobalVertexIndex(dm, vtx[v], &gidx)); 306cc13d412SHong Zhang PetscCall(DMNetworkGetLocalVecOffset(dmclone, vtx[v], 0, &offset)); 307cc13d412SHong Zhang switch (gidx) { 308cc13d412SHong Zhang case 0: 309cc13d412SHong Zhang carray[offset] = -1.0; 310cc13d412SHong Zhang carray[offset + 1] = -1.0; 311cc13d412SHong Zhang break; 312cc13d412SHong Zhang case 1: 313cc13d412SHong Zhang carray[offset] = -2.0; 314cc13d412SHong Zhang carray[offset + 1] = 2.0; 315cc13d412SHong Zhang break; 316cc13d412SHong Zhang case 2: 317cc13d412SHong Zhang carray[offset] = 0.0; 318cc13d412SHong Zhang carray[offset + 1] = 2.0; 319cc13d412SHong Zhang break; 320cc13d412SHong Zhang case 3: 321cc13d412SHong Zhang carray[offset] = -1.0; 322cc13d412SHong Zhang carray[offset + 1] = 0.0; 323cc13d412SHong Zhang break; 324cc13d412SHong Zhang case 4: 325cc13d412SHong Zhang carray[offset] = 0.0; 326cc13d412SHong Zhang carray[offset + 1] = 0.0; 327cc13d412SHong Zhang break; 328cc13d412SHong Zhang case 5: 329cc13d412SHong Zhang carray[offset] = 0.0; 330cc13d412SHong Zhang carray[offset + 1] = 1.0; 331cc13d412SHong Zhang break; 332cc13d412SHong Zhang case 6: 333cc13d412SHong Zhang carray[offset] = -1.0; 334cc13d412SHong Zhang carray[offset + 1] = 1.0; 335cc13d412SHong Zhang break; 336cc13d412SHong Zhang case 7: 337cc13d412SHong Zhang carray[offset] = -2.0; 338cc13d412SHong Zhang carray[offset + 1] = 1.0; 339cc13d412SHong Zhang break; 340cc13d412SHong Zhang case 8: 341cc13d412SHong Zhang carray[offset] = -2.0; 342cc13d412SHong Zhang carray[offset + 1] = 0.0; 343cc13d412SHong Zhang break; 344cc13d412SHong Zhang case 9: 345cc13d412SHong Zhang carray[offset] = 1.0; 346cc13d412SHong Zhang carray[offset + 1] = 0.0; 347cc13d412SHong Zhang break; 348cc13d412SHong Zhang case 10: 349cc13d412SHong Zhang carray[offset] = 1.0; 350cc13d412SHong Zhang carray[offset + 1] = -1.0; 351cc13d412SHong Zhang break; 352cc13d412SHong Zhang case 11: 353cc13d412SHong Zhang carray[offset] = 2.0; 354cc13d412SHong Zhang carray[offset + 1] = -1.0; 355cc13d412SHong Zhang break; 356cc13d412SHong Zhang case 12: 357cc13d412SHong Zhang carray[offset] = 2.0; 358cc13d412SHong Zhang carray[offset + 1] = 0.0; 359cc13d412SHong Zhang break; 360cc13d412SHong Zhang case 13: 361cc13d412SHong Zhang carray[offset] = 0.0; 362cc13d412SHong Zhang carray[offset + 1] = -1.0; 363cc13d412SHong Zhang break; 364cc13d412SHong Zhang case 14: 365cc13d412SHong Zhang carray[offset] = 2.0; 366cc13d412SHong Zhang carray[offset + 1] = 1.0; 367cc13d412SHong Zhang break; 368cc13d412SHong Zhang default: 369cc13d412SHong Zhang PetscCheck(gidx < 15 && gidx > -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "gidx %" PetscInt_FMT "must between 0 and 14", gidx); 370cc13d412SHong Zhang } 371cc13d412SHong Zhang } 372cc13d412SHong Zhang } 373cc13d412SHong Zhang PetscCall(VecRestoreArrayWrite(coords, &carray)); 374cc13d412SHong Zhang PetscFunctionReturn(PETSC_SUCCESS); 375cc13d412SHong Zhang } 376cc13d412SHong Zhang 377cc13d412SHong Zhang static PetscErrorCode CoordinatePrint(DM dm) 378cc13d412SHong Zhang { 379cc13d412SHong Zhang DM dmclone; 380cc13d412SHong Zhang PetscInt cdim, v, off, vglobal, vStart, vEnd; 381cc13d412SHong Zhang const PetscScalar *carray; 382cc13d412SHong Zhang Vec coords; 383cc13d412SHong Zhang MPI_Comm comm; 384cc13d412SHong Zhang PetscMPIInt rank; 385cc13d412SHong Zhang 386cc13d412SHong Zhang PetscFunctionBegin; 387cc13d412SHong Zhang PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 388cc13d412SHong Zhang PetscCallMPI(MPI_Comm_rank(comm, &rank)); 389cc13d412SHong Zhang 390cc13d412SHong Zhang PetscCall(DMGetCoordinateDM(dm, &dmclone)); 391cc13d412SHong Zhang PetscCall(DMNetworkGetVertexRange(dm, &vStart, &vEnd)); 392cc13d412SHong Zhang PetscCall(DMGetCoordinatesLocal(dm, &coords)); 393cc13d412SHong Zhang 394cc13d412SHong Zhang PetscCall(DMGetCoordinateDim(dm, &cdim)); 395cc13d412SHong Zhang PetscCall(VecGetArrayRead(coords, &carray)); 396cc13d412SHong Zhang 397cc13d412SHong Zhang PetscCall(PetscPrintf(MPI_COMM_WORLD, "\nCoordinatePrint, cdim %" PetscInt_FMT ":\n", cdim)); 398cc13d412SHong Zhang PetscCall(PetscSynchronizedPrintf(MPI_COMM_WORLD, "[%i]\n", rank)); 399cc13d412SHong Zhang for (v = vStart; v < vEnd; v++) { 400cc13d412SHong Zhang PetscCall(DMNetworkGetLocalVecOffset(dmclone, v, 0, &off)); 401cc13d412SHong Zhang PetscCall(DMNetworkGetGlobalVertexIndex(dmclone, v, &vglobal)); 402cc13d412SHong Zhang switch (cdim) { 403cc13d412SHong Zhang case 2: 404cc13d412SHong Zhang PetscCall(PetscSynchronizedPrintf(MPI_COMM_WORLD, "Vertex: %" PetscInt_FMT ", x = %f y = %f \n", vglobal, (double)PetscRealPart(carray[off]), (double)PetscRealPart(carray[off + 1]))); 405cc13d412SHong Zhang break; 406cc13d412SHong Zhang default: 407cc13d412SHong Zhang PetscCheck(cdim == 2, MPI_COMM_WORLD, PETSC_ERR_SUP, "Only supports Network embedding dimension of 2, not supplied %" PetscInt_FMT, cdim); 408cc13d412SHong Zhang break; 409cc13d412SHong Zhang } 410cc13d412SHong Zhang } 411cc13d412SHong Zhang PetscCall(PetscSynchronizedFlush(MPI_COMM_WORLD, NULL)); 412cc13d412SHong Zhang PetscCall(VecRestoreArrayRead(coords, &carray)); 413cc13d412SHong Zhang PetscFunctionReturn(PETSC_SUCCESS); 414cc13d412SHong Zhang } 415cc13d412SHong Zhang 416d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 417d71ae5a4SJacob Faibussowitsch { 418cc13d412SHong Zhang DM networkdm, dmclone; 419d5c9c0c4SHong Zhang PetscMPIInt rank, size; 4202bf73ac6SHong Zhang PetscInt Nsubnet = 2, numVertices[2], numEdges[2], i, j, nv, ne, it_max = 10; 421cc13d412SHong Zhang PetscInt vStart, vEnd, compkey; 422c4762a1bSJed Brown const PetscInt *vtx, *edges; 423cc13d412SHong Zhang Vec X, F, coords; 424c4762a1bSJed Brown SNES snes, snes_power, snes_water; 425c4762a1bSJed Brown Mat Jac; 426cc13d412SHong Zhang PetscBool ghost, viewJ = PETSC_FALSE, viewX = PETSC_FALSE, test = PETSC_FALSE, distribute = PETSC_TRUE, flg, printCoord = PETSC_FALSE, viewCSV = PETSC_FALSE; 427c4762a1bSJed Brown UserCtx user; 428c4762a1bSJed Brown SNESConvergedReason reason; 4294279555eSSatish Balay #if defined(PETSC_USE_LOG) 4304279555eSSatish Balay PetscLogStage stage[4]; 4314279555eSSatish Balay #endif 432c4762a1bSJed Brown 433c4762a1bSJed Brown /* Power subnetwork */ 434c4762a1bSJed Brown UserCtx_Power *appctx_power = &user.appctx_power; 435c4762a1bSJed Brown char pfdata_file[PETSC_MAX_PATH_LEN] = "power/case9.m"; 436c4762a1bSJed Brown PFDATA *pfdata = NULL; 4372bf73ac6SHong Zhang PetscInt genj, loadj, *edgelist_power = NULL, power_netnum; 438c4762a1bSJed Brown PetscScalar Sbase = 0.0; 439c4762a1bSJed Brown 440c4762a1bSJed Brown /* Water subnetwork */ 441c4762a1bSJed Brown AppCtx_Water *appctx_water = &user.appctx_water; 442c4762a1bSJed Brown WATERDATA *waterdata = NULL; 443c4762a1bSJed Brown char waterdata_file[PETSC_MAX_PATH_LEN] = "water/sample1.inp"; 4442bf73ac6SHong Zhang PetscInt *edgelist_water = NULL, water_netnum; 445c4762a1bSJed Brown 4462bf73ac6SHong Zhang /* Shared vertices between subnetworks */ 4472bf73ac6SHong Zhang PetscInt power_svtx, water_svtx; 448c4762a1bSJed Brown 449327415f7SBarry Smith PetscFunctionBeginUser; 4509566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, "ex1options", help)); 4519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 4529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); 453c4762a1bSJed Brown 454c4762a1bSJed Brown /* (1) Read Data - Only rank 0 reads the data */ 4559566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Read Data", &stage[0])); 4569566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[0])); 457c4762a1bSJed Brown 4582bf73ac6SHong Zhang for (i = 0; i < Nsubnet; i++) { 459c4762a1bSJed Brown numVertices[i] = 0; 460c4762a1bSJed Brown numEdges[i] = 0; 461c4762a1bSJed Brown } 462c4762a1bSJed Brown 4632bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE FIRST SUBNETWORK: Electric Power Grid */ 4642bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 4659566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-pfdata", pfdata_file, PETSC_MAX_PATH_LEN - 1, NULL)); 4669566063dSJacob Faibussowitsch PetscCall(PetscNew(&pfdata)); 4679566063dSJacob Faibussowitsch PetscCall(PFReadMatPowerData(pfdata, pfdata_file)); 46848a46eb9SPierre Jolivet if (rank == 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, "Power network: nb = %" PetscInt_FMT ", ngen = %" PetscInt_FMT ", nload = %" PetscInt_FMT ", nbranch = %" PetscInt_FMT "\n", pfdata->nbus, pfdata->ngen, pfdata->nload, pfdata->nbranch)); 469c4762a1bSJed Brown Sbase = pfdata->sbase; 4702bf73ac6SHong Zhang if (rank == 0) { /* proc[0] will create Electric Power Grid */ 471c4762a1bSJed Brown numEdges[0] = pfdata->nbranch; 472c4762a1bSJed Brown numVertices[0] = pfdata->nbus; 473c4762a1bSJed Brown 4749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * numEdges[0], &edgelist_power)); 4759566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Power(pfdata, edgelist_power)); 476c4762a1bSJed Brown } 477c4762a1bSJed Brown /* Broadcast power Sbase to all processors */ 4789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&Sbase, 1, MPIU_SCALAR, 0, PETSC_COMM_WORLD)); 479c4762a1bSJed Brown appctx_power->Sbase = Sbase; 480c4762a1bSJed Brown appctx_power->jac_error = PETSC_FALSE; 481c4762a1bSJed Brown /* If external option activated. Introduce error in jacobian */ 4829566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-jac_error", &appctx_power->jac_error)); 483c4762a1bSJed Brown 4842bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE SECOND SUBNETWORK: Water */ 4852bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 4869566063dSJacob Faibussowitsch PetscCall(PetscNew(&waterdata)); 4879566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-waterdata", waterdata_file, PETSC_MAX_PATH_LEN - 1, NULL)); 4889566063dSJacob Faibussowitsch PetscCall(WaterReadData(waterdata, waterdata_file)); 4892bf73ac6SHong Zhang if (size == 1 || (size > 1 && rank == 1)) { 4909566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(2 * waterdata->nedge, &edgelist_water)); 4919566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Water(waterdata, edgelist_water)); 492c4762a1bSJed Brown numEdges[1] = waterdata->nedge; 493c4762a1bSJed Brown numVertices[1] = waterdata->nvertex; 494c4762a1bSJed Brown } 4953ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePop()); 496c4762a1bSJed Brown 4972bf73ac6SHong Zhang /* (2) Create a network consist of two subnetworks */ 4989566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Net Setup", &stage[1])); 4999566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[1])); 500c4762a1bSJed Brown 501cc13d412SHong Zhang PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewCSV", &viewCSV, NULL)); 502cc13d412SHong Zhang PetscCall(PetscOptionsGetBool(NULL, NULL, "-printCoord", &printCoord, NULL)); 5039566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test", &test, NULL)); 5049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-distribute", &distribute, NULL)); 505c4762a1bSJed Brown 506c4762a1bSJed Brown /* Create an empty network object */ 5079566063dSJacob Faibussowitsch PetscCall(DMNetworkCreate(PETSC_COMM_WORLD, &networkdm)); 508c4762a1bSJed Brown 509c4762a1bSJed Brown /* Register the components in the network */ 5109566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "branchstruct", sizeof(struct _p_EDGE_Power), &appctx_power->compkey_branch)); 5119566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "busstruct", sizeof(struct _p_VERTEX_Power), &appctx_power->compkey_bus)); 5129566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "genstruct", sizeof(struct _p_GEN), &appctx_power->compkey_gen)); 5139566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "loadstruct", sizeof(struct _p_LOAD), &appctx_power->compkey_load)); 514c4762a1bSJed Brown 5159566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "edge_water", sizeof(struct _p_EDGE_Water), &appctx_water->compkey_edge)); 5169566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "vertex_water", sizeof(struct _p_VERTEX_Water), &appctx_water->compkey_vtx)); 517cc13d412SHong Zhang 51863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[%d] Total local nvertices %" PetscInt_FMT " + %" PetscInt_FMT " = %" PetscInt_FMT ", nedges %" PetscInt_FMT " + %" PetscInt_FMT " = %" PetscInt_FMT "\n", rank, numVertices[0], numVertices[1], numVertices[0] + numVertices[1], numEdges[0], numEdges[1], numEdges[0] + numEdges[1])); 5199566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT)); 520c4762a1bSJed Brown 5219566063dSJacob Faibussowitsch PetscCall(DMNetworkSetNumSubNetworks(networkdm, PETSC_DECIDE, Nsubnet)); 5229566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, "power", numEdges[0], edgelist_power, &power_netnum)); 5239566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, "water", numEdges[1], edgelist_water, &water_netnum)); 524c4762a1bSJed Brown 5252bf73ac6SHong Zhang /* vertex subnet[0].4 shares with vertex subnet[1].0 */ 5269371c9d4SSatish Balay power_svtx = 4; 5279371c9d4SSatish Balay water_svtx = 0; 5289566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSharedVertices(networkdm, power_netnum, water_netnum, 1, &power_svtx, &water_svtx)); 529c4762a1bSJed Brown 530c4762a1bSJed Brown /* Set up the network layout */ 5319566063dSJacob Faibussowitsch PetscCall(DMNetworkLayoutSetUp(networkdm)); 532c4762a1bSJed Brown 533c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE POWER SUBNETWORK */ 5349371c9d4SSatish Balay genj = 0; 5359371c9d4SSatish Balay loadj = 0; 5369566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, power_netnum, &nv, &ne, &vtx, &edges)); 5372bf73ac6SHong Zhang 53848a46eb9SPierre Jolivet for (i = 0; i < ne; i++) PetscCall(DMNetworkAddComponent(networkdm, edges[i], appctx_power->compkey_branch, &pfdata->branch[i], 0)); 539c4762a1bSJed Brown 540c4762a1bSJed Brown for (i = 0; i < nv; i++) { 5419566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &flg)); 5422bf73ac6SHong Zhang if (flg) continue; 5432bf73ac6SHong Zhang 5449566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_bus, &pfdata->bus[i], 2)); 545c4762a1bSJed Brown if (pfdata->bus[i].ngen) { 54648a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i].ngen; j++) PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_gen, &pfdata->gen[genj++], 0)); 547c4762a1bSJed Brown } 548c4762a1bSJed Brown if (pfdata->bus[i].nload) { 54948a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i].nload; j++) PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_load, &pfdata->load[loadj++], 0)); 550c4762a1bSJed Brown } 551c4762a1bSJed Brown } 552c4762a1bSJed Brown 553c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE WATER SUBNETWORK */ 5549566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, water_netnum, &nv, &ne, &vtx, &edges)); 55548a46eb9SPierre Jolivet for (i = 0; i < ne; i++) PetscCall(DMNetworkAddComponent(networkdm, edges[i], appctx_water->compkey_edge, &waterdata->edge[i], 0)); 556c4762a1bSJed Brown 557c4762a1bSJed Brown for (i = 0; i < nv; i++) { 5589566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &flg)); 5592bf73ac6SHong Zhang if (flg) continue; 5602bf73ac6SHong Zhang 5619566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_water->compkey_vtx, &waterdata->vertex[i], 1)); 562c4762a1bSJed Brown } 5632bf73ac6SHong Zhang 564eac198afSGetnet /* ADD VARIABLES AND COMPONENTS AT THE SHARED VERTEX: net[0].4 coupls with net[1].0 -- owning and all ghost ranks of the vertex do this */ 5659566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 5662bf73ac6SHong Zhang for (i = 0; i < nv; i++) { 5672bf73ac6SHong Zhang /* power */ 5689566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_bus, &pfdata->bus[4], 2)); 5692bf73ac6SHong Zhang /* bus[4] is a load, add its component */ 5709566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_load, &pfdata->load[0], 0)); 5712bf73ac6SHong Zhang 5722bf73ac6SHong Zhang /* water */ 5739566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_water->compkey_vtx, &waterdata->vertex[0], 1)); 574c4762a1bSJed Brown } 575c4762a1bSJed Brown 576cc13d412SHong Zhang /* Set coordinates for visualization */ 577cc13d412SHong Zhang PetscCall(DMSetCoordinateDim(networkdm, 2)); 578cc13d412SHong Zhang PetscCall(DMGetCoordinateDM(networkdm, &dmclone)); 579cc13d412SHong Zhang PetscCall(DMNetworkGetVertexRange(dmclone, &vStart, &vEnd)); 580cc13d412SHong Zhang PetscCall(DMNetworkRegisterComponent(dmclone, "coordinates", 0, &compkey)); 581aa624791SPierre Jolivet for (i = vStart; i < vEnd; i++) PetscCall(DMNetworkAddComponent(dmclone, i, compkey, NULL, 2)); 582cc13d412SHong Zhang PetscCall(DMNetworkFinalizeComponents(dmclone)); 583cc13d412SHong Zhang 584cc13d412SHong Zhang PetscCall(DMCreateLocalVector(dmclone, &coords)); 585cc13d412SHong Zhang PetscCall(DMSetCoordinatesLocal(networkdm, coords)); /* set/get coords to/from networkdm */ 586cc13d412SHong Zhang PetscCall(CoordinateVecSetUp(networkdm, coords)); 587cc13d412SHong Zhang if (printCoord) PetscCall(CoordinatePrint(networkdm)); 588cc13d412SHong Zhang 589c4762a1bSJed Brown /* Set up DM for use */ 590*5f25b224SDuncan Campbell PetscCall(DMSetFromOptions(networkdm)); 5919566063dSJacob Faibussowitsch PetscCall(DMSetUp(networkdm)); 592c4762a1bSJed Brown 593c4762a1bSJed Brown /* Free user objects */ 5949566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_power)); 5959566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->bus)); 5969566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->gen)); 5979566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->branch)); 5989566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->load)); 5999566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata)); 6002bf73ac6SHong Zhang 6019566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_water)); 6029566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->vertex)); 6039566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->edge)); 6049566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata)); 605c4762a1bSJed Brown 606d5c9c0c4SHong Zhang /* Re-distribute networkdm to multiple processes for better job balance */ 607cc13d412SHong Zhang if (distribute) { 6089566063dSJacob Faibussowitsch PetscCall(DMNetworkDistribute(&networkdm, 0)); 609cc13d412SHong Zhang 610cc13d412SHong Zhang if (printCoord) PetscCall(CoordinatePrint(networkdm)); 611cc13d412SHong Zhang if (viewCSV) { /* CSV View of network with coordinates */ 612cc13d412SHong Zhang PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_CSV)); 6139566063dSJacob Faibussowitsch PetscCall(DMView(networkdm, PETSC_VIEWER_STDOUT_WORLD)); 614cc13d412SHong Zhang PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD)); 615c4762a1bSJed Brown } 616d5c9c0c4SHong Zhang } 617cc13d412SHong Zhang PetscCall(VecDestroy(&coords)); 618c4762a1bSJed Brown 6192bf73ac6SHong Zhang /* Test DMNetworkGetSubnetwork() and DMNetworkGetSubnetworkSharedVertices() */ 620c4762a1bSJed Brown if (test) { 6212bf73ac6SHong Zhang PetscInt v, gidx; 6229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 6232bf73ac6SHong Zhang for (i = 0; i < Nsubnet; i++) { 6249566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, i, &nv, &ne, &vtx, &edges)); 62563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] After distribute, subnet[%" PetscInt_FMT "] ne %" PetscInt_FMT ", nv %" PetscInt_FMT "\n", rank, i, ne, nv)); 6269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 627c4762a1bSJed Brown 6282bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 6299566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[v], &ghost)); 6309566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm, vtx[v], &gidx)); 63163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] subnet[%" PetscInt_FMT "] v %" PetscInt_FMT " %" PetscInt_FMT "; ghost %d\n", rank, i, vtx[v], gidx, ghost)); 632c4762a1bSJed Brown } 6339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 634c4762a1bSJed Brown } 6359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 6362bf73ac6SHong Zhang 6379566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 63863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] After distribute, num of shared vertices nsv = %" PetscInt_FMT "\n", rank, nv)); 6392bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 6409566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm, vtx[v], &gidx)); 64163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] sv %" PetscInt_FMT ", gidx=%" PetscInt_FMT "\n", rank, vtx[v], gidx)); 6422bf73ac6SHong Zhang } 6439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 644c4762a1bSJed Brown } 645c4762a1bSJed Brown 6462bf73ac6SHong Zhang /* Create solution vector X */ 6479566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(networkdm, &X)); 6489566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X, &F)); 6499566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &user.localXold)); 6503ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePop()); 651c4762a1bSJed Brown 652c4762a1bSJed Brown /* (3) Setup Solvers */ 6539566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewJ", &viewJ, NULL)); 6549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewX", &viewX, NULL)); 655c4762a1bSJed Brown 6569566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Setup", &stage[2])); 6579566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[2])); 658c4762a1bSJed Brown 6599566063dSJacob Faibussowitsch PetscCall(SetInitialGuess(networkdm, X, &user)); 660c4762a1bSJed Brown 661c4762a1bSJed Brown /* Create coupled snes */ 6629566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_coupled setup ......\n")); 6632bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 6649566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes)); 6659566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, networkdm)); 6669566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes, "coupled_")); 6679566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, F, FormFunction, &user)); 6689566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, UserMonitor, &user, NULL)); 6699566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes)); 670c4762a1bSJed Brown 671c4762a1bSJed Brown if (viewJ) { 672c4762a1bSJed Brown /* View Jac structure */ 6739566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &Jac, NULL, NULL, NULL)); 6749566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 675c4762a1bSJed Brown } 676c4762a1bSJed Brown 677c4762a1bSJed Brown if (viewX) { 6789566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Solution:\n")); 6799566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 680c4762a1bSJed Brown } 681c4762a1bSJed Brown 682c4762a1bSJed Brown if (viewJ) { 683c4762a1bSJed Brown /* View assembled Jac */ 6849566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 685c4762a1bSJed Brown } 686c4762a1bSJed Brown 687c4762a1bSJed Brown /* Create snes_power */ 6889566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_power setup ......\n")); 689c4762a1bSJed Brown 690c4762a1bSJed Brown user.subsnes_id = 0; 6919566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes_power)); 6929566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_power, networkdm)); 6939566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_power, "power_")); 6949566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_power, F, FormFunction, &user)); 6959566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_power, UserMonitor, &user, NULL)); 696c4762a1bSJed Brown 697c4762a1bSJed Brown /* Use user-provide Jacobian */ 6989566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(networkdm, &Jac)); 6999566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes_power, Jac, Jac, FormJacobian_subPower, &user)); 7009566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_power)); 701c4762a1bSJed Brown 702c4762a1bSJed Brown if (viewX) { 7039566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Power Solution:\n")); 7049566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 705c4762a1bSJed Brown } 706c4762a1bSJed Brown if (viewJ) { 7079566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Power Jac:\n")); 7089566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes_power, &Jac, NULL, NULL, NULL)); 7099566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 7109566063dSJacob Faibussowitsch /* PetscCall(MatView(Jac,PETSC_VIEWER_STDOUT_WORLD)); */ 711c4762a1bSJed Brown } 712c4762a1bSJed Brown 713c4762a1bSJed Brown /* Create snes_water */ 7149566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_water setup......\n")); 715c4762a1bSJed Brown 716c4762a1bSJed Brown user.subsnes_id = 1; 7179566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes_water)); 7189566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_water, networkdm)); 7199566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_water, "water_")); 7209566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_water, F, FormFunction, &user)); 7219566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_water, UserMonitor, &user, NULL)); 7229566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_water)); 723c4762a1bSJed Brown 724c4762a1bSJed Brown if (viewX) { 7259566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Water Solution:\n")); 7269566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 727c4762a1bSJed Brown } 7289566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 729c4762a1bSJed Brown 730c4762a1bSJed Brown /* (4) Solve */ 7319566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Solve", &stage[3])); 7329566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[3])); 733c4762a1bSJed Brown user.it = 0; 734c4762a1bSJed Brown reason = SNES_DIVERGED_DTOL; 735c4762a1bSJed Brown while (user.it < it_max && (PetscInt)reason < 0) { 736c4762a1bSJed Brown #if 0 737c4762a1bSJed Brown user.subsnes_id = 0; 7389566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_power,NULL,X)); 739c4762a1bSJed Brown 740c4762a1bSJed Brown user.subsnes_id = 1; 7419566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_water,NULL,X)); 742c4762a1bSJed Brown #endif 7432bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 7449566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes, NULL, X)); 745c4762a1bSJed Brown 7469566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(snes, &reason)); 747c4762a1bSJed Brown user.it++; 748c4762a1bSJed Brown } 74963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Coupled_SNES converged in %" PetscInt_FMT " iterations\n", user.it)); 750c4762a1bSJed Brown if (viewX) { 7519566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Final Solution:\n")); 7529566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 753c4762a1bSJed Brown } 7549566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 755c4762a1bSJed Brown 756c4762a1bSJed Brown /* Free objects */ 757c4762a1bSJed Brown /* -------------*/ 7589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X)); 7599566063dSJacob Faibussowitsch PetscCall(VecDestroy(&F)); 7609566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &user.localXold)); 761c4762a1bSJed Brown 7629566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes)); 7639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Jac)); 7649566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_power)); 7659566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_water)); 766c4762a1bSJed Brown 7679566063dSJacob Faibussowitsch PetscCall(DMDestroy(&networkdm)); 7689566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 769b122ec5aSJacob Faibussowitsch return 0; 770c4762a1bSJed Brown } 771c4762a1bSJed Brown 772c4762a1bSJed Brown /*TEST 773c4762a1bSJed Brown 774c4762a1bSJed Brown build: 775dfd57a17SPierre Jolivet requires: !complex double defined(PETSC_HAVE_ATTRIBUTEALIGNED) 776c4762a1bSJed Brown depends: power/PFReadData.c power/pffunctions.c water/waterreaddata.c water/waterfunctions.c 777c4762a1bSJed Brown 778c4762a1bSJed Brown test: 779cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -dmnetwork_view 780c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 781c4762a1bSJed Brown output_file: output/ex1.out 782c4762a1bSJed Brown 783c4762a1bSJed Brown test: 784c4762a1bSJed Brown suffix: 2 785c4762a1bSJed Brown nsize: 3 7862bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type parmetis 787c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 788d5c9c0c4SHong Zhang output_file: output/ex1_2.out 7892bf73ac6SHong Zhang requires: parmetis 7902bf73ac6SHong Zhang 791cc13d412SHong Zhang test: 792cc13d412SHong Zhang suffix: 3 793cc13d412SHong Zhang nsize: 3 794cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -distribute false 795cc13d412SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 796cc13d412SHong Zhang output_file: output/ex1_2.out 797d5c9c0c4SHong Zhang 798d5c9c0c4SHong Zhang test: 7992bf73ac6SHong Zhang suffix: 4 8002bf73ac6SHong Zhang nsize: 4 801cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type simple -dmnetwork_view -dmnetwork_view_distributed 802d5c9c0c4SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 8032bf73ac6SHong Zhang output_file: output/ex1_4.out 804c4762a1bSJed Brown 805cc13d412SHong Zhang test: 806cc13d412SHong Zhang suffix: 5 807cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -viewCSV 808cc13d412SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 809cc13d412SHong Zhang output_file: output/ex1_5.out 810cc13d412SHong Zhang 811cc13d412SHong Zhang test: 812cc13d412SHong Zhang suffix: 6 813cc13d412SHong Zhang nsize: 3 814cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type parmetis -dmnetwork_view_distributed draw:null 815cc13d412SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 816cc13d412SHong Zhang output_file: output/ex1_2.out 817cc13d412SHong Zhang requires: parmetis 818cc13d412SHong Zhang 819c4762a1bSJed Brown TEST*/ 820