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)); 44*3ba16761SJacob 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)); 91*3ba16761SJacob 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)); 121*3ba16761SJacob 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 218*3ba16761SJacob 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)); 283*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 284c4762a1bSJed Brown } 285c4762a1bSJed Brown 286d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 287d71ae5a4SJacob Faibussowitsch { 288c4762a1bSJed Brown DM networkdm; 289c4762a1bSJed Brown PetscLogStage stage[4]; 290d5c9c0c4SHong Zhang PetscMPIInt rank, size; 2912bf73ac6SHong Zhang PetscInt Nsubnet = 2, numVertices[2], numEdges[2], i, j, nv, ne, it_max = 10; 292c4762a1bSJed Brown const PetscInt *vtx, *edges; 293c4762a1bSJed Brown Vec X, F; 294c4762a1bSJed Brown SNES snes, snes_power, snes_water; 295c4762a1bSJed Brown Mat Jac; 2962bf73ac6SHong Zhang PetscBool ghost, viewJ = PETSC_FALSE, viewX = PETSC_FALSE, viewDM = PETSC_FALSE, test = PETSC_FALSE, distribute = PETSC_TRUE, flg; 297c4762a1bSJed Brown UserCtx user; 298c4762a1bSJed Brown SNESConvergedReason reason; 299c4762a1bSJed Brown 300c4762a1bSJed Brown /* Power subnetwork */ 301c4762a1bSJed Brown UserCtx_Power *appctx_power = &user.appctx_power; 302c4762a1bSJed Brown char pfdata_file[PETSC_MAX_PATH_LEN] = "power/case9.m"; 303c4762a1bSJed Brown PFDATA *pfdata = NULL; 3042bf73ac6SHong Zhang PetscInt genj, loadj, *edgelist_power = NULL, power_netnum; 305c4762a1bSJed Brown PetscScalar Sbase = 0.0; 306c4762a1bSJed Brown 307c4762a1bSJed Brown /* Water subnetwork */ 308c4762a1bSJed Brown AppCtx_Water *appctx_water = &user.appctx_water; 309c4762a1bSJed Brown WATERDATA *waterdata = NULL; 310c4762a1bSJed Brown char waterdata_file[PETSC_MAX_PATH_LEN] = "water/sample1.inp"; 3112bf73ac6SHong Zhang PetscInt *edgelist_water = NULL, water_netnum; 312c4762a1bSJed Brown 3132bf73ac6SHong Zhang /* Shared vertices between subnetworks */ 3142bf73ac6SHong Zhang PetscInt power_svtx, water_svtx; 315c4762a1bSJed Brown 316327415f7SBarry Smith PetscFunctionBeginUser; 3179566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, "ex1options", help)); 3189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 3199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); 320c4762a1bSJed Brown 321c4762a1bSJed Brown /* (1) Read Data - Only rank 0 reads the data */ 3229566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Read Data", &stage[0])); 3239566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[0])); 324c4762a1bSJed Brown 3252bf73ac6SHong Zhang for (i = 0; i < Nsubnet; i++) { 326c4762a1bSJed Brown numVertices[i] = 0; 327c4762a1bSJed Brown numEdges[i] = 0; 328c4762a1bSJed Brown } 329c4762a1bSJed Brown 3302bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE FIRST SUBNETWORK: Electric Power Grid */ 3312bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 3329566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-pfdata", pfdata_file, PETSC_MAX_PATH_LEN - 1, NULL)); 3339566063dSJacob Faibussowitsch PetscCall(PetscNew(&pfdata)); 3349566063dSJacob Faibussowitsch PetscCall(PFReadMatPowerData(pfdata, pfdata_file)); 33548a46eb9SPierre 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)); 336c4762a1bSJed Brown Sbase = pfdata->sbase; 3372bf73ac6SHong Zhang if (rank == 0) { /* proc[0] will create Electric Power Grid */ 338c4762a1bSJed Brown numEdges[0] = pfdata->nbranch; 339c4762a1bSJed Brown numVertices[0] = pfdata->nbus; 340c4762a1bSJed Brown 3419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * numEdges[0], &edgelist_power)); 3429566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Power(pfdata, edgelist_power)); 343c4762a1bSJed Brown } 344c4762a1bSJed Brown /* Broadcast power Sbase to all processors */ 3459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&Sbase, 1, MPIU_SCALAR, 0, PETSC_COMM_WORLD)); 346c4762a1bSJed Brown appctx_power->Sbase = Sbase; 347c4762a1bSJed Brown appctx_power->jac_error = PETSC_FALSE; 348c4762a1bSJed Brown /* If external option activated. Introduce error in jacobian */ 3499566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-jac_error", &appctx_power->jac_error)); 350c4762a1bSJed Brown 3512bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE SECOND SUBNETWORK: Water */ 3522bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 3539566063dSJacob Faibussowitsch PetscCall(PetscNew(&waterdata)); 3549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-waterdata", waterdata_file, PETSC_MAX_PATH_LEN - 1, NULL)); 3559566063dSJacob Faibussowitsch PetscCall(WaterReadData(waterdata, waterdata_file)); 3562bf73ac6SHong Zhang if (size == 1 || (size > 1 && rank == 1)) { 3579566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(2 * waterdata->nedge, &edgelist_water)); 3589566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Water(waterdata, edgelist_water)); 359c4762a1bSJed Brown numEdges[1] = waterdata->nedge; 360c4762a1bSJed Brown numVertices[1] = waterdata->nvertex; 361c4762a1bSJed Brown } 362*3ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePop()); 363c4762a1bSJed Brown 3642bf73ac6SHong Zhang /* (2) Create a network consist of two subnetworks */ 3659566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Net Setup", &stage[1])); 3669566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[1])); 367c4762a1bSJed Brown 3689566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewDM", &viewDM, NULL)); 3699566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-test", &test, NULL)); 3709566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-distribute", &distribute, NULL)); 371c4762a1bSJed Brown 372c4762a1bSJed Brown /* Create an empty network object */ 3739566063dSJacob Faibussowitsch PetscCall(DMNetworkCreate(PETSC_COMM_WORLD, &networkdm)); 374c4762a1bSJed Brown 375c4762a1bSJed Brown /* Register the components in the network */ 3769566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "branchstruct", sizeof(struct _p_EDGE_Power), &appctx_power->compkey_branch)); 3779566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "busstruct", sizeof(struct _p_VERTEX_Power), &appctx_power->compkey_bus)); 3789566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "genstruct", sizeof(struct _p_GEN), &appctx_power->compkey_gen)); 3799566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "loadstruct", sizeof(struct _p_LOAD), &appctx_power->compkey_load)); 380c4762a1bSJed Brown 3819566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "edge_water", sizeof(struct _p_EDGE_Water), &appctx_water->compkey_edge)); 3829566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "vertex_water", sizeof(struct _p_VERTEX_Water), &appctx_water->compkey_vtx)); 3832bf73ac6SHong Zhang #if 0 3849566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_branch %d\n",appctx_power->compkey_branch)); 3859566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_bus %d\n",appctx_power->compkey_bus)); 3869566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_gen %d\n",appctx_power->compkey_gen)); 3879566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_load %d\n",appctx_power->compkey_load)); 3889566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"water->compkey_edge %d\n",appctx_water->compkey_edge)); 3899566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"water->compkey_vtx %d\n",appctx_water->compkey_vtx)); 3902bf73ac6SHong Zhang #endif 39163a3b9bcSJacob 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])); 3929566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT)); 393c4762a1bSJed Brown 3949566063dSJacob Faibussowitsch PetscCall(DMNetworkSetNumSubNetworks(networkdm, PETSC_DECIDE, Nsubnet)); 3959566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, "power", numEdges[0], edgelist_power, &power_netnum)); 3969566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, "water", numEdges[1], edgelist_water, &water_netnum)); 397c4762a1bSJed Brown 3982bf73ac6SHong Zhang /* vertex subnet[0].4 shares with vertex subnet[1].0 */ 3999371c9d4SSatish Balay power_svtx = 4; 4009371c9d4SSatish Balay water_svtx = 0; 4019566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSharedVertices(networkdm, power_netnum, water_netnum, 1, &power_svtx, &water_svtx)); 402c4762a1bSJed Brown 403c4762a1bSJed Brown /* Set up the network layout */ 4049566063dSJacob Faibussowitsch PetscCall(DMNetworkLayoutSetUp(networkdm)); 405c4762a1bSJed Brown 406c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE POWER SUBNETWORK */ 4079371c9d4SSatish Balay genj = 0; 4089371c9d4SSatish Balay loadj = 0; 4099566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, power_netnum, &nv, &ne, &vtx, &edges)); 4102bf73ac6SHong Zhang 41148a46eb9SPierre Jolivet for (i = 0; i < ne; i++) PetscCall(DMNetworkAddComponent(networkdm, edges[i], appctx_power->compkey_branch, &pfdata->branch[i], 0)); 412c4762a1bSJed Brown 413c4762a1bSJed Brown for (i = 0; i < nv; i++) { 4149566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &flg)); 4152bf73ac6SHong Zhang if (flg) continue; 4162bf73ac6SHong Zhang 4179566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_bus, &pfdata->bus[i], 2)); 418c4762a1bSJed Brown if (pfdata->bus[i].ngen) { 41948a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i].ngen; j++) PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_gen, &pfdata->gen[genj++], 0)); 420c4762a1bSJed Brown } 421c4762a1bSJed Brown if (pfdata->bus[i].nload) { 42248a46eb9SPierre Jolivet for (j = 0; j < pfdata->bus[i].nload; j++) PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_load, &pfdata->load[loadj++], 0)); 423c4762a1bSJed Brown } 424c4762a1bSJed Brown } 425c4762a1bSJed Brown 426c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE WATER SUBNETWORK */ 4279566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, water_netnum, &nv, &ne, &vtx, &edges)); 42848a46eb9SPierre Jolivet for (i = 0; i < ne; i++) PetscCall(DMNetworkAddComponent(networkdm, edges[i], appctx_water->compkey_edge, &waterdata->edge[i], 0)); 429c4762a1bSJed Brown 430c4762a1bSJed Brown for (i = 0; i < nv; i++) { 4319566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &flg)); 4322bf73ac6SHong Zhang if (flg) continue; 4332bf73ac6SHong Zhang 4349566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_water->compkey_vtx, &waterdata->vertex[i], 1)); 435c4762a1bSJed Brown } 4362bf73ac6SHong Zhang 437eac198afSGetnet /* 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 */ 4389566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 4392bf73ac6SHong Zhang for (i = 0; i < nv; i++) { 4402bf73ac6SHong Zhang /* power */ 4419566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_bus, &pfdata->bus[4], 2)); 4422bf73ac6SHong Zhang /* bus[4] is a load, add its component */ 4439566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_power->compkey_load, &pfdata->load[0], 0)); 4442bf73ac6SHong Zhang 4452bf73ac6SHong Zhang /* water */ 4469566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, vtx[i], appctx_water->compkey_vtx, &waterdata->vertex[0], 1)); 447c4762a1bSJed Brown } 448c4762a1bSJed Brown 449c4762a1bSJed Brown /* Set up DM for use */ 4509566063dSJacob Faibussowitsch PetscCall(DMSetUp(networkdm)); 451c4762a1bSJed Brown if (viewDM) { 4529566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nAfter DMSetUp, DMView:\n")); 4539566063dSJacob Faibussowitsch PetscCall(DMView(networkdm, PETSC_VIEWER_STDOUT_WORLD)); 454c4762a1bSJed Brown } 455c4762a1bSJed Brown 456c4762a1bSJed Brown /* Free user objects */ 4579566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_power)); 4589566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->bus)); 4599566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->gen)); 4609566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->branch)); 4619566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->load)); 4629566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata)); 4632bf73ac6SHong Zhang 4649566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_water)); 4659566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->vertex)); 4669566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->edge)); 4679566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata)); 468c4762a1bSJed Brown 469d5c9c0c4SHong Zhang /* Re-distribute networkdm to multiple processes for better job balance */ 4702bf73ac6SHong Zhang if (size > 1 && distribute) { 4719566063dSJacob Faibussowitsch PetscCall(DMNetworkDistribute(&networkdm, 0)); 472c4762a1bSJed Brown if (viewDM) { 4739566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nAfter DMNetworkDistribute, DMView:\n")); 4749566063dSJacob Faibussowitsch PetscCall(DMView(networkdm, PETSC_VIEWER_STDOUT_WORLD)); 475c4762a1bSJed Brown } 476d5c9c0c4SHong Zhang } 477c4762a1bSJed Brown 4782bf73ac6SHong Zhang /* Test DMNetworkGetSubnetwork() and DMNetworkGetSubnetworkSharedVertices() */ 479c4762a1bSJed Brown if (test) { 4802bf73ac6SHong Zhang PetscInt v, gidx; 4819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 4822bf73ac6SHong Zhang for (i = 0; i < Nsubnet; i++) { 4839566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, i, &nv, &ne, &vtx, &edges)); 48463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] After distribute, subnet[%" PetscInt_FMT "] ne %" PetscInt_FMT ", nv %" PetscInt_FMT "\n", rank, i, ne, nv)); 4859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 486c4762a1bSJed Brown 4872bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 4889566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[v], &ghost)); 4899566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm, vtx[v], &gidx)); 49063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] subnet[%" PetscInt_FMT "] v %" PetscInt_FMT " %" PetscInt_FMT "; ghost %d\n", rank, i, vtx[v], gidx, ghost)); 491c4762a1bSJed Brown } 4929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 493c4762a1bSJed Brown } 4949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 4952bf73ac6SHong Zhang 4969566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm, &nv, &vtx)); 49763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] After distribute, num of shared vertices nsv = %" PetscInt_FMT "\n", rank, nv)); 4982bf73ac6SHong Zhang for (v = 0; v < nv; v++) { 4999566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm, vtx[v], &gidx)); 50063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] sv %" PetscInt_FMT ", gidx=%" PetscInt_FMT "\n", rank, vtx[v], gidx)); 5012bf73ac6SHong Zhang } 5029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 503c4762a1bSJed Brown } 504c4762a1bSJed Brown 5052bf73ac6SHong Zhang /* Create solution vector X */ 5069566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(networkdm, &X)); 5079566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X, &F)); 5089566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &user.localXold)); 509*3ba16761SJacob Faibussowitsch PetscCall(PetscLogStagePop()); 510c4762a1bSJed Brown 511c4762a1bSJed Brown /* (3) Setup Solvers */ 5129566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewJ", &viewJ, NULL)); 5139566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewX", &viewX, NULL)); 514c4762a1bSJed Brown 5159566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Setup", &stage[2])); 5169566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[2])); 517c4762a1bSJed Brown 5189566063dSJacob Faibussowitsch PetscCall(SetInitialGuess(networkdm, X, &user)); 519c4762a1bSJed Brown 520c4762a1bSJed Brown /* Create coupled snes */ 5219566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_coupled setup ......\n")); 5222bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 5239566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes)); 5249566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, networkdm)); 5259566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes, "coupled_")); 5269566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, F, FormFunction, &user)); 5279566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, UserMonitor, &user, NULL)); 5289566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes)); 529c4762a1bSJed Brown 530c4762a1bSJed Brown if (viewJ) { 531c4762a1bSJed Brown /* View Jac structure */ 5329566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &Jac, NULL, NULL, NULL)); 5339566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 534c4762a1bSJed Brown } 535c4762a1bSJed Brown 536c4762a1bSJed Brown if (viewX) { 5379566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Solution:\n")); 5389566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 539c4762a1bSJed Brown } 540c4762a1bSJed Brown 541c4762a1bSJed Brown if (viewJ) { 542c4762a1bSJed Brown /* View assembled Jac */ 5439566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 544c4762a1bSJed Brown } 545c4762a1bSJed Brown 546c4762a1bSJed Brown /* Create snes_power */ 5479566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_power setup ......\n")); 548c4762a1bSJed Brown 549c4762a1bSJed Brown user.subsnes_id = 0; 5509566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes_power)); 5519566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_power, networkdm)); 5529566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_power, "power_")); 5539566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_power, F, FormFunction, &user)); 5549566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_power, UserMonitor, &user, NULL)); 555c4762a1bSJed Brown 556c4762a1bSJed Brown /* Use user-provide Jacobian */ 5579566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(networkdm, &Jac)); 5589566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes_power, Jac, Jac, FormJacobian_subPower, &user)); 5599566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_power)); 560c4762a1bSJed Brown 561c4762a1bSJed Brown if (viewX) { 5629566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Power Solution:\n")); 5639566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 564c4762a1bSJed Brown } 565c4762a1bSJed Brown if (viewJ) { 5669566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Power Jac:\n")); 5679566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes_power, &Jac, NULL, NULL, NULL)); 5689566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 5699566063dSJacob Faibussowitsch /* PetscCall(MatView(Jac,PETSC_VIEWER_STDOUT_WORLD)); */ 570c4762a1bSJed Brown } 571c4762a1bSJed Brown 572c4762a1bSJed Brown /* Create snes_water */ 5739566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES_water setup......\n")); 574c4762a1bSJed Brown 575c4762a1bSJed Brown user.subsnes_id = 1; 5769566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes_water)); 5779566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_water, networkdm)); 5789566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_water, "water_")); 5799566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_water, F, FormFunction, &user)); 5809566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_water, UserMonitor, &user, NULL)); 5819566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_water)); 582c4762a1bSJed Brown 583c4762a1bSJed Brown if (viewX) { 5849566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Water Solution:\n")); 5859566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 586c4762a1bSJed Brown } 5879566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 588c4762a1bSJed Brown 589c4762a1bSJed Brown /* (4) Solve */ 5909566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Solve", &stage[3])); 5919566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[3])); 592c4762a1bSJed Brown user.it = 0; 593c4762a1bSJed Brown reason = SNES_DIVERGED_DTOL; 594c4762a1bSJed Brown while (user.it < it_max && (PetscInt)reason < 0) { 595c4762a1bSJed Brown #if 0 596c4762a1bSJed Brown user.subsnes_id = 0; 5979566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_power,NULL,X)); 598c4762a1bSJed Brown 599c4762a1bSJed Brown user.subsnes_id = 1; 6009566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_water,NULL,X)); 601c4762a1bSJed Brown #endif 6022bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 6039566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes, NULL, X)); 604c4762a1bSJed Brown 6059566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(snes, &reason)); 606c4762a1bSJed Brown user.it++; 607c4762a1bSJed Brown } 60863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Coupled_SNES converged in %" PetscInt_FMT " iterations\n", user.it)); 609c4762a1bSJed Brown if (viewX) { 6109566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Final Solution:\n")); 6119566063dSJacob Faibussowitsch PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 612c4762a1bSJed Brown } 6139566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 614c4762a1bSJed Brown 615c4762a1bSJed Brown /* Free objects */ 616c4762a1bSJed Brown /* -------------*/ 6179566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X)); 6189566063dSJacob Faibussowitsch PetscCall(VecDestroy(&F)); 6199566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &user.localXold)); 620c4762a1bSJed Brown 6219566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes)); 6229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Jac)); 6239566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_power)); 6249566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_water)); 625c4762a1bSJed Brown 6269566063dSJacob Faibussowitsch PetscCall(DMDestroy(&networkdm)); 6279566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 628b122ec5aSJacob Faibussowitsch return 0; 629c4762a1bSJed Brown } 630c4762a1bSJed Brown 631c4762a1bSJed Brown /*TEST 632c4762a1bSJed Brown 633c4762a1bSJed Brown build: 634dfd57a17SPierre Jolivet requires: !complex double defined(PETSC_HAVE_ATTRIBUTEALIGNED) 635c4762a1bSJed Brown depends: power/PFReadData.c power/pffunctions.c water/waterreaddata.c water/waterfunctions.c 636c4762a1bSJed Brown 637c4762a1bSJed Brown test: 6382bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -viewDM 639c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 640c4762a1bSJed Brown output_file: output/ex1.out 641c4762a1bSJed Brown 642c4762a1bSJed Brown test: 643c4762a1bSJed Brown suffix: 2 644c4762a1bSJed Brown nsize: 3 6452bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type parmetis 646c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 647d5c9c0c4SHong Zhang output_file: output/ex1_2.out 6482bf73ac6SHong Zhang requires: parmetis 6492bf73ac6SHong Zhang 6502bf73ac6SHong Zhang # test: 6512bf73ac6SHong Zhang # suffix: 3 6522bf73ac6SHong Zhang # nsize: 3 6532bf73ac6SHong Zhang # args: -coupled_snes_converged_reason -options_left no -distribute false 6542bf73ac6SHong Zhang # localrunfiles: ex1options power/case9.m water/sample1.inp 6552bf73ac6SHong Zhang # output_file: output/ex1_2.out 656d5c9c0c4SHong Zhang 657d5c9c0c4SHong Zhang test: 6582bf73ac6SHong Zhang suffix: 4 6592bf73ac6SHong Zhang nsize: 4 6602bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type simple -viewDM 661d5c9c0c4SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 6622bf73ac6SHong Zhang output_file: output/ex1_4.out 663c4762a1bSJed Brown 664c4762a1bSJed Brown TEST*/ 665