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 199371c9d4SSatish Balay PetscErrorCode UserMonitor(SNES snes, PetscInt its, PetscReal fnorm, void *appctx) { 20c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 21c4762a1bSJed Brown Vec X, localXold = user->localXold; 22c4762a1bSJed Brown DM networkdm; 23c4762a1bSJed Brown PetscMPIInt rank; 24c4762a1bSJed Brown MPI_Comm comm; 25c4762a1bSJed Brown 26c4762a1bSJed Brown PetscFunctionBegin; 279566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 29c4762a1bSJed Brown #if 0 30dd400576SPatrick Sanan if (rank == 0) { 31c4762a1bSJed Brown PetscInt subsnes_id = user->subsnes_id; 32c4762a1bSJed Brown if (subsnes_id == 2) { 3363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF," it %" PetscInt_FMT ", subsnes_id %" PetscInt_FMT ", fnorm %g\n",user->it,user->subsnes_id,(double)fnorm)); 34c4762a1bSJed Brown } else { 3563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF," subsnes_id %" PetscInt_FMT ", fnorm %g\n",user->subsnes_id,(double)fnorm)); 36c4762a1bSJed Brown } 37c4762a1bSJed Brown } 38c4762a1bSJed Brown #endif 399566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &X)); 409566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &networkdm)); 419566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localXold)); 429566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localXold)); 43c4762a1bSJed Brown PetscFunctionReturn(0); 44c4762a1bSJed Brown } 45c4762a1bSJed Brown 469371c9d4SSatish Balay PetscErrorCode FormJacobian_subPower(SNES snes, Vec X, Mat J, Mat Jpre, void *appctx) { 47c4762a1bSJed Brown DM networkdm; 48c4762a1bSJed Brown Vec localX; 49c4762a1bSJed Brown PetscInt nv, ne, i, j, offset, nvar, row; 50c4762a1bSJed Brown const PetscInt *vtx, *edges; 51c4762a1bSJed Brown PetscBool ghostvtex; 52c4762a1bSJed Brown PetscScalar one = 1.0; 53c4762a1bSJed Brown PetscMPIInt rank; 54c4762a1bSJed Brown MPI_Comm comm; 55c4762a1bSJed Brown 56c4762a1bSJed Brown PetscFunctionBegin; 579566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &networkdm)); 589566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localX)); 59c4762a1bSJed Brown 609566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)networkdm, &comm)); 619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 62c4762a1bSJed Brown 639566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX)); 649566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX)); 65c4762a1bSJed Brown 669566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(J)); 67c4762a1bSJed Brown 68c4762a1bSJed Brown /* Power subnetwork: copied from power/FormJacobian_Power() */ 699566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 709566063dSJacob Faibussowitsch PetscCall(FormJacobian_Power_private(networkdm, localX, J, nv, ne, vtx, edges, appctx)); 71c4762a1bSJed Brown 72c4762a1bSJed Brown /* Water subnetwork: Identity */ 739566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 1, &nv, &ne, &vtx, &edges)); 74c4762a1bSJed Brown for (i = 0; i < nv; i++) { 759566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghostvtex)); 76c4762a1bSJed Brown if (ghostvtex) continue; 77c4762a1bSJed Brown 789566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVecOffset(networkdm, vtx[i], ALL_COMPONENTS, &offset)); 799566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[i], ALL_COMPONENTS, NULL, NULL, &nvar)); 80c4762a1bSJed Brown for (j = 0; j < nvar; j++) { 81c4762a1bSJed Brown row = offset + j; 829566063dSJacob Faibussowitsch PetscCall(MatSetValues(J, 1, &row, 1, &row, &one, ADD_VALUES)); 83c4762a1bSJed Brown } 84c4762a1bSJed Brown } 859566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 869566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 87c4762a1bSJed Brown 889566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localX)); 89c4762a1bSJed Brown PetscFunctionReturn(0); 90c4762a1bSJed Brown } 91c4762a1bSJed Brown 92c4762a1bSJed Brown /* Dummy equation localF(X) = localX - localXold */ 939371c9d4SSatish Balay PetscErrorCode FormFunction_Dummy(DM networkdm, Vec localX, Vec localF, PetscInt nv, PetscInt ne, const PetscInt *vtx, const PetscInt *edges, void *appctx) { 94c4762a1bSJed Brown const PetscScalar *xarr, *xoldarr; 95c4762a1bSJed Brown PetscScalar *farr; 96c4762a1bSJed Brown PetscInt i, j, offset, nvar; 97c4762a1bSJed Brown PetscBool ghostvtex; 98c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 99c4762a1bSJed Brown Vec localXold = user->localXold; 100c4762a1bSJed Brown 101c4762a1bSJed Brown PetscFunctionBegin; 1029566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localX, &xarr)); 1039566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localXold, &xoldarr)); 1049566063dSJacob Faibussowitsch PetscCall(VecGetArray(localF, &farr)); 105c4762a1bSJed Brown 106c4762a1bSJed Brown for (i = 0; i < nv; i++) { 1079566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghostvtex)); 108c4762a1bSJed Brown if (ghostvtex) continue; 109c4762a1bSJed Brown 1109566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vtx[i], ALL_COMPONENTS, &offset)); 1119566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[i], ALL_COMPONENTS, NULL, NULL, &nvar)); 1129371c9d4SSatish Balay for (j = 0; j < nvar; j++) { farr[offset + j] = xarr[offset + j] - xoldarr[offset + j]; } 113c4762a1bSJed Brown } 114c4762a1bSJed Brown 1159566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localX, &xarr)); 1169566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localXold, &xoldarr)); 1179566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localF, &farr)); 118c4762a1bSJed Brown PetscFunctionReturn(0); 119c4762a1bSJed Brown } 120c4762a1bSJed Brown 1219371c9d4SSatish Balay PetscErrorCode FormFunction(SNES snes, Vec X, Vec F, void *appctx) { 122c4762a1bSJed Brown DM networkdm; 123c4762a1bSJed Brown Vec localX, localF; 1242bf73ac6SHong Zhang PetscInt nv, ne, v; 125c4762a1bSJed Brown const PetscInt *vtx, *edges; 126c4762a1bSJed Brown PetscMPIInt rank; 127c4762a1bSJed Brown MPI_Comm comm; 128c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 129c4762a1bSJed Brown UserCtx_Power appctx_power = (*user).appctx_power; 1302bf73ac6SHong Zhang AppCtx_Water appctx_water = (*user).appctx_water; 131c4762a1bSJed Brown 132c4762a1bSJed Brown PetscFunctionBegin; 1339566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &networkdm)); 1349566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)networkdm, &comm)); 1359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 136c4762a1bSJed Brown 1379566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localX)); 1389566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localF)); 1399566063dSJacob Faibussowitsch PetscCall(VecSet(F, 0.0)); 1409566063dSJacob Faibussowitsch PetscCall(VecSet(localF, 0.0)); 141c4762a1bSJed Brown 1429566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX)); 1439566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX)); 144c4762a1bSJed Brown 145c4762a1bSJed Brown /* Form Function for power subnetwork */ 1469566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 147c4762a1bSJed Brown if (user->subsnes_id == 1) { /* snes_water only */ 1489566063dSJacob Faibussowitsch PetscCall(FormFunction_Dummy(networkdm, localX, localF, nv, ne, vtx, edges, user)); 149c4762a1bSJed Brown } else { 1509566063dSJacob Faibussowitsch PetscCall(FormFunction_Power(networkdm, localX, localF, nv, ne, vtx, edges, &appctx_power)); 151c4762a1bSJed Brown } 152c4762a1bSJed Brown 153c4762a1bSJed Brown /* Form Function for water subnetwork */ 1549566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 1, &nv, &ne, &vtx, &edges)); 155c4762a1bSJed Brown if (user->subsnes_id == 0) { /* snes_power only */ 1569566063dSJacob Faibussowitsch PetscCall(FormFunction_Dummy(networkdm, localX, localF, nv, ne, vtx, edges, user)); 157c4762a1bSJed Brown } else { 1589566063dSJacob Faibussowitsch PetscCall(FormFunction_Water(networkdm, localX, localF, nv, ne, vtx, edges, NULL)); 159c4762a1bSJed Brown } 160c4762a1bSJed Brown 1612bf73ac6SHong Zhang /* Illustrate how to access the coupling vertex of the subnetworks without doing anything to F yet */ 1629566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 1632bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 1642bf73ac6SHong Zhang PetscInt key, ncomp, nvar, nconnedges, k, e, keye, goffset[3]; 165c4762a1bSJed Brown void *component; 1662bf73ac6SHong Zhang const PetscInt *connedges; 167c4762a1bSJed Brown 1689566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[v], ALL_COMPONENTS, NULL, NULL, &nvar)); 1699566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, vtx[v], &ncomp)); 17063a3b9bcSJacob Faibussowitsch /* printf(" [%d] coupling vertex[%" PetscInt_FMT "]: v %" PetscInt_FMT ", ncomp %" PetscInt_FMT "; nvar %" PetscInt_FMT "\n",rank,v,vtx[v], ncomp,nvar); */ 171c4762a1bSJed Brown 1722bf73ac6SHong Zhang for (k = 0; k < ncomp; k++) { 1739566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[v], k, &key, &component, &nvar)); 1749566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVecOffset(networkdm, vtx[v], k, &goffset[k])); 175c4762a1bSJed Brown 1762bf73ac6SHong Zhang /* Verify the coupling vertex is a powernet load vertex or a water vertex */ 1772bf73ac6SHong Zhang switch (k) { 1789371c9d4SSatish Balay case 0: 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); break; 1799371c9d4SSatish Balay case 1: 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"); break; 1809371c9d4SSatish Balay case 2: PetscCheck(key == appctx_water.compkey_vtx && nvar == 1 && goffset[2] == goffset[1], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not a water vertex"); break; 18163a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "k %" PetscInt_FMT " is wrong", k); 1822bf73ac6SHong Zhang } 18363a3b9bcSJacob Faibussowitsch /* printf(" [%d] coupling vertex[%" PetscInt_FMT "]: key %" PetscInt_FMT "; nvar %" PetscInt_FMT ", goffset %" PetscInt_FMT "\n",rank,v,key,nvar,goffset[k]); */ 1842bf73ac6SHong Zhang } 185c4762a1bSJed Brown 1862bf73ac6SHong Zhang /* Get its supporting edges */ 1879566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSupportingEdges(networkdm, vtx[v], &nconnedges, &connedges)); 18863a3b9bcSJacob Faibussowitsch /* printf("\n[%d] coupling vertex: nconnedges %" PetscInt_FMT "\n",rank,nconnedges); */ 189c4762a1bSJed Brown for (k = 0; k < nconnedges; k++) { 190c4762a1bSJed Brown e = connedges[k]; 1919566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, e, &ncomp)); 19263a3b9bcSJacob Faibussowitsch /* printf("\n [%d] connected edge[%" PetscInt_FMT "]=%" PetscInt_FMT " has ncomp %" PetscInt_FMT "\n",rank,k,e,ncomp); */ 1939566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, e, 0, &keye, &component, NULL)); 1949371c9d4SSatish Balay if (keye != appctx_water.compkey_edge) { PetscCheck(keye == appctx_power.compkey_branch, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not a power branch"); } 195c4762a1bSJed Brown } 196c4762a1bSJed Brown } 197c4762a1bSJed Brown 1989566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localX)); 199c4762a1bSJed Brown 2009566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localF, ADD_VALUES, F)); 2019566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localF, ADD_VALUES, F)); 2029566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localF)); 2032bf73ac6SHong Zhang #if 0 204dd400576SPatrick Sanan if (rank == 0) printf("F:\n"); 2059566063dSJacob Faibussowitsch PetscCall(VecView(F,PETSC_VIEWER_STDOUT_WORLD)); 2062bf73ac6SHong Zhang #endif 207c4762a1bSJed Brown PetscFunctionReturn(0); 208c4762a1bSJed Brown } 209c4762a1bSJed Brown 2109371c9d4SSatish Balay PetscErrorCode SetInitialGuess(DM networkdm, Vec X, void *appctx) { 2112bf73ac6SHong Zhang PetscInt nv, ne, i, j, ncomp, offset, key; 212c4762a1bSJed Brown const PetscInt *vtx, *edges; 213c4762a1bSJed Brown UserCtx *user = (UserCtx *)appctx; 214c4762a1bSJed Brown Vec localX = user->localXold; 215c4762a1bSJed Brown UserCtx_Power appctx_power = (*user).appctx_power; 2162bf73ac6SHong Zhang AppCtx_Water appctx_water = (*user).appctx_water; 2172bf73ac6SHong Zhang PetscBool ghost; 2182bf73ac6SHong Zhang PetscScalar *xarr; 2192bf73ac6SHong Zhang VERTEX_Power bus; 2202bf73ac6SHong Zhang VERTEX_Water vertex; 2212bf73ac6SHong Zhang void *component; 2222bf73ac6SHong Zhang GEN gen; 223c4762a1bSJed Brown 224c4762a1bSJed Brown PetscFunctionBegin; 2259566063dSJacob Faibussowitsch PetscCall(VecSet(X, 0.0)); 2269566063dSJacob Faibussowitsch PetscCall(VecSet(localX, 0.0)); 227c4762a1bSJed Brown 228c4762a1bSJed Brown /* Set initial guess for power subnetwork */ 2299566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 2309566063dSJacob Faibussowitsch PetscCall(SetInitialGuess_Power(networkdm, localX, nv, ne, vtx, edges, &appctx_power)); 231c4762a1bSJed Brown 232c4762a1bSJed Brown /* Set initial guess for water subnetwork */ 2339566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 1, &nv, &ne, &vtx, &edges)); 2349566063dSJacob Faibussowitsch PetscCall(SetInitialGuess_Water(networkdm, localX, nv, ne, vtx, edges, NULL)); 235c4762a1bSJed Brown 2362bf73ac6SHong Zhang /* Set initial guess at the coupling vertex */ 2379566063dSJacob Faibussowitsch PetscCall(VecGetArray(localX, &xarr)); 2389566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 2392bf73ac6SHong Zhang for (i = 0; i < nv; i++) { 2409566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghost)); 2412bf73ac6SHong Zhang if (ghost) continue; 2422bf73ac6SHong Zhang 2439566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, vtx[i], &ncomp)); 2442bf73ac6SHong Zhang for (j = 0; j < ncomp; j++) { 2459566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vtx[i], j, &offset)); 2469566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[i], j, &key, (void **)&component, NULL)); 2472bf73ac6SHong Zhang if (key == appctx_power.compkey_bus) { 2482bf73ac6SHong Zhang bus = (VERTEX_Power)(component); 2492bf73ac6SHong Zhang xarr[offset] = bus->va * PETSC_PI / 180.0; 2502bf73ac6SHong Zhang xarr[offset + 1] = bus->vm; 2512bf73ac6SHong Zhang } else if (key == appctx_power.compkey_gen) { 2522bf73ac6SHong Zhang gen = (GEN)(component); 2532bf73ac6SHong Zhang if (!gen->status) continue; 2542bf73ac6SHong Zhang xarr[offset + 1] = gen->vs; 2552bf73ac6SHong Zhang } else if (key == appctx_water.compkey_vtx) { 2562bf73ac6SHong Zhang vertex = (VERTEX_Water)(component); 2572bf73ac6SHong Zhang if (vertex->type == VERTEX_TYPE_JUNCTION) { 2582bf73ac6SHong Zhang xarr[offset] = 100; 2592bf73ac6SHong Zhang } else if (vertex->type == VERTEX_TYPE_RESERVOIR) { 2602bf73ac6SHong Zhang xarr[offset] = vertex->res.head; 2612bf73ac6SHong Zhang } else { 2622bf73ac6SHong Zhang xarr[offset] = vertex->tank.initlvl + vertex->tank.elev; 263c4762a1bSJed Brown } 2642bf73ac6SHong Zhang } 2652bf73ac6SHong Zhang } 2662bf73ac6SHong Zhang } 2679566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localX, &xarr)); 268c4762a1bSJed Brown 2699566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localX, ADD_VALUES, X)); 2709566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localX, ADD_VALUES, X)); 271c4762a1bSJed Brown PetscFunctionReturn(0); 272c4762a1bSJed Brown } 273c4762a1bSJed Brown 2749371c9d4SSatish Balay int main(int argc, char **argv) { 275c4762a1bSJed Brown DM networkdm; 276c4762a1bSJed Brown PetscLogStage stage[4]; 277d5c9c0c4SHong Zhang PetscMPIInt rank, size; 2782bf73ac6SHong Zhang PetscInt Nsubnet = 2, numVertices[2], numEdges[2], i, j, nv, ne, it_max = 10; 279c4762a1bSJed Brown const PetscInt *vtx, *edges; 280c4762a1bSJed Brown Vec X, F; 281c4762a1bSJed Brown SNES snes, snes_power, snes_water; 282c4762a1bSJed Brown Mat Jac; 2832bf73ac6SHong Zhang PetscBool ghost, viewJ = PETSC_FALSE, viewX = PETSC_FALSE, viewDM = PETSC_FALSE, test = PETSC_FALSE, distribute = PETSC_TRUE, flg; 284c4762a1bSJed Brown UserCtx user; 285c4762a1bSJed Brown SNESConvergedReason reason; 286c4762a1bSJed Brown 287c4762a1bSJed Brown /* Power subnetwork */ 288c4762a1bSJed Brown UserCtx_Power *appctx_power = &user.appctx_power; 289c4762a1bSJed Brown char pfdata_file[PETSC_MAX_PATH_LEN] = "power/case9.m"; 290c4762a1bSJed Brown PFDATA *pfdata = NULL; 2912bf73ac6SHong Zhang PetscInt genj, loadj, *edgelist_power = NULL, power_netnum; 292c4762a1bSJed Brown PetscScalar Sbase = 0.0; 293c4762a1bSJed Brown 294c4762a1bSJed Brown /* Water subnetwork */ 295c4762a1bSJed Brown AppCtx_Water *appctx_water = &user.appctx_water; 296c4762a1bSJed Brown WATERDATA *waterdata = NULL; 297c4762a1bSJed Brown char waterdata_file[PETSC_MAX_PATH_LEN] = "water/sample1.inp"; 2982bf73ac6SHong Zhang PetscInt *edgelist_water = NULL, water_netnum; 299c4762a1bSJed Brown 3002bf73ac6SHong Zhang /* Shared vertices between subnetworks */ 3012bf73ac6SHong Zhang PetscInt power_svtx, water_svtx; 302c4762a1bSJed Brown 303327415f7SBarry Smith PetscFunctionBeginUser; 3049566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, "ex1options", help)); 3059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 3069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); 307c4762a1bSJed Brown 308c4762a1bSJed Brown /* (1) Read Data - Only rank 0 reads the data */ 309c4762a1bSJed Brown /*--------------------------------------------*/ 3109566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Read Data", &stage[0])); 3119566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[0])); 312c4762a1bSJed Brown 3132bf73ac6SHong Zhang for (i = 0; i < Nsubnet; i++) { 314c4762a1bSJed Brown numVertices[i] = 0; 315c4762a1bSJed Brown numEdges[i] = 0; 316c4762a1bSJed Brown } 317c4762a1bSJed Brown 3182bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE FIRST SUBNETWORK: Electric Power Grid */ 3192bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 3209566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-pfdata", pfdata_file, PETSC_MAX_PATH_LEN - 1, NULL)); 3219566063dSJacob Faibussowitsch PetscCall(PetscNew(&pfdata)); 3229566063dSJacob Faibussowitsch PetscCall(PFReadMatPowerData(pfdata, pfdata_file)); 323*48a46eb9SPierre 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)); 324c4762a1bSJed Brown Sbase = pfdata->sbase; 3252bf73ac6SHong Zhang if (rank == 0) { /* proc[0] will create Electric Power Grid */ 326c4762a1bSJed Brown numEdges[0] = pfdata->nbranch; 327c4762a1bSJed Brown numVertices[0] = pfdata->nbus; 328c4762a1bSJed Brown 3299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * numEdges[0], &edgelist_power)); 3309566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Power(pfdata, edgelist_power)); 331c4762a1bSJed Brown } 332c4762a1bSJed Brown /* Broadcast power Sbase to all processors */ 3339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&Sbase, 1, MPIU_SCALAR, 0, PETSC_COMM_WORLD)); 334c4762a1bSJed Brown appctx_power->Sbase = Sbase; 335c4762a1bSJed Brown appctx_power->jac_error = PETSC_FALSE; 336c4762a1bSJed Brown /* If external option activated. Introduce error in jacobian */ 3379566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-jac_error", &appctx_power->jac_error)); 338c4762a1bSJed Brown 3392bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE SECOND SUBNETWORK: Water */ 3402bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 3419566063dSJacob Faibussowitsch PetscCall(PetscNew(&waterdata)); 3429566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-waterdata", waterdata_file, PETSC_MAX_PATH_LEN - 1, NULL)); 3439566063dSJacob Faibussowitsch PetscCall(WaterReadData(waterdata, waterdata_file)); 3442bf73ac6SHong Zhang if (size == 1 || (size > 1 && rank == 1)) { 3459566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(2 * waterdata->nedge, &edgelist_water)); 3469566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Water(waterdata, edgelist_water)); 347c4762a1bSJed Brown numEdges[1] = waterdata->nedge; 348c4762a1bSJed Brown numVertices[1] = waterdata->nvertex; 349c4762a1bSJed Brown } 3502bf73ac6SHong Zhang PetscLogStagePop(); 351c4762a1bSJed Brown 3522bf73ac6SHong Zhang /* (2) Create a network consist of two subnetworks */ 3532bf73ac6SHong Zhang /*-------------------------------------------------*/ 3549566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Net Setup", &stage[1])); 3559566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[1])); 356c4762a1bSJed Brown 3579566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewDM", &viewDM, NULL)); 3589566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test", &test, NULL)); 3599566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-distribute", &distribute, NULL)); 360c4762a1bSJed Brown 361c4762a1bSJed Brown /* Create an empty network object */ 3629566063dSJacob Faibussowitsch PetscCall(DMNetworkCreate(PETSC_COMM_WORLD, &networkdm)); 363c4762a1bSJed Brown 364c4762a1bSJed Brown /* Register the components in the network */ 3659566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "branchstruct", sizeof(struct _p_EDGE_Power), &appctx_power->compkey_branch)); 3669566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "busstruct", sizeof(struct _p_VERTEX_Power), &appctx_power->compkey_bus)); 3679566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "genstruct", sizeof(struct _p_GEN), &appctx_power->compkey_gen)); 3689566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "loadstruct", sizeof(struct _p_LOAD), &appctx_power->compkey_load)); 369c4762a1bSJed Brown 3709566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "edge_water", sizeof(struct _p_EDGE_Water), &appctx_water->compkey_edge)); 3719566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "vertex_water", sizeof(struct _p_VERTEX_Water), &appctx_water->compkey_vtx)); 3722bf73ac6SHong Zhang #if 0 3739566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_branch %d\n",appctx_power->compkey_branch)); 3749566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_bus %d\n",appctx_power->compkey_bus)); 3759566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_gen %d\n",appctx_power->compkey_gen)); 3769566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_load %d\n",appctx_power->compkey_load)); 3779566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"water->compkey_edge %d\n",appctx_water->compkey_edge)); 3789566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"water->compkey_vtx %d\n",appctx_water->compkey_vtx)); 3792bf73ac6SHong Zhang #endif 38063a3b9bcSJacob 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])); 3819566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT)); 382c4762a1bSJed Brown 3839566063dSJacob Faibussowitsch PetscCall(DMNetworkSetNumSubNetworks(networkdm, PETSC_DECIDE, Nsubnet)); 3849566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, "power", numEdges[0], edgelist_power, &power_netnum)); 3859566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, "water", numEdges[1], edgelist_water, &water_netnum)); 386c4762a1bSJed Brown 3872bf73ac6SHong Zhang /* vertex subnet[0].4 shares with vertex subnet[1].0 */ 3889371c9d4SSatish Balay power_svtx = 4; 3899371c9d4SSatish Balay water_svtx = 0; 3909566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSharedVertices(networkdm, power_netnum, water_netnum, 1, &power_svtx, &water_svtx)); 391c4762a1bSJed Brown 392c4762a1bSJed Brown /* Set up the network layout */ 3939566063dSJacob Faibussowitsch PetscCall(DMNetworkLayoutSetUp(networkdm)); 394c4762a1bSJed Brown 395c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE POWER SUBNETWORK */ 3962bf73ac6SHong Zhang /*-------------------------------------------------------*/ 3979371c9d4SSatish Balay genj = 0; 3989371c9d4SSatish Balay loadj = 0; 3999566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, power_netnum, &nv, &ne, &vtx, &edges)); 4002bf73ac6SHong Zhang 401*48a46eb9SPierre Jolivet for (i = 0; i < ne; i++) PetscCall(DMNetworkAddComponent(networkdm, edges[i], appctx_power->compkey_branch, &pfdata->branch[i], 0)); 402c4762a1bSJed Brown 403c4762a1bSJed Brown for (i = 0; i < nv; i++) { 4049566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &flg)); 4052bf73ac6SHong Zhang if (flg) continue; 4062bf73ac6SHong Zhang 4079566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_bus, &pfdata->bus[i], 2)); 408c4762a1bSJed Brown if (pfdata->bus[i].ngen) { 409*48a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i].ngen; j++) PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_gen, &pfdata->gen[genj++], 0)); 410c4762a1bSJed Brown } 411c4762a1bSJed Brown if (pfdata->bus[i].nload) { 412*48a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i].nload; j++) PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_load, &pfdata->load[loadj++], 0)); 413c4762a1bSJed Brown } 414c4762a1bSJed Brown } 415c4762a1bSJed Brown 416c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE WATER SUBNETWORK */ 4172bf73ac6SHong Zhang /*-------------------------------------------------------*/ 4189566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, water_netnum, &nv, &ne, &vtx, &edges)); 419*48a46eb9SPierre Jolivet for (i = 0; i < ne; i++) PetscCall(DMNetworkAddComponent(networkdm, edges[i], appctx_water->compkey_edge, &waterdata->edge[i], 0)); 420c4762a1bSJed Brown 421c4762a1bSJed Brown for (i = 0; i < nv; i++) { 4229566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &flg)); 4232bf73ac6SHong Zhang if (flg) continue; 4242bf73ac6SHong Zhang 4259566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_water->compkey_vtx, &waterdata->vertex[i], 1)); 426c4762a1bSJed Brown } 4272bf73ac6SHong Zhang 428eac198afSGetnet /* 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 */ 4292bf73ac6SHong Zhang /*----------------------------------------------------------------------------------------------------------------------------*/ 4309566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 4312bf73ac6SHong Zhang for (i = 0; i < nv; i++) { 4322bf73ac6SHong Zhang /* power */ 4339566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_bus, &pfdata->bus[4], 2)); 4342bf73ac6SHong Zhang /* bus[4] is a load, add its component */ 4359566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_load, &pfdata->load[0], 0)); 4362bf73ac6SHong Zhang 4372bf73ac6SHong Zhang /* water */ 4389566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_water->compkey_vtx, &waterdata->vertex[0], 1)); 439c4762a1bSJed Brown } 440c4762a1bSJed Brown 441c4762a1bSJed Brown /* Set up DM for use */ 4429566063dSJacob Faibussowitsch PetscCall(DMSetUp(networkdm)); 443c4762a1bSJed Brown if (viewDM) { 4449566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nAfter DMSetUp, DMView:\n")); 4459566063dSJacob Faibussowitsch PetscCall(DMView(networkdm, PETSC_VIEWER_STDOUT_WORLD)); 446c4762a1bSJed Brown } 447c4762a1bSJed Brown 448c4762a1bSJed Brown /* Free user objects */ 4499566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_power)); 4509566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->bus)); 4519566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->gen)); 4529566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->branch)); 4539566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->load)); 4549566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata)); 4552bf73ac6SHong Zhang 4569566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_water)); 4579566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->vertex)); 4589566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->edge)); 4599566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata)); 460c4762a1bSJed Brown 461d5c9c0c4SHong Zhang /* Re-distribute networkdm to multiple processes for better job balance */ 4622bf73ac6SHong Zhang if (size > 1 && distribute) { 4639566063dSJacob Faibussowitsch PetscCall(DMNetworkDistribute(&networkdm, 0)); 464c4762a1bSJed Brown if (viewDM) { 4659566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nAfter DMNetworkDistribute, DMView:\n")); 4669566063dSJacob Faibussowitsch PetscCall(DMView(networkdm, PETSC_VIEWER_STDOUT_WORLD)); 467c4762a1bSJed Brown } 468d5c9c0c4SHong Zhang } 469c4762a1bSJed Brown 4702bf73ac6SHong Zhang /* Test DMNetworkGetSubnetwork() and DMNetworkGetSubnetworkSharedVertices() */ 471c4762a1bSJed Brown if (test) { 4722bf73ac6SHong Zhang PetscInt v, gidx; 4739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 4742bf73ac6SHong Zhang for (i = 0; i < Nsubnet; i++) { 4759566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, i, &nv, &ne, &vtx, &edges)); 47663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] After distribute, subnet[%" PetscInt_FMT "] ne %" PetscInt_FMT ", nv %" PetscInt_FMT "\n", rank, i, ne, nv)); 4779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 478c4762a1bSJed Brown 4792bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 4809566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[v], &ghost)); 4819566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm, vtx[v], &gidx)); 48263a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] subnet[%" PetscInt_FMT "] v %" PetscInt_FMT " %" PetscInt_FMT "; ghost %d\n", rank, i, vtx[v], gidx, ghost)); 483c4762a1bSJed Brown } 4849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 485c4762a1bSJed Brown } 4869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 4872bf73ac6SHong Zhang 4889566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 48963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] After distribute, num of shared vertices nsv = %" PetscInt_FMT "\n", rank, nv)); 4902bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 4919566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm, vtx[v], &gidx)); 49263a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] sv %" PetscInt_FMT ", gidx=%" PetscInt_FMT "\n", rank, vtx[v], gidx)); 4932bf73ac6SHong Zhang } 4949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 495c4762a1bSJed Brown } 496c4762a1bSJed Brown 4972bf73ac6SHong Zhang /* Create solution vector X */ 4989566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(networkdm, &X)); 4999566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X, &F)); 5009566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &user.localXold)); 5012bf73ac6SHong Zhang PetscLogStagePop(); 502c4762a1bSJed Brown 503c4762a1bSJed Brown /* (3) Setup Solvers */ 504c4762a1bSJed Brown /*-------------------*/ 5059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewJ", &viewJ, NULL)); 5069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewX", &viewX, NULL)); 507c4762a1bSJed Brown 5089566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Setup", &stage[2])); 5099566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[2])); 510c4762a1bSJed Brown 5119566063dSJacob Faibussowitsch PetscCall(SetInitialGuess(networkdm, X, &user)); 512c4762a1bSJed Brown 513c4762a1bSJed Brown /* Create coupled snes */ 514c4762a1bSJed Brown /*-------------------- */ 5159566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_coupled setup ......\n")); 5162bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 5179566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes)); 5189566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, networkdm)); 5199566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes, "coupled_")); 5209566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, F, FormFunction, &user)); 5219566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, UserMonitor, &user, NULL)); 5229566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes)); 523c4762a1bSJed Brown 524c4762a1bSJed Brown if (viewJ) { 525c4762a1bSJed Brown /* View Jac structure */ 5269566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &Jac, NULL, NULL, NULL)); 5279566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 528c4762a1bSJed Brown } 529c4762a1bSJed Brown 530c4762a1bSJed Brown if (viewX) { 5319566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Solution:\n")); 5329566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 533c4762a1bSJed Brown } 534c4762a1bSJed Brown 535c4762a1bSJed Brown if (viewJ) { 536c4762a1bSJed Brown /* View assembled Jac */ 5379566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 538c4762a1bSJed Brown } 539c4762a1bSJed Brown 540c4762a1bSJed Brown /* Create snes_power */ 541c4762a1bSJed Brown /*-------------------*/ 5429566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_power setup ......\n")); 543c4762a1bSJed Brown 544c4762a1bSJed Brown user.subsnes_id = 0; 5459566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes_power)); 5469566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_power, networkdm)); 5479566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_power, "power_")); 5489566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_power, F, FormFunction, &user)); 5499566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_power, UserMonitor, &user, NULL)); 550c4762a1bSJed Brown 551c4762a1bSJed Brown /* Use user-provide Jacobian */ 5529566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(networkdm, &Jac)); 5539566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes_power, Jac, Jac, FormJacobian_subPower, &user)); 5549566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_power)); 555c4762a1bSJed Brown 556c4762a1bSJed Brown if (viewX) { 5579566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Power Solution:\n")); 5589566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 559c4762a1bSJed Brown } 560c4762a1bSJed Brown if (viewJ) { 5619566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Power Jac:\n")); 5629566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes_power, &Jac, NULL, NULL, NULL)); 5639566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 5649566063dSJacob Faibussowitsch /* PetscCall(MatView(Jac,PETSC_VIEWER_STDOUT_WORLD)); */ 565c4762a1bSJed Brown } 566c4762a1bSJed Brown 567c4762a1bSJed Brown /* Create snes_water */ 568c4762a1bSJed Brown /*-------------------*/ 5699566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_water setup......\n")); 570c4762a1bSJed Brown 571c4762a1bSJed Brown user.subsnes_id = 1; 5729566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes_water)); 5739566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_water, networkdm)); 5749566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_water, "water_")); 5759566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_water, F, FormFunction, &user)); 5769566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_water, UserMonitor, &user, NULL)); 5779566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_water)); 578c4762a1bSJed Brown 579c4762a1bSJed Brown if (viewX) { 5809566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Water Solution:\n")); 5819566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 582c4762a1bSJed Brown } 5839566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 584c4762a1bSJed Brown 585c4762a1bSJed Brown /* (4) Solve */ 586c4762a1bSJed Brown /*-----------*/ 5879566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Solve", &stage[3])); 5889566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[3])); 589c4762a1bSJed Brown user.it = 0; 590c4762a1bSJed Brown reason = SNES_DIVERGED_DTOL; 591c4762a1bSJed Brown while (user.it < it_max && (PetscInt)reason < 0) { 592c4762a1bSJed Brown #if 0 593c4762a1bSJed Brown user.subsnes_id = 0; 5949566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_power,NULL,X)); 595c4762a1bSJed Brown 596c4762a1bSJed Brown user.subsnes_id = 1; 5979566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_water,NULL,X)); 598c4762a1bSJed Brown #endif 5992bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 6009566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes, NULL, X)); 601c4762a1bSJed Brown 6029566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(snes, &reason)); 603c4762a1bSJed Brown user.it++; 604c4762a1bSJed Brown } 60563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Coupled_SNES converged in %" PetscInt_FMT " iterations\n", user.it)); 606c4762a1bSJed Brown if (viewX) { 6079566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Final Solution:\n")); 6089566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 609c4762a1bSJed Brown } 6109566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 611c4762a1bSJed Brown 612c4762a1bSJed Brown /* Free objects */ 613c4762a1bSJed Brown /* -------------*/ 6149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X)); 6159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&F)); 6169566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &user.localXold)); 617c4762a1bSJed Brown 6189566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes)); 6199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Jac)); 6209566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_power)); 6219566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_water)); 622c4762a1bSJed Brown 6239566063dSJacob Faibussowitsch PetscCall(DMDestroy(&networkdm)); 6249566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 625b122ec5aSJacob Faibussowitsch return 0; 626c4762a1bSJed Brown } 627c4762a1bSJed Brown 628c4762a1bSJed Brown /*TEST 629c4762a1bSJed Brown 630c4762a1bSJed Brown build: 631dfd57a17SPierre Jolivet requires: !complex double defined(PETSC_HAVE_ATTRIBUTEALIGNED) 632c4762a1bSJed Brown depends: power/PFReadData.c power/pffunctions.c water/waterreaddata.c water/waterfunctions.c 633c4762a1bSJed Brown 634c4762a1bSJed Brown test: 6352bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -viewDM 636c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 637c4762a1bSJed Brown output_file: output/ex1.out 638c4762a1bSJed Brown 639c4762a1bSJed Brown test: 640c4762a1bSJed Brown suffix: 2 641c4762a1bSJed Brown nsize: 3 6422bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type parmetis 643c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 644d5c9c0c4SHong Zhang output_file: output/ex1_2.out 6452bf73ac6SHong Zhang requires: parmetis 6462bf73ac6SHong Zhang 6472bf73ac6SHong Zhang # test: 6482bf73ac6SHong Zhang # suffix: 3 6492bf73ac6SHong Zhang # nsize: 3 6502bf73ac6SHong Zhang # args: -coupled_snes_converged_reason -options_left no -distribute false 6512bf73ac6SHong Zhang # localrunfiles: ex1options power/case9.m water/sample1.inp 6522bf73ac6SHong Zhang # output_file: output/ex1_2.out 653d5c9c0c4SHong Zhang 654d5c9c0c4SHong Zhang test: 6552bf73ac6SHong Zhang suffix: 4 6562bf73ac6SHong Zhang nsize: 4 6572bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type simple -viewDM 658d5c9c0c4SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 6592bf73ac6SHong Zhang output_file: output/ex1_4.out 660c4762a1bSJed Brown 661c4762a1bSJed Brown TEST*/ 662