1c4762a1bSJed Brown static char help[] = "This example demonstrates the use of DMNetwork interface 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 This example shows the use of subnetwork feature in DMNetwork. \n\ 6c4762a1bSJed Brown Run this program: mpiexec -n <n> ./ex1 \n\\n"; 7c4762a1bSJed Brown 8c4762a1bSJed Brown #include "power/power.h" 9c4762a1bSJed Brown #include "water/water.h" 10c4762a1bSJed Brown 11c4762a1bSJed Brown typedef struct { 12c4762a1bSJed Brown UserCtx_Power appctx_power; 13c4762a1bSJed Brown AppCtx_Water appctx_water; 14c4762a1bSJed Brown PetscInt subsnes_id; /* snes solver id */ 15c4762a1bSJed Brown PetscInt it; /* iteration number */ 16c4762a1bSJed Brown Vec localXold; /* store previous solution, used by FormFunction_Dummy() */ 17c4762a1bSJed Brown } UserCtx; 18c4762a1bSJed Brown 19d71ae5a4SJacob Faibussowitsch PetscErrorCode UserMonitor(SNES snes, PetscInt its, PetscReal fnorm, void *appctx) 20d71ae5a4SJacob Faibussowitsch { 21c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 22c4762a1bSJed Brown Vec X, localXold = user->localXold; 23c4762a1bSJed Brown DM networkdm; 24c4762a1bSJed Brown PetscMPIInt rank; 25c4762a1bSJed Brown MPI_Comm comm; 26c4762a1bSJed Brown 27c4762a1bSJed Brown PetscFunctionBegin; 289566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 30c4762a1bSJed Brown #if 0 31dd400576SPatrick Sanan if (rank == 0) { 32c4762a1bSJed Brown PetscInt subsnes_id = user->subsnes_id; 33c4762a1bSJed Brown if (subsnes_id == 2) { 3463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF," it %" PetscInt_FMT ", subsnes_id %" PetscInt_FMT ", fnorm %g\n",user->it,user->subsnes_id,(double)fnorm)); 35c4762a1bSJed Brown } else { 3663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF," subsnes_id %" PetscInt_FMT ", fnorm %g\n",user->subsnes_id,(double)fnorm)); 37c4762a1bSJed Brown } 38c4762a1bSJed Brown } 39c4762a1bSJed Brown #endif 409566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &X)); 419566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &networkdm)); 429566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localXold)); 439566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localXold)); 443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45c4762a1bSJed Brown } 46c4762a1bSJed Brown 47d71ae5a4SJacob Faibussowitsch PetscErrorCode FormJacobian_subPower(SNES snes, Vec X, Mat J, Mat Jpre, void *appctx) 48d71ae5a4SJacob Faibussowitsch { 49c4762a1bSJed Brown DM networkdm; 50c4762a1bSJed Brown Vec localX; 51c4762a1bSJed Brown PetscInt nv, ne, i, j, offset, nvar, row; 52c4762a1bSJed Brown const PetscInt *vtx, *edges; 53c4762a1bSJed Brown PetscBool ghostvtex; 54c4762a1bSJed Brown PetscScalar one = 1.0; 55c4762a1bSJed Brown PetscMPIInt rank; 56c4762a1bSJed Brown MPI_Comm comm; 57c4762a1bSJed Brown 58c4762a1bSJed Brown PetscFunctionBegin; 599566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &networkdm)); 609566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localX)); 61c4762a1bSJed Brown 629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)networkdm, &comm)); 639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 64c4762a1bSJed Brown 659566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX)); 669566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX)); 67c4762a1bSJed Brown 689566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(J)); 69c4762a1bSJed Brown 70c4762a1bSJed Brown /* Power subnetwork: copied from power/FormJacobian_Power() */ 719566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 729566063dSJacob Faibussowitsch PetscCall(FormJacobian_Power_private(networkdm, localX, J, nv, ne, vtx, edges, appctx)); 73c4762a1bSJed Brown 74c4762a1bSJed Brown /* Water subnetwork: Identity */ 759566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 1, &nv, &ne, &vtx, &edges)); 76c4762a1bSJed Brown for (i = 0; i < nv; i++) { 779566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghostvtex)); 78c4762a1bSJed Brown if (ghostvtex) continue; 79c4762a1bSJed Brown 809566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVecOffset(networkdm, vtx[i], ALL_COMPONENTS, &offset)); 819566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[i], ALL_COMPONENTS, NULL, NULL, &nvar)); 82c4762a1bSJed Brown for (j = 0; j < nvar; j++) { 83c4762a1bSJed Brown row = offset + j; 849566063dSJacob Faibussowitsch PetscCall(MatSetValues(J, 1, &row, 1, &row, &one, ADD_VALUES)); 85c4762a1bSJed Brown } 86c4762a1bSJed Brown } 879566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 889566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 89c4762a1bSJed Brown 909566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localX)); 913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 92c4762a1bSJed Brown } 93c4762a1bSJed Brown 94c4762a1bSJed Brown /* Dummy equation localF(X) = localX - localXold */ 95d71ae5a4SJacob Faibussowitsch PetscErrorCode FormFunction_Dummy(DM networkdm, Vec localX, Vec localF, PetscInt nv, PetscInt ne, const PetscInt *vtx, const PetscInt *edges, void *appctx) 96d71ae5a4SJacob Faibussowitsch { 97c4762a1bSJed Brown const PetscScalar *xarr, *xoldarr; 98c4762a1bSJed Brown PetscScalar *farr; 99c4762a1bSJed Brown PetscInt i, j, offset, nvar; 100c4762a1bSJed Brown PetscBool ghostvtex; 101c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 102c4762a1bSJed Brown Vec localXold = user->localXold; 103c4762a1bSJed Brown 104c4762a1bSJed Brown PetscFunctionBegin; 1059566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localX, &xarr)); 1069566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localXold, &xoldarr)); 1079566063dSJacob Faibussowitsch PetscCall(VecGetArray(localF, &farr)); 108c4762a1bSJed Brown 109c4762a1bSJed Brown for (i = 0; i < nv; i++) { 1109566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghostvtex)); 111c4762a1bSJed Brown if (ghostvtex) continue; 112c4762a1bSJed Brown 1139566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vtx[i], ALL_COMPONENTS, &offset)); 1149566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[i], ALL_COMPONENTS, NULL, NULL, &nvar)); 115ad540459SPierre Jolivet for (j = 0; j < nvar; j++) farr[offset + j] = xarr[offset + j] - xoldarr[offset + j]; 116c4762a1bSJed Brown } 117c4762a1bSJed Brown 1189566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localX, &xarr)); 1199566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localXold, &xoldarr)); 1209566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localF, &farr)); 1213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 122c4762a1bSJed Brown } 123c4762a1bSJed Brown 124d71ae5a4SJacob Faibussowitsch PetscErrorCode FormFunction(SNES snes, Vec X, Vec F, void *appctx) 125d71ae5a4SJacob Faibussowitsch { 126c4762a1bSJed Brown DM networkdm; 127c4762a1bSJed Brown Vec localX, localF; 1282bf73ac6SHong Zhang PetscInt nv, ne, v; 129c4762a1bSJed Brown const PetscInt *vtx, *edges; 130c4762a1bSJed Brown PetscMPIInt rank; 131c4762a1bSJed Brown MPI_Comm comm; 132c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 133c4762a1bSJed Brown UserCtx_Power appctx_power = (*user).appctx_power; 1342bf73ac6SHong Zhang AppCtx_Water appctx_water = (*user).appctx_water; 135c4762a1bSJed Brown 136c4762a1bSJed Brown PetscFunctionBegin; 1379566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &networkdm)); 1389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)networkdm, &comm)); 1399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 140c4762a1bSJed Brown 1419566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localX)); 1429566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localF)); 1439566063dSJacob Faibussowitsch PetscCall(VecSet(F, 0.0)); 1449566063dSJacob Faibussowitsch PetscCall(VecSet(localF, 0.0)); 145c4762a1bSJed Brown 1469566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX)); 1479566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX)); 148c4762a1bSJed Brown 149c4762a1bSJed Brown /* Form Function for power subnetwork */ 1509566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 151c4762a1bSJed Brown if (user->subsnes_id == 1) { /* snes_water only */ 1529566063dSJacob Faibussowitsch PetscCall(FormFunction_Dummy(networkdm, localX, localF, nv, ne, vtx, edges, user)); 153c4762a1bSJed Brown } else { 1549566063dSJacob Faibussowitsch PetscCall(FormFunction_Power(networkdm, localX, localF, nv, ne, vtx, edges, &appctx_power)); 155c4762a1bSJed Brown } 156c4762a1bSJed Brown 157c4762a1bSJed Brown /* Form Function for water subnetwork */ 1589566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 1, &nv, &ne, &vtx, &edges)); 159c4762a1bSJed Brown if (user->subsnes_id == 0) { /* snes_power only */ 1609566063dSJacob Faibussowitsch PetscCall(FormFunction_Dummy(networkdm, localX, localF, nv, ne, vtx, edges, user)); 161c4762a1bSJed Brown } else { 1629566063dSJacob Faibussowitsch PetscCall(FormFunction_Water(networkdm, localX, localF, nv, ne, vtx, edges, NULL)); 163c4762a1bSJed Brown } 164c4762a1bSJed Brown 1652bf73ac6SHong Zhang /* Illustrate how to access the coupling vertex of the subnetworks without doing anything to F yet */ 1669566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 1672bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 1682bf73ac6SHong Zhang PetscInt key, ncomp, nvar, nconnedges, k, e, keye, goffset[3]; 169c4762a1bSJed Brown void *component; 1702bf73ac6SHong Zhang const PetscInt *connedges; 171c4762a1bSJed Brown 1729566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[v], ALL_COMPONENTS, NULL, NULL, &nvar)); 1739566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, vtx[v], &ncomp)); 17463a3b9bcSJacob Faibussowitsch /* printf(" [%d] coupling vertex[%" PetscInt_FMT "]: v %" PetscInt_FMT ", ncomp %" PetscInt_FMT "; nvar %" PetscInt_FMT "\n",rank,v,vtx[v], ncomp,nvar); */ 175c4762a1bSJed Brown 1762bf73ac6SHong Zhang for (k = 0; k < ncomp; k++) { 1779566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[v], k, &key, &component, &nvar)); 1789566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVecOffset(networkdm, vtx[v], k, &goffset[k])); 179c4762a1bSJed Brown 1802bf73ac6SHong Zhang /* Verify the coupling vertex is a powernet load vertex or a water vertex */ 1812bf73ac6SHong Zhang switch (k) { 182d71ae5a4SJacob Faibussowitsch case 0: 183d71ae5a4SJacob 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); 184d71ae5a4SJacob Faibussowitsch break; 185d71ae5a4SJacob Faibussowitsch case 1: 186d71ae5a4SJacob 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"); 187d71ae5a4SJacob Faibussowitsch break; 188d71ae5a4SJacob Faibussowitsch case 2: 189d71ae5a4SJacob Faibussowitsch PetscCheck(key == appctx_water.compkey_vtx && nvar == 1 && goffset[2] == goffset[1], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not a water vertex"); 190d71ae5a4SJacob Faibussowitsch break; 191d71ae5a4SJacob Faibussowitsch default: 192d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "k %" PetscInt_FMT " is wrong", k); 1932bf73ac6SHong Zhang } 19463a3b9bcSJacob Faibussowitsch /* printf(" [%d] coupling vertex[%" PetscInt_FMT "]: key %" PetscInt_FMT "; nvar %" PetscInt_FMT ", goffset %" PetscInt_FMT "\n",rank,v,key,nvar,goffset[k]); */ 1952bf73ac6SHong Zhang } 196c4762a1bSJed Brown 1972bf73ac6SHong Zhang /* Get its supporting edges */ 1989566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSupportingEdges(networkdm, vtx[v], &nconnedges, &connedges)); 19963a3b9bcSJacob Faibussowitsch /* printf("\n[%d] coupling vertex: nconnedges %" PetscInt_FMT "\n",rank,nconnedges); */ 200c4762a1bSJed Brown for (k = 0; k < nconnedges; k++) { 201c4762a1bSJed Brown e = connedges[k]; 2029566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, e, &ncomp)); 20363a3b9bcSJacob Faibussowitsch /* printf("\n [%d] connected edge[%" PetscInt_FMT "]=%" PetscInt_FMT " has ncomp %" PetscInt_FMT "\n",rank,k,e,ncomp); */ 2049566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, e, 0, &keye, &component, NULL)); 205ad540459SPierre Jolivet if (keye != appctx_water.compkey_edge) PetscCheck(keye == appctx_power.compkey_branch, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not a power branch"); 206c4762a1bSJed Brown } 207c4762a1bSJed Brown } 208c4762a1bSJed Brown 2099566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localX)); 210c4762a1bSJed Brown 2119566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localF, ADD_VALUES, F)); 2129566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localF, ADD_VALUES, F)); 2139566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localF)); 2142bf73ac6SHong Zhang #if 0 215dd400576SPatrick Sanan if (rank == 0) printf("F:\n"); 2169566063dSJacob Faibussowitsch PetscCall(VecView(F,PETSC_VIEWER_STDOUT_WORLD)); 2172bf73ac6SHong Zhang #endif 2183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 219c4762a1bSJed Brown } 220c4762a1bSJed Brown 221d71ae5a4SJacob Faibussowitsch PetscErrorCode SetInitialGuess(DM networkdm, Vec X, void *appctx) 222d71ae5a4SJacob Faibussowitsch { 2232bf73ac6SHong Zhang PetscInt nv, ne, i, j, ncomp, offset, key; 224c4762a1bSJed Brown const PetscInt *vtx, *edges; 225c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 226c4762a1bSJed Brown Vec localX = user->localXold; 227c4762a1bSJed Brown UserCtx_Power appctx_power = (*user).appctx_power; 2282bf73ac6SHong Zhang AppCtx_Water appctx_water = (*user).appctx_water; 2292bf73ac6SHong Zhang PetscBool ghost; 2302bf73ac6SHong Zhang PetscScalar *xarr; 2312bf73ac6SHong Zhang VERTEX_Power bus; 2322bf73ac6SHong Zhang VERTEX_Water vertex; 2332bf73ac6SHong Zhang void *component; 2342bf73ac6SHong Zhang GEN gen; 235c4762a1bSJed Brown 236c4762a1bSJed Brown PetscFunctionBegin; 2379566063dSJacob Faibussowitsch PetscCall(VecSet(X, 0.0)); 2389566063dSJacob Faibussowitsch PetscCall(VecSet(localX, 0.0)); 239c4762a1bSJed Brown 240c4762a1bSJed Brown /* Set initial guess for power subnetwork */ 2419566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 2429566063dSJacob Faibussowitsch PetscCall(SetInitialGuess_Power(networkdm, localX, nv, ne, vtx, edges, &appctx_power)); 243c4762a1bSJed Brown 244c4762a1bSJed Brown /* Set initial guess for water subnetwork */ 2459566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 1, &nv, &ne, &vtx, &edges)); 2469566063dSJacob Faibussowitsch PetscCall(SetInitialGuess_Water(networkdm, localX, nv, ne, vtx, edges, NULL)); 247c4762a1bSJed Brown 2482bf73ac6SHong Zhang /* Set initial guess at the coupling vertex */ 2499566063dSJacob Faibussowitsch PetscCall(VecGetArray(localX, &xarr)); 2509566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 2512bf73ac6SHong Zhang for (i = 0; i < nv; i++) { 2529566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghost)); 2532bf73ac6SHong Zhang if (ghost) continue; 2542bf73ac6SHong Zhang 2559566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, vtx[i], &ncomp)); 2562bf73ac6SHong Zhang for (j = 0; j < ncomp; j++) { 2579566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vtx[i], j, &offset)); 2589566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[i], j, &key, (void **)&component, NULL)); 2592bf73ac6SHong Zhang if (key == appctx_power.compkey_bus) { 2602bf73ac6SHong Zhang bus = (VERTEX_Power)(component); 2612bf73ac6SHong Zhang xarr[offset] = bus->va * PETSC_PI / 180.0; 2622bf73ac6SHong Zhang xarr[offset + 1] = bus->vm; 2632bf73ac6SHong Zhang } else if (key == appctx_power.compkey_gen) { 2642bf73ac6SHong Zhang gen = (GEN)(component); 2652bf73ac6SHong Zhang if (!gen->status) continue; 2662bf73ac6SHong Zhang xarr[offset + 1] = gen->vs; 2672bf73ac6SHong Zhang } else if (key == appctx_water.compkey_vtx) { 2682bf73ac6SHong Zhang vertex = (VERTEX_Water)(component); 2692bf73ac6SHong Zhang if (vertex->type == VERTEX_TYPE_JUNCTION) { 2702bf73ac6SHong Zhang xarr[offset] = 100; 2712bf73ac6SHong Zhang } else if (vertex->type == VERTEX_TYPE_RESERVOIR) { 2722bf73ac6SHong Zhang xarr[offset] = vertex->res.head; 2732bf73ac6SHong Zhang } else { 2742bf73ac6SHong Zhang xarr[offset] = vertex->tank.initlvl + vertex->tank.elev; 275c4762a1bSJed Brown } 2762bf73ac6SHong Zhang } 2772bf73ac6SHong Zhang } 2782bf73ac6SHong Zhang } 2799566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localX, &xarr)); 280c4762a1bSJed Brown 2819566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localX, ADD_VALUES, X)); 2829566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localX, ADD_VALUES, X)); 2833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 284c4762a1bSJed Brown } 285c4762a1bSJed Brown 286*cc13d412SHong Zhang /* Set coordinates */ 287*cc13d412SHong Zhang static PetscErrorCode CoordinateVecSetUp(DM dm, Vec coords) 288*cc13d412SHong Zhang { 289*cc13d412SHong Zhang DM dmclone; 290*cc13d412SHong Zhang PetscInt i, gidx, offset, v, nv, Nsubnet; 291*cc13d412SHong Zhang const PetscInt *vtx; 292*cc13d412SHong Zhang PetscScalar *carray; 293*cc13d412SHong Zhang 294*cc13d412SHong Zhang PetscFunctionBeginUser; 295*cc13d412SHong Zhang PetscCall(DMGetCoordinateDM(dm, &dmclone)); 296*cc13d412SHong Zhang PetscCall(VecGetArrayWrite(coords, &carray)); 297*cc13d412SHong Zhang PetscCall(DMNetworkGetNumSubNetworks(dm, NULL, &Nsubnet)); 298*cc13d412SHong Zhang for (i = 0; i < Nsubnet; i++) { 299*cc13d412SHong Zhang PetscCall(DMNetworkGetSubnetwork(dm, i, &nv, NULL, &vtx, NULL)); 300*cc13d412SHong Zhang for (v = 0; v < nv; v++) { 301*cc13d412SHong Zhang PetscCall(DMNetworkGetGlobalVertexIndex(dm, vtx[v], &gidx)); 302*cc13d412SHong Zhang PetscCall(DMNetworkGetLocalVecOffset(dmclone, vtx[v], 0, &offset)); 303*cc13d412SHong Zhang switch (gidx) { 304*cc13d412SHong Zhang case 0: 305*cc13d412SHong Zhang carray[offset] = -1.0; 306*cc13d412SHong Zhang carray[offset + 1] = -1.0; 307*cc13d412SHong Zhang break; 308*cc13d412SHong Zhang case 1: 309*cc13d412SHong Zhang carray[offset] = -2.0; 310*cc13d412SHong Zhang carray[offset + 1] = 2.0; 311*cc13d412SHong Zhang break; 312*cc13d412SHong Zhang case 2: 313*cc13d412SHong Zhang carray[offset] = 0.0; 314*cc13d412SHong Zhang carray[offset + 1] = 2.0; 315*cc13d412SHong Zhang break; 316*cc13d412SHong Zhang case 3: 317*cc13d412SHong Zhang carray[offset] = -1.0; 318*cc13d412SHong Zhang carray[offset + 1] = 0.0; 319*cc13d412SHong Zhang break; 320*cc13d412SHong Zhang case 4: 321*cc13d412SHong Zhang carray[offset] = 0.0; 322*cc13d412SHong Zhang carray[offset + 1] = 0.0; 323*cc13d412SHong Zhang break; 324*cc13d412SHong Zhang case 5: 325*cc13d412SHong Zhang carray[offset] = 0.0; 326*cc13d412SHong Zhang carray[offset + 1] = 1.0; 327*cc13d412SHong Zhang break; 328*cc13d412SHong Zhang case 6: 329*cc13d412SHong Zhang carray[offset] = -1.0; 330*cc13d412SHong Zhang carray[offset + 1] = 1.0; 331*cc13d412SHong Zhang break; 332*cc13d412SHong Zhang case 7: 333*cc13d412SHong Zhang carray[offset] = -2.0; 334*cc13d412SHong Zhang carray[offset + 1] = 1.0; 335*cc13d412SHong Zhang break; 336*cc13d412SHong Zhang case 8: 337*cc13d412SHong Zhang carray[offset] = -2.0; 338*cc13d412SHong Zhang carray[offset + 1] = 0.0; 339*cc13d412SHong Zhang break; 340*cc13d412SHong Zhang case 9: 341*cc13d412SHong Zhang carray[offset] = 1.0; 342*cc13d412SHong Zhang carray[offset + 1] = 0.0; 343*cc13d412SHong Zhang break; 344*cc13d412SHong Zhang case 10: 345*cc13d412SHong Zhang carray[offset] = 1.0; 346*cc13d412SHong Zhang carray[offset + 1] = -1.0; 347*cc13d412SHong Zhang break; 348*cc13d412SHong Zhang case 11: 349*cc13d412SHong Zhang carray[offset] = 2.0; 350*cc13d412SHong Zhang carray[offset + 1] = -1.0; 351*cc13d412SHong Zhang break; 352*cc13d412SHong Zhang case 12: 353*cc13d412SHong Zhang carray[offset] = 2.0; 354*cc13d412SHong Zhang carray[offset + 1] = 0.0; 355*cc13d412SHong Zhang break; 356*cc13d412SHong Zhang case 13: 357*cc13d412SHong Zhang carray[offset] = 0.0; 358*cc13d412SHong Zhang carray[offset + 1] = -1.0; 359*cc13d412SHong Zhang break; 360*cc13d412SHong Zhang case 14: 361*cc13d412SHong Zhang carray[offset] = 2.0; 362*cc13d412SHong Zhang carray[offset + 1] = 1.0; 363*cc13d412SHong Zhang break; 364*cc13d412SHong Zhang default: 365*cc13d412SHong Zhang PetscCheck(gidx < 15 && gidx > -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "gidx %" PetscInt_FMT "must between 0 and 14", gidx); 366*cc13d412SHong Zhang } 367*cc13d412SHong Zhang } 368*cc13d412SHong Zhang } 369*cc13d412SHong Zhang PetscCall(VecRestoreArrayWrite(coords, &carray)); 370*cc13d412SHong Zhang PetscFunctionReturn(PETSC_SUCCESS); 371*cc13d412SHong Zhang } 372*cc13d412SHong Zhang 373*cc13d412SHong Zhang static PetscErrorCode CoordinatePrint(DM dm) 374*cc13d412SHong Zhang { 375*cc13d412SHong Zhang DM dmclone; 376*cc13d412SHong Zhang PetscInt cdim, v, off, vglobal, vStart, vEnd; 377*cc13d412SHong Zhang const PetscScalar *carray; 378*cc13d412SHong Zhang Vec coords; 379*cc13d412SHong Zhang MPI_Comm comm; 380*cc13d412SHong Zhang PetscMPIInt rank; 381*cc13d412SHong Zhang 382*cc13d412SHong Zhang PetscFunctionBegin; 383*cc13d412SHong Zhang PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 384*cc13d412SHong Zhang PetscCallMPI(MPI_Comm_rank(comm, &rank)); 385*cc13d412SHong Zhang 386*cc13d412SHong Zhang PetscCall(DMGetCoordinateDM(dm, &dmclone)); 387*cc13d412SHong Zhang PetscCall(DMNetworkGetVertexRange(dm, &vStart, &vEnd)); 388*cc13d412SHong Zhang PetscCall(DMGetCoordinatesLocal(dm, &coords)); 389*cc13d412SHong Zhang 390*cc13d412SHong Zhang PetscCall(DMGetCoordinateDim(dm, &cdim)); 391*cc13d412SHong Zhang PetscCall(VecGetArrayRead(coords, &carray)); 392*cc13d412SHong Zhang 393*cc13d412SHong Zhang PetscCall(PetscPrintf(MPI_COMM_WORLD, "\nCoordinatePrint, cdim %" PetscInt_FMT ":\n", cdim)); 394*cc13d412SHong Zhang PetscCall(PetscSynchronizedPrintf(MPI_COMM_WORLD, "[%i]\n", rank)); 395*cc13d412SHong Zhang for (v = vStart; v < vEnd; v++) { 396*cc13d412SHong Zhang PetscCall(DMNetworkGetLocalVecOffset(dmclone, v, 0, &off)); 397*cc13d412SHong Zhang PetscCall(DMNetworkGetGlobalVertexIndex(dmclone, v, &vglobal)); 398*cc13d412SHong Zhang switch (cdim) { 399*cc13d412SHong Zhang case 2: 400*cc13d412SHong Zhang PetscCall(PetscSynchronizedPrintf(MPI_COMM_WORLD, "Vertex: %" PetscInt_FMT ", x = %f y = %f \n", vglobal, (double)PetscRealPart(carray[off]), (double)PetscRealPart(carray[off + 1]))); 401*cc13d412SHong Zhang break; 402*cc13d412SHong Zhang default: 403*cc13d412SHong Zhang PetscCheck(cdim == 2, MPI_COMM_WORLD, PETSC_ERR_SUP, "Only supports Network embedding dimension of 2, not supplied %" PetscInt_FMT, cdim); 404*cc13d412SHong Zhang break; 405*cc13d412SHong Zhang } 406*cc13d412SHong Zhang } 407*cc13d412SHong Zhang PetscCall(PetscSynchronizedFlush(MPI_COMM_WORLD, NULL)); 408*cc13d412SHong Zhang PetscCall(VecRestoreArrayRead(coords, &carray)); 409*cc13d412SHong Zhang PetscFunctionReturn(PETSC_SUCCESS); 410*cc13d412SHong Zhang } 411*cc13d412SHong Zhang 412d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 413d71ae5a4SJacob Faibussowitsch { 414*cc13d412SHong Zhang DM networkdm, dmclone; 415c4762a1bSJed Brown PetscLogStage stage[4]; 416d5c9c0c4SHong Zhang PetscMPIInt rank, size; 4172bf73ac6SHong Zhang PetscInt Nsubnet = 2, numVertices[2], numEdges[2], i, j, nv, ne, it_max = 10; 418*cc13d412SHong Zhang PetscInt vStart, vEnd, compkey; 419c4762a1bSJed Brown const PetscInt *vtx, *edges; 420*cc13d412SHong Zhang Vec X, F, coords; 421c4762a1bSJed Brown SNES snes, snes_power, snes_water; 422c4762a1bSJed Brown Mat Jac; 423*cc13d412SHong Zhang PetscBool ghost, viewJ = PETSC_FALSE, viewX = PETSC_FALSE, test = PETSC_FALSE, distribute = PETSC_TRUE, flg, printCoord = PETSC_FALSE, viewCSV = PETSC_FALSE; 424c4762a1bSJed Brown UserCtx user; 425c4762a1bSJed Brown SNESConvergedReason reason; 426c4762a1bSJed Brown 427c4762a1bSJed Brown /* Power subnetwork */ 428c4762a1bSJed Brown UserCtx_Power *appctx_power = &user.appctx_power; 429c4762a1bSJed Brown char pfdata_file[PETSC_MAX_PATH_LEN] = "power/case9.m"; 430c4762a1bSJed Brown PFDATA *pfdata = NULL; 4312bf73ac6SHong Zhang PetscInt genj, loadj, *edgelist_power = NULL, power_netnum; 432c4762a1bSJed Brown PetscScalar Sbase = 0.0; 433c4762a1bSJed Brown 434c4762a1bSJed Brown /* Water subnetwork */ 435c4762a1bSJed Brown AppCtx_Water *appctx_water = &user.appctx_water; 436c4762a1bSJed Brown WATERDATA *waterdata = NULL; 437c4762a1bSJed Brown char waterdata_file[PETSC_MAX_PATH_LEN] = "water/sample1.inp"; 4382bf73ac6SHong Zhang PetscInt *edgelist_water = NULL, water_netnum; 439c4762a1bSJed Brown 4402bf73ac6SHong Zhang /* Shared vertices between subnetworks */ 4412bf73ac6SHong Zhang PetscInt power_svtx, water_svtx; 442c4762a1bSJed Brown 443327415f7SBarry Smith PetscFunctionBeginUser; 4449566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, "ex1options", help)); 4459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 4469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); 447c4762a1bSJed Brown 448c4762a1bSJed Brown /* (1) Read Data - Only rank 0 reads the data */ 4499566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Read Data", &stage[0])); 4509566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[0])); 451c4762a1bSJed Brown 4522bf73ac6SHong Zhang for (i = 0; i < Nsubnet; i++) { 453c4762a1bSJed Brown numVertices[i] = 0; 454c4762a1bSJed Brown numEdges[i] = 0; 455c4762a1bSJed Brown } 456c4762a1bSJed Brown 4572bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE FIRST SUBNETWORK: Electric Power Grid */ 4582bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 4599566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-pfdata", pfdata_file, PETSC_MAX_PATH_LEN - 1, NULL)); 4609566063dSJacob Faibussowitsch PetscCall(PetscNew(&pfdata)); 4619566063dSJacob Faibussowitsch PetscCall(PFReadMatPowerData(pfdata, pfdata_file)); 46248a46eb9SPierre 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)); 463c4762a1bSJed Brown Sbase = pfdata->sbase; 4642bf73ac6SHong Zhang if (rank == 0) { /* proc[0] will create Electric Power Grid */ 465c4762a1bSJed Brown numEdges[0] = pfdata->nbranch; 466c4762a1bSJed Brown numVertices[0] = pfdata->nbus; 467c4762a1bSJed Brown 4689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * numEdges[0], &edgelist_power)); 4699566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Power(pfdata, edgelist_power)); 470c4762a1bSJed Brown } 471c4762a1bSJed Brown /* Broadcast power Sbase to all processors */ 4729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&Sbase, 1, MPIU_SCALAR, 0, PETSC_COMM_WORLD)); 473c4762a1bSJed Brown appctx_power->Sbase = Sbase; 474c4762a1bSJed Brown appctx_power->jac_error = PETSC_FALSE; 475c4762a1bSJed Brown /* If external option activated. Introduce error in jacobian */ 4769566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-jac_error", &appctx_power->jac_error)); 477c4762a1bSJed Brown 4782bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE SECOND SUBNETWORK: Water */ 4792bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 4809566063dSJacob Faibussowitsch PetscCall(PetscNew(&waterdata)); 4819566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-waterdata", waterdata_file, PETSC_MAX_PATH_LEN - 1, NULL)); 4829566063dSJacob Faibussowitsch PetscCall(WaterReadData(waterdata, waterdata_file)); 4832bf73ac6SHong Zhang if (size == 1 || (size > 1 && rank == 1)) { 4849566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(2 * waterdata->nedge, &edgelist_water)); 4859566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Water(waterdata, edgelist_water)); 486c4762a1bSJed Brown numEdges[1] = waterdata->nedge; 487c4762a1bSJed Brown numVertices[1] = waterdata->nvertex; 488c4762a1bSJed Brown } 4893ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePop()); 490c4762a1bSJed Brown 4912bf73ac6SHong Zhang /* (2) Create a network consist of two subnetworks */ 4929566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Net Setup", &stage[1])); 4939566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[1])); 494c4762a1bSJed Brown 495*cc13d412SHong Zhang PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewCSV", &viewCSV, NULL)); 496*cc13d412SHong Zhang PetscCall(PetscOptionsGetBool(NULL, NULL, "-printCoord", &printCoord, NULL)); 4979566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test", &test, NULL)); 4989566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-distribute", &distribute, NULL)); 499c4762a1bSJed Brown 500c4762a1bSJed Brown /* Create an empty network object */ 5019566063dSJacob Faibussowitsch PetscCall(DMNetworkCreate(PETSC_COMM_WORLD, &networkdm)); 502c4762a1bSJed Brown 503c4762a1bSJed Brown /* Register the components in the network */ 5049566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "branchstruct", sizeof(struct _p_EDGE_Power), &appctx_power->compkey_branch)); 5059566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "busstruct", sizeof(struct _p_VERTEX_Power), &appctx_power->compkey_bus)); 5069566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "genstruct", sizeof(struct _p_GEN), &appctx_power->compkey_gen)); 5079566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "loadstruct", sizeof(struct _p_LOAD), &appctx_power->compkey_load)); 508c4762a1bSJed Brown 5099566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "edge_water", sizeof(struct _p_EDGE_Water), &appctx_water->compkey_edge)); 5109566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "vertex_water", sizeof(struct _p_VERTEX_Water), &appctx_water->compkey_vtx)); 511*cc13d412SHong Zhang 51263a3b9bcSJacob 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])); 5139566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT)); 514c4762a1bSJed Brown 5159566063dSJacob Faibussowitsch PetscCall(DMNetworkSetNumSubNetworks(networkdm, PETSC_DECIDE, Nsubnet)); 5169566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, "power", numEdges[0], edgelist_power, &power_netnum)); 5179566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, "water", numEdges[1], edgelist_water, &water_netnum)); 518c4762a1bSJed Brown 5192bf73ac6SHong Zhang /* vertex subnet[0].4 shares with vertex subnet[1].0 */ 5209371c9d4SSatish Balay power_svtx = 4; 5219371c9d4SSatish Balay water_svtx = 0; 5229566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSharedVertices(networkdm, power_netnum, water_netnum, 1, &power_svtx, &water_svtx)); 523c4762a1bSJed Brown 524c4762a1bSJed Brown /* Set up the network layout */ 5259566063dSJacob Faibussowitsch PetscCall(DMNetworkLayoutSetUp(networkdm)); 526c4762a1bSJed Brown 527c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE POWER SUBNETWORK */ 5289371c9d4SSatish Balay genj = 0; 5299371c9d4SSatish Balay loadj = 0; 5309566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, power_netnum, &nv, &ne, &vtx, &edges)); 5312bf73ac6SHong Zhang 53248a46eb9SPierre Jolivet for (i = 0; i < ne; i++) PetscCall(DMNetworkAddComponent(networkdm, edges[i], appctx_power->compkey_branch, &pfdata->branch[i], 0)); 533c4762a1bSJed Brown 534c4762a1bSJed Brown for (i = 0; i < nv; i++) { 5359566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &flg)); 5362bf73ac6SHong Zhang if (flg) continue; 5372bf73ac6SHong Zhang 5389566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_bus, &pfdata->bus[i], 2)); 539c4762a1bSJed Brown if (pfdata->bus[i].ngen) { 54048a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i].ngen; j++) PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_gen, &pfdata->gen[genj++], 0)); 541c4762a1bSJed Brown } 542c4762a1bSJed Brown if (pfdata->bus[i].nload) { 54348a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i].nload; j++) PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_load, &pfdata->load[loadj++], 0)); 544c4762a1bSJed Brown } 545c4762a1bSJed Brown } 546c4762a1bSJed Brown 547c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE WATER SUBNETWORK */ 5489566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, water_netnum, &nv, &ne, &vtx, &edges)); 54948a46eb9SPierre Jolivet for (i = 0; i < ne; i++) PetscCall(DMNetworkAddComponent(networkdm, edges[i], appctx_water->compkey_edge, &waterdata->edge[i], 0)); 550c4762a1bSJed Brown 551c4762a1bSJed Brown for (i = 0; i < nv; i++) { 5529566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &flg)); 5532bf73ac6SHong Zhang if (flg) continue; 5542bf73ac6SHong Zhang 5559566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_water->compkey_vtx, &waterdata->vertex[i], 1)); 556c4762a1bSJed Brown } 5572bf73ac6SHong Zhang 558eac198afSGetnet /* 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 */ 5599566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 5602bf73ac6SHong Zhang for (i = 0; i < nv; i++) { 5612bf73ac6SHong Zhang /* power */ 5629566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_bus, &pfdata->bus[4], 2)); 5632bf73ac6SHong Zhang /* bus[4] is a load, add its component */ 5649566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_load, &pfdata->load[0], 0)); 5652bf73ac6SHong Zhang 5662bf73ac6SHong Zhang /* water */ 5679566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_water->compkey_vtx, &waterdata->vertex[0], 1)); 568c4762a1bSJed Brown } 569c4762a1bSJed Brown 570*cc13d412SHong Zhang /* Set coordinates for visualization */ 571*cc13d412SHong Zhang PetscCall(DMSetCoordinateDim(networkdm, 2)); 572*cc13d412SHong Zhang PetscCall(DMGetCoordinateDM(networkdm, &dmclone)); 573*cc13d412SHong Zhang PetscCall(DMNetworkGetVertexRange(dmclone, &vStart, &vEnd)); 574*cc13d412SHong Zhang PetscCall(DMNetworkRegisterComponent(dmclone, "coordinates", 0, &compkey)); 575*cc13d412SHong Zhang for (i = vStart; i < vEnd; i++) { PetscCall(DMNetworkAddComponent(dmclone, i, compkey, NULL, 2)); } 576*cc13d412SHong Zhang PetscCall(DMNetworkFinalizeComponents(dmclone)); 577*cc13d412SHong Zhang 578*cc13d412SHong Zhang PetscCall(DMCreateLocalVector(dmclone, &coords)); 579*cc13d412SHong Zhang PetscCall(DMSetCoordinatesLocal(networkdm, coords)); /* set/get coords to/from networkdm */ 580*cc13d412SHong Zhang PetscCall(CoordinateVecSetUp(networkdm, coords)); 581*cc13d412SHong Zhang if (printCoord) PetscCall(CoordinatePrint(networkdm)); 582*cc13d412SHong Zhang 583c4762a1bSJed Brown /* Set up DM for use */ 5849566063dSJacob Faibussowitsch PetscCall(DMSetUp(networkdm)); 585c4762a1bSJed Brown 586c4762a1bSJed Brown /* Free user objects */ 5879566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_power)); 5889566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->bus)); 5899566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->gen)); 5909566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->branch)); 5919566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->load)); 5929566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata)); 5932bf73ac6SHong Zhang 5949566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_water)); 5959566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->vertex)); 5969566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->edge)); 5979566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata)); 598c4762a1bSJed Brown 599d5c9c0c4SHong Zhang /* Re-distribute networkdm to multiple processes for better job balance */ 600*cc13d412SHong Zhang if (distribute) { 6019566063dSJacob Faibussowitsch PetscCall(DMNetworkDistribute(&networkdm, 0)); 602*cc13d412SHong Zhang 603*cc13d412SHong Zhang if (printCoord) PetscCall(CoordinatePrint(networkdm)); 604*cc13d412SHong Zhang if (viewCSV) { /* CSV View of network with coordinates */ 605*cc13d412SHong Zhang PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_CSV)); 6069566063dSJacob Faibussowitsch PetscCall(DMView(networkdm, PETSC_VIEWER_STDOUT_WORLD)); 607*cc13d412SHong Zhang PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD)); 608c4762a1bSJed Brown } 609d5c9c0c4SHong Zhang } 610*cc13d412SHong Zhang PetscCall(VecDestroy(&coords)); 611c4762a1bSJed Brown 6122bf73ac6SHong Zhang /* Test DMNetworkGetSubnetwork() and DMNetworkGetSubnetworkSharedVertices() */ 613c4762a1bSJed Brown if (test) { 6142bf73ac6SHong Zhang PetscInt v, gidx; 6159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 6162bf73ac6SHong Zhang for (i = 0; i < Nsubnet; i++) { 6179566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, i, &nv, &ne, &vtx, &edges)); 61863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] After distribute, subnet[%" PetscInt_FMT "] ne %" PetscInt_FMT ", nv %" PetscInt_FMT "\n", rank, i, ne, nv)); 6199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 620c4762a1bSJed Brown 6212bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 6229566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[v], &ghost)); 6239566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm, vtx[v], &gidx)); 62463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] subnet[%" PetscInt_FMT "] v %" PetscInt_FMT " %" PetscInt_FMT "; ghost %d\n", rank, i, vtx[v], gidx, ghost)); 625c4762a1bSJed Brown } 6269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 627c4762a1bSJed Brown } 6289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 6292bf73ac6SHong Zhang 6309566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 63163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] After distribute, num of shared vertices nsv = %" PetscInt_FMT "\n", rank, nv)); 6322bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 6339566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm, vtx[v], &gidx)); 63463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] sv %" PetscInt_FMT ", gidx=%" PetscInt_FMT "\n", rank, vtx[v], gidx)); 6352bf73ac6SHong Zhang } 6369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 637c4762a1bSJed Brown } 638c4762a1bSJed Brown 6392bf73ac6SHong Zhang /* Create solution vector X */ 6409566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(networkdm, &X)); 6419566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X, &F)); 6429566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &user.localXold)); 6433ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePop()); 644c4762a1bSJed Brown 645c4762a1bSJed Brown /* (3) Setup Solvers */ 6469566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewJ", &viewJ, NULL)); 6479566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewX", &viewX, NULL)); 648c4762a1bSJed Brown 6499566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Setup", &stage[2])); 6509566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[2])); 651c4762a1bSJed Brown 6529566063dSJacob Faibussowitsch PetscCall(SetInitialGuess(networkdm, X, &user)); 653c4762a1bSJed Brown 654c4762a1bSJed Brown /* Create coupled snes */ 6559566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_coupled setup ......\n")); 6562bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 6579566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes)); 6589566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, networkdm)); 6599566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes, "coupled_")); 6609566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, F, FormFunction, &user)); 6619566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, UserMonitor, &user, NULL)); 6629566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes)); 663c4762a1bSJed Brown 664c4762a1bSJed Brown if (viewJ) { 665c4762a1bSJed Brown /* View Jac structure */ 6669566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &Jac, NULL, NULL, NULL)); 6679566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 668c4762a1bSJed Brown } 669c4762a1bSJed Brown 670c4762a1bSJed Brown if (viewX) { 6719566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Solution:\n")); 6729566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 673c4762a1bSJed Brown } 674c4762a1bSJed Brown 675c4762a1bSJed Brown if (viewJ) { 676c4762a1bSJed Brown /* View assembled Jac */ 6779566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 678c4762a1bSJed Brown } 679c4762a1bSJed Brown 680c4762a1bSJed Brown /* Create snes_power */ 6819566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_power setup ......\n")); 682c4762a1bSJed Brown 683c4762a1bSJed Brown user.subsnes_id = 0; 6849566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes_power)); 6859566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_power, networkdm)); 6869566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_power, "power_")); 6879566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_power, F, FormFunction, &user)); 6889566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_power, UserMonitor, &user, NULL)); 689c4762a1bSJed Brown 690c4762a1bSJed Brown /* Use user-provide Jacobian */ 6919566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(networkdm, &Jac)); 6929566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes_power, Jac, Jac, FormJacobian_subPower, &user)); 6939566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_power)); 694c4762a1bSJed Brown 695c4762a1bSJed Brown if (viewX) { 6969566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Power Solution:\n")); 6979566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 698c4762a1bSJed Brown } 699c4762a1bSJed Brown if (viewJ) { 7009566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Power Jac:\n")); 7019566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes_power, &Jac, NULL, NULL, NULL)); 7029566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 7039566063dSJacob Faibussowitsch /* PetscCall(MatView(Jac,PETSC_VIEWER_STDOUT_WORLD)); */ 704c4762a1bSJed Brown } 705c4762a1bSJed Brown 706c4762a1bSJed Brown /* Create snes_water */ 7079566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_water setup......\n")); 708c4762a1bSJed Brown 709c4762a1bSJed Brown user.subsnes_id = 1; 7109566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes_water)); 7119566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_water, networkdm)); 7129566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_water, "water_")); 7139566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_water, F, FormFunction, &user)); 7149566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_water, UserMonitor, &user, NULL)); 7159566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_water)); 716c4762a1bSJed Brown 717c4762a1bSJed Brown if (viewX) { 7189566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Water Solution:\n")); 7199566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 720c4762a1bSJed Brown } 7219566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 722c4762a1bSJed Brown 723c4762a1bSJed Brown /* (4) Solve */ 7249566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Solve", &stage[3])); 7259566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[3])); 726c4762a1bSJed Brown user.it = 0; 727c4762a1bSJed Brown reason = SNES_DIVERGED_DTOL; 728c4762a1bSJed Brown while (user.it < it_max && (PetscInt)reason < 0) { 729c4762a1bSJed Brown #if 0 730c4762a1bSJed Brown user.subsnes_id = 0; 7319566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_power,NULL,X)); 732c4762a1bSJed Brown 733c4762a1bSJed Brown user.subsnes_id = 1; 7349566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_water,NULL,X)); 735c4762a1bSJed Brown #endif 7362bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 7379566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes, NULL, X)); 738c4762a1bSJed Brown 7399566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(snes, &reason)); 740c4762a1bSJed Brown user.it++; 741c4762a1bSJed Brown } 74263a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Coupled_SNES converged in %" PetscInt_FMT " iterations\n", user.it)); 743c4762a1bSJed Brown if (viewX) { 7449566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Final Solution:\n")); 7459566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 746c4762a1bSJed Brown } 7479566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 748c4762a1bSJed Brown 749c4762a1bSJed Brown /* Free objects */ 750c4762a1bSJed Brown /* -------------*/ 7519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X)); 7529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&F)); 7539566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &user.localXold)); 754c4762a1bSJed Brown 7559566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes)); 7569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Jac)); 7579566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_power)); 7589566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_water)); 759c4762a1bSJed Brown 7609566063dSJacob Faibussowitsch PetscCall(DMDestroy(&networkdm)); 7619566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 762b122ec5aSJacob Faibussowitsch return 0; 763c4762a1bSJed Brown } 764c4762a1bSJed Brown 765c4762a1bSJed Brown /*TEST 766c4762a1bSJed Brown 767c4762a1bSJed Brown build: 768dfd57a17SPierre Jolivet requires: !complex double defined(PETSC_HAVE_ATTRIBUTEALIGNED) 769c4762a1bSJed Brown depends: power/PFReadData.c power/pffunctions.c water/waterreaddata.c water/waterfunctions.c 770c4762a1bSJed Brown 771c4762a1bSJed Brown test: 772*cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -dmnetwork_view 773c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 774c4762a1bSJed Brown output_file: output/ex1.out 775c4762a1bSJed Brown 776c4762a1bSJed Brown test: 777c4762a1bSJed Brown suffix: 2 778c4762a1bSJed Brown nsize: 3 7792bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type parmetis 780c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 781d5c9c0c4SHong Zhang output_file: output/ex1_2.out 7822bf73ac6SHong Zhang requires: parmetis 7832bf73ac6SHong Zhang 784*cc13d412SHong Zhang test: 785*cc13d412SHong Zhang suffix: 3 786*cc13d412SHong Zhang nsize: 3 787*cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -distribute false 788*cc13d412SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 789*cc13d412SHong Zhang output_file: output/ex1_2.out 790d5c9c0c4SHong Zhang 791d5c9c0c4SHong Zhang test: 7922bf73ac6SHong Zhang suffix: 4 7932bf73ac6SHong Zhang nsize: 4 794*cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type simple -dmnetwork_view -dmnetwork_view_distributed 795d5c9c0c4SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 7962bf73ac6SHong Zhang output_file: output/ex1_4.out 797c4762a1bSJed Brown 798*cc13d412SHong Zhang test: 799*cc13d412SHong Zhang suffix: 5 800*cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -viewCSV 801*cc13d412SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 802*cc13d412SHong Zhang output_file: output/ex1_5.out 803*cc13d412SHong Zhang 804*cc13d412SHong Zhang test: 805*cc13d412SHong Zhang suffix: 6 806*cc13d412SHong Zhang nsize: 3 807*cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type parmetis -dmnetwork_view_distributed draw:null 808*cc13d412SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 809*cc13d412SHong Zhang output_file: output/ex1_2.out 810*cc13d412SHong Zhang requires: parmetis 811*cc13d412SHong Zhang 812c4762a1bSJed Brown TEST*/ 813