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 286cc13d412SHong Zhang /* Set coordinates */ 287cc13d412SHong Zhang static PetscErrorCode CoordinateVecSetUp(DM dm, Vec coords) 288cc13d412SHong Zhang { 289cc13d412SHong Zhang DM dmclone; 290cc13d412SHong Zhang PetscInt i, gidx, offset, v, nv, Nsubnet; 291cc13d412SHong Zhang const PetscInt *vtx; 292cc13d412SHong Zhang PetscScalar *carray; 293cc13d412SHong Zhang 294cc13d412SHong Zhang PetscFunctionBeginUser; 295cc13d412SHong Zhang PetscCall(DMGetCoordinateDM(dm, &dmclone)); 296cc13d412SHong Zhang PetscCall(VecGetArrayWrite(coords, &carray)); 297cc13d412SHong Zhang PetscCall(DMNetworkGetNumSubNetworks(dm, NULL, &Nsubnet)); 298cc13d412SHong Zhang for (i = 0; i < Nsubnet; i++) { 299cc13d412SHong Zhang PetscCall(DMNetworkGetSubnetwork(dm, i, &nv, NULL, &vtx, NULL)); 300cc13d412SHong Zhang for (v = 0; v < nv; v++) { 301cc13d412SHong Zhang PetscCall(DMNetworkGetGlobalVertexIndex(dm, vtx[v], &gidx)); 302cc13d412SHong Zhang PetscCall(DMNetworkGetLocalVecOffset(dmclone, vtx[v], 0, &offset)); 303cc13d412SHong Zhang switch (gidx) { 304cc13d412SHong Zhang case 0: 305cc13d412SHong Zhang carray[offset] = -1.0; 306cc13d412SHong Zhang carray[offset + 1] = -1.0; 307cc13d412SHong Zhang break; 308cc13d412SHong Zhang case 1: 309cc13d412SHong Zhang carray[offset] = -2.0; 310cc13d412SHong Zhang carray[offset + 1] = 2.0; 311cc13d412SHong Zhang break; 312cc13d412SHong Zhang case 2: 313cc13d412SHong Zhang carray[offset] = 0.0; 314cc13d412SHong Zhang carray[offset + 1] = 2.0; 315cc13d412SHong Zhang break; 316cc13d412SHong Zhang case 3: 317cc13d412SHong Zhang carray[offset] = -1.0; 318cc13d412SHong Zhang carray[offset + 1] = 0.0; 319cc13d412SHong Zhang break; 320cc13d412SHong Zhang case 4: 321cc13d412SHong Zhang carray[offset] = 0.0; 322cc13d412SHong Zhang carray[offset + 1] = 0.0; 323cc13d412SHong Zhang break; 324cc13d412SHong Zhang case 5: 325cc13d412SHong Zhang carray[offset] = 0.0; 326cc13d412SHong Zhang carray[offset + 1] = 1.0; 327cc13d412SHong Zhang break; 328cc13d412SHong Zhang case 6: 329cc13d412SHong Zhang carray[offset] = -1.0; 330cc13d412SHong Zhang carray[offset + 1] = 1.0; 331cc13d412SHong Zhang break; 332cc13d412SHong Zhang case 7: 333cc13d412SHong Zhang carray[offset] = -2.0; 334cc13d412SHong Zhang carray[offset + 1] = 1.0; 335cc13d412SHong Zhang break; 336cc13d412SHong Zhang case 8: 337cc13d412SHong Zhang carray[offset] = -2.0; 338cc13d412SHong Zhang carray[offset + 1] = 0.0; 339cc13d412SHong Zhang break; 340cc13d412SHong Zhang case 9: 341cc13d412SHong Zhang carray[offset] = 1.0; 342cc13d412SHong Zhang carray[offset + 1] = 0.0; 343cc13d412SHong Zhang break; 344cc13d412SHong Zhang case 10: 345cc13d412SHong Zhang carray[offset] = 1.0; 346cc13d412SHong Zhang carray[offset + 1] = -1.0; 347cc13d412SHong Zhang break; 348cc13d412SHong Zhang case 11: 349cc13d412SHong Zhang carray[offset] = 2.0; 350cc13d412SHong Zhang carray[offset + 1] = -1.0; 351cc13d412SHong Zhang break; 352cc13d412SHong Zhang case 12: 353cc13d412SHong Zhang carray[offset] = 2.0; 354cc13d412SHong Zhang carray[offset + 1] = 0.0; 355cc13d412SHong Zhang break; 356cc13d412SHong Zhang case 13: 357cc13d412SHong Zhang carray[offset] = 0.0; 358cc13d412SHong Zhang carray[offset + 1] = -1.0; 359cc13d412SHong Zhang break; 360cc13d412SHong Zhang case 14: 361cc13d412SHong Zhang carray[offset] = 2.0; 362cc13d412SHong Zhang carray[offset + 1] = 1.0; 363cc13d412SHong Zhang break; 364cc13d412SHong Zhang default: 365cc13d412SHong Zhang PetscCheck(gidx < 15 && gidx > -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "gidx %" PetscInt_FMT "must between 0 and 14", gidx); 366cc13d412SHong Zhang } 367cc13d412SHong Zhang } 368cc13d412SHong Zhang } 369cc13d412SHong Zhang PetscCall(VecRestoreArrayWrite(coords, &carray)); 370cc13d412SHong Zhang PetscFunctionReturn(PETSC_SUCCESS); 371cc13d412SHong Zhang } 372cc13d412SHong Zhang 373cc13d412SHong Zhang static PetscErrorCode CoordinatePrint(DM dm) 374cc13d412SHong Zhang { 375cc13d412SHong Zhang DM dmclone; 376cc13d412SHong Zhang PetscInt cdim, v, off, vglobal, vStart, vEnd; 377cc13d412SHong Zhang const PetscScalar *carray; 378cc13d412SHong Zhang Vec coords; 379cc13d412SHong Zhang MPI_Comm comm; 380cc13d412SHong Zhang PetscMPIInt rank; 381cc13d412SHong Zhang 382cc13d412SHong Zhang PetscFunctionBegin; 383cc13d412SHong Zhang PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 384cc13d412SHong Zhang PetscCallMPI(MPI_Comm_rank(comm, &rank)); 385cc13d412SHong Zhang 386cc13d412SHong Zhang PetscCall(DMGetCoordinateDM(dm, &dmclone)); 387cc13d412SHong Zhang PetscCall(DMNetworkGetVertexRange(dm, &vStart, &vEnd)); 388cc13d412SHong Zhang PetscCall(DMGetCoordinatesLocal(dm, &coords)); 389cc13d412SHong Zhang 390cc13d412SHong Zhang PetscCall(DMGetCoordinateDim(dm, &cdim)); 391cc13d412SHong Zhang PetscCall(VecGetArrayRead(coords, &carray)); 392cc13d412SHong Zhang 393cc13d412SHong Zhang PetscCall(PetscPrintf(MPI_COMM_WORLD, "\nCoordinatePrint, cdim %" PetscInt_FMT ":\n", cdim)); 394cc13d412SHong Zhang PetscCall(PetscSynchronizedPrintf(MPI_COMM_WORLD, "[%i]\n", rank)); 395cc13d412SHong Zhang for (v = vStart; v < vEnd; v++) { 396cc13d412SHong Zhang PetscCall(DMNetworkGetLocalVecOffset(dmclone, v, 0, &off)); 397cc13d412SHong Zhang PetscCall(DMNetworkGetGlobalVertexIndex(dmclone, v, &vglobal)); 398cc13d412SHong Zhang switch (cdim) { 399cc13d412SHong Zhang case 2: 400cc13d412SHong Zhang PetscCall(PetscSynchronizedPrintf(MPI_COMM_WORLD, "Vertex: %" PetscInt_FMT ", x = %f y = %f \n", vglobal, (double)PetscRealPart(carray[off]), (double)PetscRealPart(carray[off + 1]))); 401cc13d412SHong Zhang break; 402cc13d412SHong Zhang default: 403cc13d412SHong Zhang PetscCheck(cdim == 2, MPI_COMM_WORLD, PETSC_ERR_SUP, "Only supports Network embedding dimension of 2, not supplied %" PetscInt_FMT, cdim); 404cc13d412SHong Zhang break; 405cc13d412SHong Zhang } 406cc13d412SHong Zhang } 407cc13d412SHong Zhang PetscCall(PetscSynchronizedFlush(MPI_COMM_WORLD, NULL)); 408cc13d412SHong Zhang PetscCall(VecRestoreArrayRead(coords, &carray)); 409cc13d412SHong Zhang PetscFunctionReturn(PETSC_SUCCESS); 410cc13d412SHong Zhang } 411cc13d412SHong Zhang 412d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 413d71ae5a4SJacob Faibussowitsch { 414cc13d412SHong Zhang DM networkdm, dmclone; 415d5c9c0c4SHong Zhang PetscMPIInt rank, size; 4162bf73ac6SHong Zhang PetscInt Nsubnet = 2, numVertices[2], numEdges[2], i, j, nv, ne, it_max = 10; 417cc13d412SHong Zhang PetscInt vStart, vEnd, compkey; 418c4762a1bSJed Brown const PetscInt *vtx, *edges; 419cc13d412SHong Zhang Vec X, F, coords; 420c4762a1bSJed Brown SNES snes, snes_power, snes_water; 421c4762a1bSJed Brown Mat Jac; 422cc13d412SHong Zhang PetscBool ghost, viewJ = PETSC_FALSE, viewX = PETSC_FALSE, test = PETSC_FALSE, distribute = PETSC_TRUE, flg, printCoord = PETSC_FALSE, viewCSV = PETSC_FALSE; 423c4762a1bSJed Brown UserCtx user; 424c4762a1bSJed Brown SNESConvergedReason reason; 425*4279555eSSatish Balay #if defined(PETSC_USE_LOG) 426*4279555eSSatish Balay PetscLogStage stage[4]; 427*4279555eSSatish Balay #endif 428c4762a1bSJed Brown 429c4762a1bSJed Brown /* Power subnetwork */ 430c4762a1bSJed Brown UserCtx_Power *appctx_power = &user.appctx_power; 431c4762a1bSJed Brown char pfdata_file[PETSC_MAX_PATH_LEN] = "power/case9.m"; 432c4762a1bSJed Brown PFDATA *pfdata = NULL; 4332bf73ac6SHong Zhang PetscInt genj, loadj, *edgelist_power = NULL, power_netnum; 434c4762a1bSJed Brown PetscScalar Sbase = 0.0; 435c4762a1bSJed Brown 436c4762a1bSJed Brown /* Water subnetwork */ 437c4762a1bSJed Brown AppCtx_Water *appctx_water = &user.appctx_water; 438c4762a1bSJed Brown WATERDATA *waterdata = NULL; 439c4762a1bSJed Brown char waterdata_file[PETSC_MAX_PATH_LEN] = "water/sample1.inp"; 4402bf73ac6SHong Zhang PetscInt *edgelist_water = NULL, water_netnum; 441c4762a1bSJed Brown 4422bf73ac6SHong Zhang /* Shared vertices between subnetworks */ 4432bf73ac6SHong Zhang PetscInt power_svtx, water_svtx; 444c4762a1bSJed Brown 445327415f7SBarry Smith PetscFunctionBeginUser; 4469566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, "ex1options", help)); 4479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 4489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); 449c4762a1bSJed Brown 450c4762a1bSJed Brown /* (1) Read Data - Only rank 0 reads the data */ 4519566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Read Data", &stage[0])); 4529566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[0])); 453c4762a1bSJed Brown 4542bf73ac6SHong Zhang for (i = 0; i < Nsubnet; i++) { 455c4762a1bSJed Brown numVertices[i] = 0; 456c4762a1bSJed Brown numEdges[i] = 0; 457c4762a1bSJed Brown } 458c4762a1bSJed Brown 4592bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE FIRST SUBNETWORK: Electric Power Grid */ 4602bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 4619566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-pfdata", pfdata_file, PETSC_MAX_PATH_LEN - 1, NULL)); 4629566063dSJacob Faibussowitsch PetscCall(PetscNew(&pfdata)); 4639566063dSJacob Faibussowitsch PetscCall(PFReadMatPowerData(pfdata, pfdata_file)); 46448a46eb9SPierre 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)); 465c4762a1bSJed Brown Sbase = pfdata->sbase; 4662bf73ac6SHong Zhang if (rank == 0) { /* proc[0] will create Electric Power Grid */ 467c4762a1bSJed Brown numEdges[0] = pfdata->nbranch; 468c4762a1bSJed Brown numVertices[0] = pfdata->nbus; 469c4762a1bSJed Brown 4709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * numEdges[0], &edgelist_power)); 4719566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Power(pfdata, edgelist_power)); 472c4762a1bSJed Brown } 473c4762a1bSJed Brown /* Broadcast power Sbase to all processors */ 4749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&Sbase, 1, MPIU_SCALAR, 0, PETSC_COMM_WORLD)); 475c4762a1bSJed Brown appctx_power->Sbase = Sbase; 476c4762a1bSJed Brown appctx_power->jac_error = PETSC_FALSE; 477c4762a1bSJed Brown /* If external option activated. Introduce error in jacobian */ 4789566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-jac_error", &appctx_power->jac_error)); 479c4762a1bSJed Brown 4802bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE SECOND SUBNETWORK: Water */ 4812bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 4829566063dSJacob Faibussowitsch PetscCall(PetscNew(&waterdata)); 4839566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-waterdata", waterdata_file, PETSC_MAX_PATH_LEN - 1, NULL)); 4849566063dSJacob Faibussowitsch PetscCall(WaterReadData(waterdata, waterdata_file)); 4852bf73ac6SHong Zhang if (size == 1 || (size > 1 && rank == 1)) { 4869566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(2 * waterdata->nedge, &edgelist_water)); 4879566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Water(waterdata, edgelist_water)); 488c4762a1bSJed Brown numEdges[1] = waterdata->nedge; 489c4762a1bSJed Brown numVertices[1] = waterdata->nvertex; 490c4762a1bSJed Brown } 4913ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePop()); 492c4762a1bSJed Brown 4932bf73ac6SHong Zhang /* (2) Create a network consist of two subnetworks */ 4949566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Net Setup", &stage[1])); 4959566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[1])); 496c4762a1bSJed Brown 497cc13d412SHong Zhang PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewCSV", &viewCSV, NULL)); 498cc13d412SHong Zhang PetscCall(PetscOptionsGetBool(NULL, NULL, "-printCoord", &printCoord, NULL)); 4999566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test", &test, NULL)); 5009566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-distribute", &distribute, NULL)); 501c4762a1bSJed Brown 502c4762a1bSJed Brown /* Create an empty network object */ 5039566063dSJacob Faibussowitsch PetscCall(DMNetworkCreate(PETSC_COMM_WORLD, &networkdm)); 504c4762a1bSJed Brown 505c4762a1bSJed Brown /* Register the components in the network */ 5069566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "branchstruct", sizeof(struct _p_EDGE_Power), &appctx_power->compkey_branch)); 5079566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "busstruct", sizeof(struct _p_VERTEX_Power), &appctx_power->compkey_bus)); 5089566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "genstruct", sizeof(struct _p_GEN), &appctx_power->compkey_gen)); 5099566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "loadstruct", sizeof(struct _p_LOAD), &appctx_power->compkey_load)); 510c4762a1bSJed Brown 5119566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "edge_water", sizeof(struct _p_EDGE_Water), &appctx_water->compkey_edge)); 5129566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "vertex_water", sizeof(struct _p_VERTEX_Water), &appctx_water->compkey_vtx)); 513cc13d412SHong Zhang 51463a3b9bcSJacob 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])); 5159566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT)); 516c4762a1bSJed Brown 5179566063dSJacob Faibussowitsch PetscCall(DMNetworkSetNumSubNetworks(networkdm, PETSC_DECIDE, Nsubnet)); 5189566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, "power", numEdges[0], edgelist_power, &power_netnum)); 5199566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, "water", numEdges[1], edgelist_water, &water_netnum)); 520c4762a1bSJed Brown 5212bf73ac6SHong Zhang /* vertex subnet[0].4 shares with vertex subnet[1].0 */ 5229371c9d4SSatish Balay power_svtx = 4; 5239371c9d4SSatish Balay water_svtx = 0; 5249566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSharedVertices(networkdm, power_netnum, water_netnum, 1, &power_svtx, &water_svtx)); 525c4762a1bSJed Brown 526c4762a1bSJed Brown /* Set up the network layout */ 5279566063dSJacob Faibussowitsch PetscCall(DMNetworkLayoutSetUp(networkdm)); 528c4762a1bSJed Brown 529c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE POWER SUBNETWORK */ 5309371c9d4SSatish Balay genj = 0; 5319371c9d4SSatish Balay loadj = 0; 5329566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, power_netnum, &nv, &ne, &vtx, &edges)); 5332bf73ac6SHong Zhang 53448a46eb9SPierre Jolivet for (i = 0; i < ne; i++) PetscCall(DMNetworkAddComponent(networkdm, edges[i], appctx_power->compkey_branch, &pfdata->branch[i], 0)); 535c4762a1bSJed Brown 536c4762a1bSJed Brown for (i = 0; i < nv; i++) { 5379566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &flg)); 5382bf73ac6SHong Zhang if (flg) continue; 5392bf73ac6SHong Zhang 5409566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_bus, &pfdata->bus[i], 2)); 541c4762a1bSJed Brown if (pfdata->bus[i].ngen) { 54248a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i].ngen; j++) PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_gen, &pfdata->gen[genj++], 0)); 543c4762a1bSJed Brown } 544c4762a1bSJed Brown if (pfdata->bus[i].nload) { 54548a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i].nload; j++) PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_load, &pfdata->load[loadj++], 0)); 546c4762a1bSJed Brown } 547c4762a1bSJed Brown } 548c4762a1bSJed Brown 549c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE WATER SUBNETWORK */ 5509566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, water_netnum, &nv, &ne, &vtx, &edges)); 55148a46eb9SPierre Jolivet for (i = 0; i < ne; i++) PetscCall(DMNetworkAddComponent(networkdm, edges[i], appctx_water->compkey_edge, &waterdata->edge[i], 0)); 552c4762a1bSJed Brown 553c4762a1bSJed Brown for (i = 0; i < nv; i++) { 5549566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &flg)); 5552bf73ac6SHong Zhang if (flg) continue; 5562bf73ac6SHong Zhang 5579566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_water->compkey_vtx, &waterdata->vertex[i], 1)); 558c4762a1bSJed Brown } 5592bf73ac6SHong Zhang 560eac198afSGetnet /* 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 */ 5619566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 5622bf73ac6SHong Zhang for (i = 0; i < nv; i++) { 5632bf73ac6SHong Zhang /* power */ 5649566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_bus, &pfdata->bus[4], 2)); 5652bf73ac6SHong Zhang /* bus[4] is a load, add its component */ 5669566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_load, &pfdata->load[0], 0)); 5672bf73ac6SHong Zhang 5682bf73ac6SHong Zhang /* water */ 5699566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_water->compkey_vtx, &waterdata->vertex[0], 1)); 570c4762a1bSJed Brown } 571c4762a1bSJed Brown 572cc13d412SHong Zhang /* Set coordinates for visualization */ 573cc13d412SHong Zhang PetscCall(DMSetCoordinateDim(networkdm, 2)); 574cc13d412SHong Zhang PetscCall(DMGetCoordinateDM(networkdm, &dmclone)); 575cc13d412SHong Zhang PetscCall(DMNetworkGetVertexRange(dmclone, &vStart, &vEnd)); 576cc13d412SHong Zhang PetscCall(DMNetworkRegisterComponent(dmclone, "coordinates", 0, &compkey)); 577aa624791SPierre Jolivet for (i = vStart; i < vEnd; i++) PetscCall(DMNetworkAddComponent(dmclone, i, compkey, NULL, 2)); 578cc13d412SHong Zhang PetscCall(DMNetworkFinalizeComponents(dmclone)); 579cc13d412SHong Zhang 580cc13d412SHong Zhang PetscCall(DMCreateLocalVector(dmclone, &coords)); 581cc13d412SHong Zhang PetscCall(DMSetCoordinatesLocal(networkdm, coords)); /* set/get coords to/from networkdm */ 582cc13d412SHong Zhang PetscCall(CoordinateVecSetUp(networkdm, coords)); 583cc13d412SHong Zhang if (printCoord) PetscCall(CoordinatePrint(networkdm)); 584cc13d412SHong Zhang 585c4762a1bSJed Brown /* Set up DM for use */ 5869566063dSJacob Faibussowitsch PetscCall(DMSetUp(networkdm)); 587c4762a1bSJed Brown 588c4762a1bSJed Brown /* Free user objects */ 5899566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_power)); 5909566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->bus)); 5919566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->gen)); 5929566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->branch)); 5939566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->load)); 5949566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata)); 5952bf73ac6SHong Zhang 5969566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_water)); 5979566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->vertex)); 5989566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->edge)); 5999566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata)); 600c4762a1bSJed Brown 601d5c9c0c4SHong Zhang /* Re-distribute networkdm to multiple processes for better job balance */ 602cc13d412SHong Zhang if (distribute) { 6039566063dSJacob Faibussowitsch PetscCall(DMNetworkDistribute(&networkdm, 0)); 604cc13d412SHong Zhang 605cc13d412SHong Zhang if (printCoord) PetscCall(CoordinatePrint(networkdm)); 606cc13d412SHong Zhang if (viewCSV) { /* CSV View of network with coordinates */ 607cc13d412SHong Zhang PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_CSV)); 6089566063dSJacob Faibussowitsch PetscCall(DMView(networkdm, PETSC_VIEWER_STDOUT_WORLD)); 609cc13d412SHong Zhang PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD)); 610c4762a1bSJed Brown } 611d5c9c0c4SHong Zhang } 612cc13d412SHong Zhang PetscCall(VecDestroy(&coords)); 613c4762a1bSJed Brown 6142bf73ac6SHong Zhang /* Test DMNetworkGetSubnetwork() and DMNetworkGetSubnetworkSharedVertices() */ 615c4762a1bSJed Brown if (test) { 6162bf73ac6SHong Zhang PetscInt v, gidx; 6179566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 6182bf73ac6SHong Zhang for (i = 0; i < Nsubnet; i++) { 6199566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, i, &nv, &ne, &vtx, &edges)); 62063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] After distribute, subnet[%" PetscInt_FMT "] ne %" PetscInt_FMT ", nv %" PetscInt_FMT "\n", rank, i, ne, nv)); 6219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 622c4762a1bSJed Brown 6232bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 6249566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[v], &ghost)); 6259566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm, vtx[v], &gidx)); 62663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] subnet[%" PetscInt_FMT "] v %" PetscInt_FMT " %" PetscInt_FMT "; ghost %d\n", rank, i, vtx[v], gidx, ghost)); 627c4762a1bSJed Brown } 6289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 629c4762a1bSJed Brown } 6309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 6312bf73ac6SHong Zhang 6329566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 63363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] After distribute, num of shared vertices nsv = %" PetscInt_FMT "\n", rank, nv)); 6342bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 6359566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm, vtx[v], &gidx)); 63663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] sv %" PetscInt_FMT ", gidx=%" PetscInt_FMT "\n", rank, vtx[v], gidx)); 6372bf73ac6SHong Zhang } 6389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 639c4762a1bSJed Brown } 640c4762a1bSJed Brown 6412bf73ac6SHong Zhang /* Create solution vector X */ 6429566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(networkdm, &X)); 6439566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X, &F)); 6449566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &user.localXold)); 6453ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePop()); 646c4762a1bSJed Brown 647c4762a1bSJed Brown /* (3) Setup Solvers */ 6489566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewJ", &viewJ, NULL)); 6499566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewX", &viewX, NULL)); 650c4762a1bSJed Brown 6519566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Setup", &stage[2])); 6529566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[2])); 653c4762a1bSJed Brown 6549566063dSJacob Faibussowitsch PetscCall(SetInitialGuess(networkdm, X, &user)); 655c4762a1bSJed Brown 656c4762a1bSJed Brown /* Create coupled snes */ 6579566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_coupled setup ......\n")); 6582bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 6599566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes)); 6609566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, networkdm)); 6619566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes, "coupled_")); 6629566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, F, FormFunction, &user)); 6639566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, UserMonitor, &user, NULL)); 6649566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes)); 665c4762a1bSJed Brown 666c4762a1bSJed Brown if (viewJ) { 667c4762a1bSJed Brown /* View Jac structure */ 6689566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &Jac, NULL, NULL, NULL)); 6699566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 670c4762a1bSJed Brown } 671c4762a1bSJed Brown 672c4762a1bSJed Brown if (viewX) { 6739566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Solution:\n")); 6749566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 675c4762a1bSJed Brown } 676c4762a1bSJed Brown 677c4762a1bSJed Brown if (viewJ) { 678c4762a1bSJed Brown /* View assembled Jac */ 6799566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 680c4762a1bSJed Brown } 681c4762a1bSJed Brown 682c4762a1bSJed Brown /* Create snes_power */ 6839566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_power setup ......\n")); 684c4762a1bSJed Brown 685c4762a1bSJed Brown user.subsnes_id = 0; 6869566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes_power)); 6879566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_power, networkdm)); 6889566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_power, "power_")); 6899566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_power, F, FormFunction, &user)); 6909566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_power, UserMonitor, &user, NULL)); 691c4762a1bSJed Brown 692c4762a1bSJed Brown /* Use user-provide Jacobian */ 6939566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(networkdm, &Jac)); 6949566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes_power, Jac, Jac, FormJacobian_subPower, &user)); 6959566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_power)); 696c4762a1bSJed Brown 697c4762a1bSJed Brown if (viewX) { 6989566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Power Solution:\n")); 6999566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 700c4762a1bSJed Brown } 701c4762a1bSJed Brown if (viewJ) { 7029566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Power Jac:\n")); 7039566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes_power, &Jac, NULL, NULL, NULL)); 7049566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 7059566063dSJacob Faibussowitsch /* PetscCall(MatView(Jac,PETSC_VIEWER_STDOUT_WORLD)); */ 706c4762a1bSJed Brown } 707c4762a1bSJed Brown 708c4762a1bSJed Brown /* Create snes_water */ 7099566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_water setup......\n")); 710c4762a1bSJed Brown 711c4762a1bSJed Brown user.subsnes_id = 1; 7129566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes_water)); 7139566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_water, networkdm)); 7149566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_water, "water_")); 7159566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_water, F, FormFunction, &user)); 7169566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_water, UserMonitor, &user, NULL)); 7179566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_water)); 718c4762a1bSJed Brown 719c4762a1bSJed Brown if (viewX) { 7209566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Water Solution:\n")); 7219566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 722c4762a1bSJed Brown } 7239566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 724c4762a1bSJed Brown 725c4762a1bSJed Brown /* (4) Solve */ 7269566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Solve", &stage[3])); 7279566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[3])); 728c4762a1bSJed Brown user.it = 0; 729c4762a1bSJed Brown reason = SNES_DIVERGED_DTOL; 730c4762a1bSJed Brown while (user.it < it_max && (PetscInt)reason < 0) { 731c4762a1bSJed Brown #if 0 732c4762a1bSJed Brown user.subsnes_id = 0; 7339566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_power,NULL,X)); 734c4762a1bSJed Brown 735c4762a1bSJed Brown user.subsnes_id = 1; 7369566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_water,NULL,X)); 737c4762a1bSJed Brown #endif 7382bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 7399566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes, NULL, X)); 740c4762a1bSJed Brown 7419566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(snes, &reason)); 742c4762a1bSJed Brown user.it++; 743c4762a1bSJed Brown } 74463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Coupled_SNES converged in %" PetscInt_FMT " iterations\n", user.it)); 745c4762a1bSJed Brown if (viewX) { 7469566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Final Solution:\n")); 7479566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 748c4762a1bSJed Brown } 7499566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 750c4762a1bSJed Brown 751c4762a1bSJed Brown /* Free objects */ 752c4762a1bSJed Brown /* -------------*/ 7539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X)); 7549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&F)); 7559566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &user.localXold)); 756c4762a1bSJed Brown 7579566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes)); 7589566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Jac)); 7599566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_power)); 7609566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_water)); 761c4762a1bSJed Brown 7629566063dSJacob Faibussowitsch PetscCall(DMDestroy(&networkdm)); 7639566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 764b122ec5aSJacob Faibussowitsch return 0; 765c4762a1bSJed Brown } 766c4762a1bSJed Brown 767c4762a1bSJed Brown /*TEST 768c4762a1bSJed Brown 769c4762a1bSJed Brown build: 770dfd57a17SPierre Jolivet requires: !complex double defined(PETSC_HAVE_ATTRIBUTEALIGNED) 771c4762a1bSJed Brown depends: power/PFReadData.c power/pffunctions.c water/waterreaddata.c water/waterfunctions.c 772c4762a1bSJed Brown 773c4762a1bSJed Brown test: 774cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -dmnetwork_view 775c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 776c4762a1bSJed Brown output_file: output/ex1.out 777c4762a1bSJed Brown 778c4762a1bSJed Brown test: 779c4762a1bSJed Brown suffix: 2 780c4762a1bSJed Brown nsize: 3 7812bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type parmetis 782c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 783d5c9c0c4SHong Zhang output_file: output/ex1_2.out 7842bf73ac6SHong Zhang requires: parmetis 7852bf73ac6SHong Zhang 786cc13d412SHong Zhang test: 787cc13d412SHong Zhang suffix: 3 788cc13d412SHong Zhang nsize: 3 789cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -distribute false 790cc13d412SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 791cc13d412SHong Zhang output_file: output/ex1_2.out 792d5c9c0c4SHong Zhang 793d5c9c0c4SHong Zhang test: 7942bf73ac6SHong Zhang suffix: 4 7952bf73ac6SHong Zhang nsize: 4 796cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type simple -dmnetwork_view -dmnetwork_view_distributed 797d5c9c0c4SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 7982bf73ac6SHong Zhang output_file: output/ex1_4.out 799c4762a1bSJed Brown 800cc13d412SHong Zhang test: 801cc13d412SHong Zhang suffix: 5 802cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -viewCSV 803cc13d412SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 804cc13d412SHong Zhang output_file: output/ex1_5.out 805cc13d412SHong Zhang 806cc13d412SHong Zhang test: 807cc13d412SHong Zhang suffix: 6 808cc13d412SHong Zhang nsize: 3 809cc13d412SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type parmetis -dmnetwork_view_distributed draw:null 810cc13d412SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 811cc13d412SHong Zhang output_file: output/ex1_2.out 812cc13d412SHong Zhang requires: parmetis 813cc13d412SHong Zhang 814c4762a1bSJed Brown TEST*/ 815