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 19c4762a1bSJed Brown PetscErrorCode UserMonitor(SNES snes,PetscInt its,PetscReal fnorm ,void *appctx) 20c4762a1bSJed Brown { 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) { 34*63a3b9bcSJacob 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 { 36*63a3b9bcSJacob 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)); 44c4762a1bSJed Brown PetscFunctionReturn(0); 45c4762a1bSJed Brown } 46c4762a1bSJed Brown 47c4762a1bSJed Brown PetscErrorCode FormJacobian_subPower(SNES snes,Vec X, Mat J,Mat Jpre,void *appctx) 48c4762a1bSJed Brown { 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)); 91c4762a1bSJed Brown PetscFunctionReturn(0); 92c4762a1bSJed Brown } 93c4762a1bSJed Brown 94c4762a1bSJed Brown /* Dummy equation localF(X) = localX - localXold */ 95c4762a1bSJed Brown PetscErrorCode FormFunction_Dummy(DM networkdm,Vec localX, Vec localF,PetscInt nv,PetscInt ne,const PetscInt* vtx,const PetscInt* edges,void* appctx) 96c4762a1bSJed Brown { 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)); 115c4762a1bSJed Brown for (j=0; j<nvar; j++) { 116c4762a1bSJed Brown farr[offset+j] = xarr[offset+j] - xoldarr[offset+j]; 117c4762a1bSJed Brown } 118c4762a1bSJed Brown } 119c4762a1bSJed Brown 1209566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localX,&xarr)); 1219566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localXold,&xoldarr)); 1229566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localF,&farr)); 123c4762a1bSJed Brown PetscFunctionReturn(0); 124c4762a1bSJed Brown } 125c4762a1bSJed Brown 126c4762a1bSJed Brown PetscErrorCode FormFunction(SNES snes,Vec X,Vec F,void *appctx) 127c4762a1bSJed Brown { 128c4762a1bSJed Brown DM networkdm; 129c4762a1bSJed Brown Vec localX,localF; 1302bf73ac6SHong Zhang PetscInt nv,ne,v; 131c4762a1bSJed Brown const PetscInt *vtx,*edges; 132c4762a1bSJed Brown PetscMPIInt rank; 133c4762a1bSJed Brown MPI_Comm comm; 134c4762a1bSJed Brown UserCtx *user = (UserCtx*)appctx; 135c4762a1bSJed Brown UserCtx_Power appctx_power = (*user).appctx_power; 1362bf73ac6SHong Zhang AppCtx_Water appctx_water = (*user).appctx_water; 137c4762a1bSJed Brown 138c4762a1bSJed Brown PetscFunctionBegin; 1399566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes,&networkdm)); 1409566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)networkdm,&comm)); 1419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm,&rank)); 142c4762a1bSJed Brown 1439566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm,&localX)); 1449566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm,&localF)); 1459566063dSJacob Faibussowitsch PetscCall(VecSet(F,0.0)); 1469566063dSJacob Faibussowitsch PetscCall(VecSet(localF,0.0)); 147c4762a1bSJed Brown 1489566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX)); 1499566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX)); 150c4762a1bSJed Brown 151c4762a1bSJed Brown /* Form Function for power subnetwork */ 1529566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm,0,&nv,&ne,&vtx,&edges)); 153c4762a1bSJed Brown if (user->subsnes_id == 1) { /* snes_water only */ 1549566063dSJacob Faibussowitsch PetscCall(FormFunction_Dummy(networkdm,localX,localF,nv,ne,vtx,edges,user)); 155c4762a1bSJed Brown } else { 1569566063dSJacob Faibussowitsch PetscCall(FormFunction_Power(networkdm,localX,localF,nv,ne,vtx,edges,&appctx_power)); 157c4762a1bSJed Brown } 158c4762a1bSJed Brown 159c4762a1bSJed Brown /* Form Function for water subnetwork */ 1609566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm,1,&nv,&ne,&vtx,&edges)); 161c4762a1bSJed Brown if (user->subsnes_id == 0) { /* snes_power only */ 1629566063dSJacob Faibussowitsch PetscCall(FormFunction_Dummy(networkdm,localX,localF,nv,ne,vtx,edges,user)); 163c4762a1bSJed Brown } else { 1649566063dSJacob Faibussowitsch PetscCall(FormFunction_Water(networkdm,localX,localF,nv,ne,vtx,edges,NULL)); 165c4762a1bSJed Brown } 166c4762a1bSJed Brown 1672bf73ac6SHong Zhang /* Illustrate how to access the coupling vertex of the subnetworks without doing anything to F yet */ 1689566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm,&nv,&vtx)); 1692bf73ac6SHong Zhang for (v=0; v<nv; v++) { 1702bf73ac6SHong Zhang PetscInt key,ncomp,nvar,nconnedges,k,e,keye,goffset[3]; 171c4762a1bSJed Brown void* component; 1722bf73ac6SHong Zhang const PetscInt *connedges; 173c4762a1bSJed Brown 1749566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm,vtx[v],ALL_COMPONENTS,NULL,NULL,&nvar)); 1759566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm,vtx[v],&ncomp)); 176*63a3b9bcSJacob Faibussowitsch /* printf(" [%d] coupling vertex[%" PetscInt_FMT "]: v %" PetscInt_FMT ", ncomp %" PetscInt_FMT "; nvar %" PetscInt_FMT "\n",rank,v,vtx[v], ncomp,nvar); */ 177c4762a1bSJed Brown 1782bf73ac6SHong Zhang for (k=0; k<ncomp; k++) { 1799566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm,vtx[v],k,&key,&component,&nvar)); 1809566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVecOffset(networkdm,vtx[v],k,&goffset[k])); 181c4762a1bSJed Brown 1822bf73ac6SHong Zhang /* Verify the coupling vertex is a powernet load vertex or a water vertex */ 1832bf73ac6SHong Zhang switch (k) { 1842bf73ac6SHong Zhang case 0: 185*63a3b9bcSJacob Faibussowitsch PetscCheckFalse(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); 1862bf73ac6SHong Zhang break; 1872bf73ac6SHong Zhang case 1: 1882c71b3e2SJacob Faibussowitsch PetscCheckFalse(key != appctx_power.compkey_load || nvar != 0 || goffset[1] != goffset[0]+2,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Not a power load vertex"); 1892bf73ac6SHong Zhang break; 1902bf73ac6SHong Zhang case 2: 1912c71b3e2SJacob Faibussowitsch PetscCheckFalse(key != appctx_water.compkey_vtx || nvar != 1 || goffset[2] != goffset[1],PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Not a water vertex"); 1922bf73ac6SHong Zhang break; 193*63a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "k %" PetscInt_FMT " is wrong",k); 1942bf73ac6SHong Zhang } 195*63a3b9bcSJacob Faibussowitsch /* printf(" [%d] coupling vertex[%" PetscInt_FMT "]: key %" PetscInt_FMT "; nvar %" PetscInt_FMT ", goffset %" PetscInt_FMT "\n",rank,v,key,nvar,goffset[k]); */ 1962bf73ac6SHong Zhang } 197c4762a1bSJed Brown 1982bf73ac6SHong Zhang /* Get its supporting edges */ 1999566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSupportingEdges(networkdm,vtx[v],&nconnedges,&connedges)); 200*63a3b9bcSJacob Faibussowitsch /* printf("\n[%d] coupling vertex: nconnedges %" PetscInt_FMT "\n",rank,nconnedges); */ 201c4762a1bSJed Brown for (k=0; k<nconnedges; k++) { 202c4762a1bSJed Brown e = connedges[k]; 2039566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm,e,&ncomp)); 204*63a3b9bcSJacob Faibussowitsch /* printf("\n [%d] connected edge[%" PetscInt_FMT "]=%" PetscInt_FMT " has ncomp %" PetscInt_FMT "\n",rank,k,e,ncomp); */ 2059566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm,e,0,&keye,&component,NULL)); 206c4762a1bSJed Brown if (keye == appctx_water.compkey_edge) { /* water_compkey_edge */ 207c4762a1bSJed Brown EDGE_Water edge=(EDGE_Water)component; 208c4762a1bSJed Brown if (edge->type == EDGE_TYPE_PUMP) { 209*63a3b9bcSJacob Faibussowitsch /* printf(" connected edge[%" PetscInt_FMT "]=%" PetscInt_FMT " has keye=%" PetscInt_FMT ", is appctx_water.compkey_edge with EDGE_TYPE_PUMP\n",k,e,keye); */ 210c4762a1bSJed Brown } 2112bf73ac6SHong Zhang } else { /* ower->compkey_branch */ 21208401ef6SPierre Jolivet PetscCheck(keye == appctx_power.compkey_branch,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Not a power branch"); 213c4762a1bSJed Brown } 214c4762a1bSJed Brown } 215c4762a1bSJed Brown } 216c4762a1bSJed Brown 2179566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm,&localX)); 218c4762a1bSJed Brown 2199566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm,localF,ADD_VALUES,F)); 2209566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm,localF,ADD_VALUES,F)); 2219566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm,&localF)); 2222bf73ac6SHong Zhang #if 0 223dd400576SPatrick Sanan if (rank == 0) printf("F:\n"); 2249566063dSJacob Faibussowitsch PetscCall(VecView(F,PETSC_VIEWER_STDOUT_WORLD)); 2252bf73ac6SHong Zhang #endif 226c4762a1bSJed Brown PetscFunctionReturn(0); 227c4762a1bSJed Brown } 228c4762a1bSJed Brown 229c4762a1bSJed Brown PetscErrorCode SetInitialGuess(DM networkdm,Vec X,void* appctx) 230c4762a1bSJed Brown { 2312bf73ac6SHong Zhang PetscInt nv,ne,i,j,ncomp,offset,key; 232c4762a1bSJed Brown const PetscInt *vtx,*edges; 233c4762a1bSJed Brown UserCtx *user = (UserCtx*)appctx; 234c4762a1bSJed Brown Vec localX = user->localXold; 235c4762a1bSJed Brown UserCtx_Power appctx_power = (*user).appctx_power; 2362bf73ac6SHong Zhang AppCtx_Water appctx_water = (*user).appctx_water; 2372bf73ac6SHong Zhang PetscBool ghost; 2382bf73ac6SHong Zhang PetscScalar *xarr; 2392bf73ac6SHong Zhang VERTEX_Power bus; 2402bf73ac6SHong Zhang VERTEX_Water vertex; 2412bf73ac6SHong Zhang void* component; 2422bf73ac6SHong Zhang GEN gen; 243c4762a1bSJed Brown 244c4762a1bSJed Brown PetscFunctionBegin; 2459566063dSJacob Faibussowitsch PetscCall(VecSet(X,0.0)); 2469566063dSJacob Faibussowitsch PetscCall(VecSet(localX,0.0)); 247c4762a1bSJed Brown 248c4762a1bSJed Brown /* Set initial guess for power subnetwork */ 2499566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm,0,&nv,&ne,&vtx,&edges)); 2509566063dSJacob Faibussowitsch PetscCall(SetInitialGuess_Power(networkdm,localX,nv,ne,vtx,edges,&appctx_power)); 251c4762a1bSJed Brown 252c4762a1bSJed Brown /* Set initial guess for water subnetwork */ 2539566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm,1,&nv,&ne,&vtx,&edges)); 2549566063dSJacob Faibussowitsch PetscCall(SetInitialGuess_Water(networkdm,localX,nv,ne,vtx,edges,NULL)); 255c4762a1bSJed Brown 2562bf73ac6SHong Zhang /* Set initial guess at the coupling vertex */ 2579566063dSJacob Faibussowitsch PetscCall(VecGetArray(localX,&xarr)); 2589566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm,&nv,&vtx)); 2592bf73ac6SHong Zhang for (i=0; i<nv; i++) { 2609566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm,vtx[i],&ghost)); 2612bf73ac6SHong Zhang if (ghost) continue; 2622bf73ac6SHong Zhang 2639566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm,vtx[i],&ncomp)); 2642bf73ac6SHong Zhang for (j=0; j<ncomp; j++) { 2659566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm,vtx[i],j,&offset)); 2669566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm,vtx[i],j,&key,(void**)&component,NULL)); 2672bf73ac6SHong Zhang if (key == appctx_power.compkey_bus) { 2682bf73ac6SHong Zhang bus = (VERTEX_Power)(component); 2692bf73ac6SHong Zhang xarr[offset] = bus->va*PETSC_PI/180.0; 2702bf73ac6SHong Zhang xarr[offset+1] = bus->vm; 2712bf73ac6SHong Zhang } else if (key == appctx_power.compkey_gen) { 2722bf73ac6SHong Zhang gen = (GEN)(component); 2732bf73ac6SHong Zhang if (!gen->status) continue; 2742bf73ac6SHong Zhang xarr[offset+1] = gen->vs; 2752bf73ac6SHong Zhang } else if (key == appctx_water.compkey_vtx) { 2762bf73ac6SHong Zhang vertex = (VERTEX_Water)(component); 2772bf73ac6SHong Zhang if (vertex->type == VERTEX_TYPE_JUNCTION) { 2782bf73ac6SHong Zhang xarr[offset] = 100; 2792bf73ac6SHong Zhang } else if (vertex->type == VERTEX_TYPE_RESERVOIR) { 2802bf73ac6SHong Zhang xarr[offset] = vertex->res.head; 2812bf73ac6SHong Zhang } else { 2822bf73ac6SHong Zhang xarr[offset] = vertex->tank.initlvl + vertex->tank.elev; 283c4762a1bSJed Brown } 2842bf73ac6SHong Zhang } 2852bf73ac6SHong Zhang } 2862bf73ac6SHong Zhang } 2879566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localX,&xarr)); 288c4762a1bSJed Brown 2899566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm,localX,ADD_VALUES,X)); 2909566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm,localX,ADD_VALUES,X)); 291c4762a1bSJed Brown PetscFunctionReturn(0); 292c4762a1bSJed Brown } 293c4762a1bSJed Brown 294c4762a1bSJed Brown int main(int argc,char **argv) 295c4762a1bSJed Brown { 296c4762a1bSJed Brown DM networkdm; 297c4762a1bSJed Brown PetscLogStage stage[4]; 298d5c9c0c4SHong Zhang PetscMPIInt rank,size; 2992bf73ac6SHong Zhang PetscInt Nsubnet=2,numVertices[2],numEdges[2],i,j,nv,ne,it_max=10; 300c4762a1bSJed Brown const PetscInt *vtx,*edges; 301c4762a1bSJed Brown Vec X,F; 302c4762a1bSJed Brown SNES snes,snes_power,snes_water; 303c4762a1bSJed Brown Mat Jac; 3042bf73ac6SHong Zhang PetscBool ghost,viewJ=PETSC_FALSE,viewX=PETSC_FALSE,viewDM=PETSC_FALSE,test=PETSC_FALSE,distribute=PETSC_TRUE,flg; 305c4762a1bSJed Brown UserCtx user; 306c4762a1bSJed Brown SNESConvergedReason reason; 307c4762a1bSJed Brown 308c4762a1bSJed Brown /* Power subnetwork */ 309c4762a1bSJed Brown UserCtx_Power *appctx_power = &user.appctx_power; 310c4762a1bSJed Brown char pfdata_file[PETSC_MAX_PATH_LEN] = "power/case9.m"; 311c4762a1bSJed Brown PFDATA *pfdata = NULL; 3122bf73ac6SHong Zhang PetscInt genj,loadj,*edgelist_power = NULL,power_netnum; 313c4762a1bSJed Brown PetscScalar Sbase = 0.0; 314c4762a1bSJed Brown 315c4762a1bSJed Brown /* Water subnetwork */ 316c4762a1bSJed Brown AppCtx_Water *appctx_water = &user.appctx_water; 317c4762a1bSJed Brown WATERDATA *waterdata = NULL; 318c4762a1bSJed Brown char waterdata_file[PETSC_MAX_PATH_LEN] = "water/sample1.inp"; 3192bf73ac6SHong Zhang PetscInt *edgelist_water = NULL,water_netnum; 320c4762a1bSJed Brown 3212bf73ac6SHong Zhang /* Shared vertices between subnetworks */ 3222bf73ac6SHong Zhang PetscInt power_svtx,water_svtx; 323c4762a1bSJed Brown 3249566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc,&argv,"ex1options",help)); 3259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); 3269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size)); 327c4762a1bSJed Brown 328c4762a1bSJed Brown /* (1) Read Data - Only rank 0 reads the data */ 329c4762a1bSJed Brown /*--------------------------------------------*/ 3309566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Read Data",&stage[0])); 3319566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[0])); 332c4762a1bSJed Brown 3332bf73ac6SHong Zhang for (i=0; i<Nsubnet; i++) { 334c4762a1bSJed Brown numVertices[i] = 0; 335c4762a1bSJed Brown numEdges[i] = 0; 336c4762a1bSJed Brown } 337c4762a1bSJed Brown 3382bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE FIRST SUBNETWORK: Electric Power Grid */ 3392bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 3409566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL,NULL,"-pfdata",pfdata_file,PETSC_MAX_PATH_LEN-1,NULL)); 3419566063dSJacob Faibussowitsch PetscCall(PetscNew(&pfdata)); 3429566063dSJacob Faibussowitsch PetscCall(PFReadMatPowerData(pfdata,pfdata_file)); 343dd400576SPatrick Sanan if (rank == 0) { 344*63a3b9bcSJacob Faibussowitsch 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)); 3452bf73ac6SHong Zhang } 346c4762a1bSJed Brown Sbase = pfdata->sbase; 3472bf73ac6SHong Zhang if (rank == 0) { /* proc[0] will create Electric Power Grid */ 348c4762a1bSJed Brown numEdges[0] = pfdata->nbranch; 349c4762a1bSJed Brown numVertices[0] = pfdata->nbus; 350c4762a1bSJed Brown 3519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2*numEdges[0],&edgelist_power)); 3529566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Power(pfdata,edgelist_power)); 353c4762a1bSJed Brown } 354c4762a1bSJed Brown /* Broadcast power Sbase to all processors */ 3559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&Sbase,1,MPIU_SCALAR,0,PETSC_COMM_WORLD)); 356c4762a1bSJed Brown appctx_power->Sbase = Sbase; 357c4762a1bSJed Brown appctx_power->jac_error = PETSC_FALSE; 358c4762a1bSJed Brown /* If external option activated. Introduce error in jacobian */ 3599566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL,NULL, "-jac_error", &appctx_power->jac_error)); 360c4762a1bSJed Brown 3612bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE SECOND SUBNETWORK: Water */ 3622bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 3639566063dSJacob Faibussowitsch PetscCall(PetscNew(&waterdata)); 3649566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL,NULL,"-waterdata",waterdata_file,PETSC_MAX_PATH_LEN-1,NULL)); 3659566063dSJacob Faibussowitsch PetscCall(WaterReadData(waterdata,waterdata_file)); 3662bf73ac6SHong Zhang if (size == 1 || (size > 1 && rank == 1)) { 3679566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(2*waterdata->nedge,&edgelist_water)); 3689566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Water(waterdata,edgelist_water)); 369c4762a1bSJed Brown numEdges[1] = waterdata->nedge; 370c4762a1bSJed Brown numVertices[1] = waterdata->nvertex; 371c4762a1bSJed Brown } 3722bf73ac6SHong Zhang PetscLogStagePop(); 373c4762a1bSJed Brown 3742bf73ac6SHong Zhang /* (2) Create a network consist of two subnetworks */ 3752bf73ac6SHong Zhang /*-------------------------------------------------*/ 3769566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Net Setup",&stage[1])); 3779566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[1])); 378c4762a1bSJed Brown 3799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-viewDM",&viewDM,NULL)); 3809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-test",&test,NULL)); 3819566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-distribute",&distribute,NULL)); 382c4762a1bSJed Brown 383c4762a1bSJed Brown /* Create an empty network object */ 3849566063dSJacob Faibussowitsch PetscCall(DMNetworkCreate(PETSC_COMM_WORLD,&networkdm)); 385c4762a1bSJed Brown 386c4762a1bSJed Brown /* Register the components in the network */ 3879566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"branchstruct",sizeof(struct _p_EDGE_Power),&appctx_power->compkey_branch)); 3889566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"busstruct",sizeof(struct _p_VERTEX_Power),&appctx_power->compkey_bus)); 3899566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"genstruct",sizeof(struct _p_GEN),&appctx_power->compkey_gen)); 3909566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"loadstruct",sizeof(struct _p_LOAD),&appctx_power->compkey_load)); 391c4762a1bSJed Brown 3929566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"edge_water",sizeof(struct _p_EDGE_Water),&appctx_water->compkey_edge)); 3939566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"vertex_water",sizeof(struct _p_VERTEX_Water),&appctx_water->compkey_vtx)); 3942bf73ac6SHong Zhang #if 0 3959566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_branch %d\n",appctx_power->compkey_branch)); 3969566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_bus %d\n",appctx_power->compkey_bus)); 3979566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_gen %d\n",appctx_power->compkey_gen)); 3989566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_load %d\n",appctx_power->compkey_load)); 3999566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"water->compkey_edge %d\n",appctx_water->compkey_edge)); 4009566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"water->compkey_vtx %d\n",appctx_water->compkey_vtx)); 4012bf73ac6SHong Zhang #endif 402*63a3b9bcSJacob 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])); 4039566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT)); 404c4762a1bSJed Brown 4059566063dSJacob Faibussowitsch PetscCall(DMNetworkSetNumSubNetworks(networkdm,PETSC_DECIDE,Nsubnet)); 4069566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm,"power",numEdges[0],edgelist_power,&power_netnum)); 4079566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm,"water",numEdges[1],edgelist_water,&water_netnum)); 408c4762a1bSJed Brown 4092bf73ac6SHong Zhang /* vertex subnet[0].4 shares with vertex subnet[1].0 */ 4102bf73ac6SHong Zhang power_svtx = 4; water_svtx = 0; 4119566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSharedVertices(networkdm,power_netnum,water_netnum,1,&power_svtx,&water_svtx)); 412c4762a1bSJed Brown 413c4762a1bSJed Brown /* Set up the network layout */ 4149566063dSJacob Faibussowitsch PetscCall(DMNetworkLayoutSetUp(networkdm)); 415c4762a1bSJed Brown 416c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE POWER SUBNETWORK */ 4172bf73ac6SHong Zhang /*-------------------------------------------------------*/ 418c4762a1bSJed Brown genj = 0; loadj = 0; 4199566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm,power_netnum,&nv,&ne,&vtx,&edges)); 4202bf73ac6SHong Zhang 421c4762a1bSJed Brown for (i = 0; i < ne; i++) { 4229566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,edges[i],appctx_power->compkey_branch,&pfdata->branch[i],0)); 423c4762a1bSJed Brown } 424c4762a1bSJed Brown 425c4762a1bSJed Brown for (i = 0; i < nv; i++) { 4269566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm,vtx[i],&flg)); 4272bf73ac6SHong Zhang if (flg) continue; 4282bf73ac6SHong Zhang 4299566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_power->compkey_bus,&pfdata->bus[i],2)); 430c4762a1bSJed Brown if (pfdata->bus[i].ngen) { 431c4762a1bSJed Brown for (j = 0; j < pfdata->bus[i].ngen; j++) { 4329566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_power->compkey_gen,&pfdata->gen[genj++],0)); 433c4762a1bSJed Brown } 434c4762a1bSJed Brown } 435c4762a1bSJed Brown if (pfdata->bus[i].nload) { 436c4762a1bSJed Brown for (j=0; j < pfdata->bus[i].nload; j++) { 4379566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_power->compkey_load,&pfdata->load[loadj++],0)); 438c4762a1bSJed Brown } 439c4762a1bSJed Brown } 440c4762a1bSJed Brown } 441c4762a1bSJed Brown 442c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE WATER SUBNETWORK */ 4432bf73ac6SHong Zhang /*-------------------------------------------------------*/ 4449566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm,water_netnum,&nv,&ne,&vtx,&edges)); 445c4762a1bSJed Brown for (i = 0; i < ne; i++) { 4469566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,edges[i],appctx_water->compkey_edge,&waterdata->edge[i],0)); 447c4762a1bSJed Brown } 448c4762a1bSJed Brown 449c4762a1bSJed Brown for (i = 0; i < nv; i++) { 4509566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm,vtx[i],&flg)); 4512bf73ac6SHong Zhang if (flg) continue; 4522bf73ac6SHong Zhang 4539566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_water->compkey_vtx,&waterdata->vertex[i],1)); 454c4762a1bSJed Brown } 4552bf73ac6SHong Zhang 456eac198afSGetnet /* 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 */ 4572bf73ac6SHong Zhang /*----------------------------------------------------------------------------------------------------------------------------*/ 4589566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm,&nv,&vtx)); 4592bf73ac6SHong Zhang for (i = 0; i < nv; i++) { 4602bf73ac6SHong Zhang /* power */ 4619566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_power->compkey_bus,&pfdata->bus[4],2)); 4622bf73ac6SHong Zhang /* bus[4] is a load, add its component */ 4639566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_power->compkey_load,&pfdata->load[0],0)); 4642bf73ac6SHong Zhang 4652bf73ac6SHong Zhang /* water */ 4669566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_water->compkey_vtx,&waterdata->vertex[0],1)); 467c4762a1bSJed Brown } 468c4762a1bSJed Brown 469c4762a1bSJed Brown /* Set up DM for use */ 4709566063dSJacob Faibussowitsch PetscCall(DMSetUp(networkdm)); 471c4762a1bSJed Brown if (viewDM) { 4729566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nAfter DMSetUp, DMView:\n")); 4739566063dSJacob Faibussowitsch PetscCall(DMView(networkdm,PETSC_VIEWER_STDOUT_WORLD)); 474c4762a1bSJed Brown } 475c4762a1bSJed Brown 476c4762a1bSJed Brown /* Free user objects */ 4779566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_power)); 4789566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->bus)); 4799566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->gen)); 4809566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->branch)); 4819566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->load)); 4829566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata)); 4832bf73ac6SHong Zhang 4849566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_water)); 4859566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->vertex)); 4869566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->edge)); 4879566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata)); 488c4762a1bSJed Brown 489d5c9c0c4SHong Zhang /* Re-distribute networkdm to multiple processes for better job balance */ 4902bf73ac6SHong Zhang if (size >1 && distribute) { 4919566063dSJacob Faibussowitsch PetscCall(DMNetworkDistribute(&networkdm,0)); 492c4762a1bSJed Brown if (viewDM) { 4939566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nAfter DMNetworkDistribute, DMView:\n")); 4949566063dSJacob Faibussowitsch PetscCall(DMView(networkdm,PETSC_VIEWER_STDOUT_WORLD)); 495c4762a1bSJed Brown } 496d5c9c0c4SHong Zhang } 497c4762a1bSJed Brown 4982bf73ac6SHong Zhang /* Test DMNetworkGetSubnetwork() and DMNetworkGetSubnetworkSharedVertices() */ 499c4762a1bSJed Brown if (test) { 5002bf73ac6SHong Zhang PetscInt v,gidx; 5019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 5022bf73ac6SHong Zhang for (i=0; i<Nsubnet; i++) { 5039566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm,i,&nv,&ne,&vtx,&edges)); 504*63a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] After distribute, subnet[%" PetscInt_FMT "] ne %" PetscInt_FMT ", nv %" PetscInt_FMT "\n",rank,i,ne,nv)); 5059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 506c4762a1bSJed Brown 5072bf73ac6SHong Zhang for (v=0; v<nv; v++) { 5089566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm,vtx[v],&ghost)); 5099566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm,vtx[v],&gidx)); 510*63a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] subnet[%" PetscInt_FMT "] v %" PetscInt_FMT " %" PetscInt_FMT "; ghost %d\n",rank,i,vtx[v],gidx,ghost)); 511c4762a1bSJed Brown } 5129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 513c4762a1bSJed Brown } 5149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 5152bf73ac6SHong Zhang 5169566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm,&nv,&vtx)); 517*63a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] After distribute, num of shared vertices nsv = %" PetscInt_FMT "\n",rank,nv)); 5182bf73ac6SHong Zhang for (v=0; v<nv; v++) { 5199566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm,vtx[v],&gidx)); 520*63a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] sv %" PetscInt_FMT ", gidx=%" PetscInt_FMT "\n",rank,vtx[v],gidx)); 5212bf73ac6SHong Zhang } 5229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 523c4762a1bSJed Brown } 524c4762a1bSJed Brown 5252bf73ac6SHong Zhang /* Create solution vector X */ 5269566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(networkdm,&X)); 5279566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X,&F)); 5289566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm,&user.localXold)); 5292bf73ac6SHong Zhang PetscLogStagePop(); 530c4762a1bSJed Brown 531c4762a1bSJed Brown /* (3) Setup Solvers */ 532c4762a1bSJed Brown /*-------------------*/ 5339566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-viewJ",&viewJ,NULL)); 5349566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-viewX",&viewX,NULL)); 535c4762a1bSJed Brown 5369566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Setup",&stage[2])); 5379566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[2])); 538c4762a1bSJed Brown 5399566063dSJacob Faibussowitsch PetscCall(SetInitialGuess(networkdm,X,&user)); 540c4762a1bSJed Brown 541c4762a1bSJed Brown /* Create coupled snes */ 542c4762a1bSJed Brown /*-------------------- */ 5439566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"SNES_coupled setup ......\n")); 5442bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 5459566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD,&snes)); 5469566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes,networkdm)); 5479566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes,"coupled_")); 5489566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes,F,FormFunction,&user)); 5499566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes,UserMonitor,&user,NULL)); 5509566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes)); 551c4762a1bSJed Brown 552c4762a1bSJed Brown if (viewJ) { 553c4762a1bSJed Brown /* View Jac structure */ 5549566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes,&Jac,NULL,NULL,NULL)); 5559566063dSJacob Faibussowitsch PetscCall(MatView(Jac,PETSC_VIEWER_DRAW_WORLD)); 556c4762a1bSJed Brown } 557c4762a1bSJed Brown 558c4762a1bSJed Brown if (viewX) { 5599566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Solution:\n")); 5609566063dSJacob Faibussowitsch PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); 561c4762a1bSJed Brown } 562c4762a1bSJed Brown 563c4762a1bSJed Brown if (viewJ) { 564c4762a1bSJed Brown /* View assembled Jac */ 5659566063dSJacob Faibussowitsch PetscCall(MatView(Jac,PETSC_VIEWER_DRAW_WORLD)); 566c4762a1bSJed Brown } 567c4762a1bSJed Brown 568c4762a1bSJed Brown /* Create snes_power */ 569c4762a1bSJed Brown /*-------------------*/ 5709566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"SNES_power setup ......\n")); 571c4762a1bSJed Brown 572c4762a1bSJed Brown user.subsnes_id = 0; 5739566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD,&snes_power)); 5749566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_power,networkdm)); 5759566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_power,"power_")); 5769566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_power,F,FormFunction,&user)); 5779566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_power,UserMonitor,&user,NULL)); 578c4762a1bSJed Brown 579c4762a1bSJed Brown /* Use user-provide Jacobian */ 5809566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(networkdm,&Jac)); 5819566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes_power,Jac,Jac,FormJacobian_subPower,&user)); 5829566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_power)); 583c4762a1bSJed Brown 584c4762a1bSJed Brown if (viewX) { 5859566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Power Solution:\n")); 5869566063dSJacob Faibussowitsch PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); 587c4762a1bSJed Brown } 588c4762a1bSJed Brown if (viewJ) { 5899566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Power Jac:\n")); 5909566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes_power,&Jac,NULL,NULL,NULL)); 5919566063dSJacob Faibussowitsch PetscCall(MatView(Jac,PETSC_VIEWER_DRAW_WORLD)); 5929566063dSJacob Faibussowitsch /* PetscCall(MatView(Jac,PETSC_VIEWER_STDOUT_WORLD)); */ 593c4762a1bSJed Brown } 594c4762a1bSJed Brown 595c4762a1bSJed Brown /* Create snes_water */ 596c4762a1bSJed Brown /*-------------------*/ 5979566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"SNES_water setup......\n")); 598c4762a1bSJed Brown 599c4762a1bSJed Brown user.subsnes_id = 1; 6009566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD,&snes_water)); 6019566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_water,networkdm)); 6029566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_water,"water_")); 6039566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_water,F,FormFunction,&user)); 6049566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_water,UserMonitor,&user,NULL)); 6059566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_water)); 606c4762a1bSJed Brown 607c4762a1bSJed Brown if (viewX) { 6089566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Water Solution:\n")); 6099566063dSJacob Faibussowitsch PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); 610c4762a1bSJed Brown } 6119566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 612c4762a1bSJed Brown 613c4762a1bSJed Brown /* (4) Solve */ 614c4762a1bSJed Brown /*-----------*/ 6159566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Solve",&stage[3])); 6169566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[3])); 617c4762a1bSJed Brown user.it = 0; 618c4762a1bSJed Brown reason = SNES_DIVERGED_DTOL; 619c4762a1bSJed Brown while (user.it < it_max && (PetscInt)reason<0) { 620c4762a1bSJed Brown #if 0 621c4762a1bSJed Brown user.subsnes_id = 0; 6229566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_power,NULL,X)); 623c4762a1bSJed Brown 624c4762a1bSJed Brown user.subsnes_id = 1; 6259566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_water,NULL,X)); 626c4762a1bSJed Brown #endif 6272bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 6289566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes,NULL,X)); 629c4762a1bSJed Brown 6309566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(snes,&reason)); 631c4762a1bSJed Brown user.it++; 632c4762a1bSJed Brown } 633*63a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Coupled_SNES converged in %" PetscInt_FMT " iterations\n",user.it)); 634c4762a1bSJed Brown if (viewX) { 6359566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Final Solution:\n")); 6369566063dSJacob Faibussowitsch PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); 637c4762a1bSJed Brown } 6389566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 639c4762a1bSJed Brown 640c4762a1bSJed Brown /* Free objects */ 641c4762a1bSJed Brown /* -------------*/ 6429566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X)); 6439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&F)); 6449566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm,&user.localXold)); 645c4762a1bSJed Brown 6469566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes)); 6479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Jac)); 6489566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_power)); 6499566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_water)); 650c4762a1bSJed Brown 6519566063dSJacob Faibussowitsch PetscCall(DMDestroy(&networkdm)); 6529566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 653b122ec5aSJacob Faibussowitsch return 0; 654c4762a1bSJed Brown } 655c4762a1bSJed Brown 656c4762a1bSJed Brown /*TEST 657c4762a1bSJed Brown 658c4762a1bSJed Brown build: 659dfd57a17SPierre Jolivet requires: !complex double defined(PETSC_HAVE_ATTRIBUTEALIGNED) 660c4762a1bSJed Brown depends: power/PFReadData.c power/pffunctions.c water/waterreaddata.c water/waterfunctions.c 661c4762a1bSJed Brown 662c4762a1bSJed Brown test: 6632bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -viewDM 664c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 665c4762a1bSJed Brown output_file: output/ex1.out 666c4762a1bSJed Brown 667c4762a1bSJed Brown test: 668c4762a1bSJed Brown suffix: 2 669c4762a1bSJed Brown nsize: 3 6702bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type parmetis 671c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 672d5c9c0c4SHong Zhang output_file: output/ex1_2.out 6732bf73ac6SHong Zhang requires: parmetis 6742bf73ac6SHong Zhang 6752bf73ac6SHong Zhang # test: 6762bf73ac6SHong Zhang # suffix: 3 6772bf73ac6SHong Zhang # nsize: 3 6782bf73ac6SHong Zhang # args: -coupled_snes_converged_reason -options_left no -distribute false 6792bf73ac6SHong Zhang # localrunfiles: ex1options power/case9.m water/sample1.inp 6802bf73ac6SHong Zhang # output_file: output/ex1_2.out 681d5c9c0c4SHong Zhang 682d5c9c0c4SHong Zhang test: 6832bf73ac6SHong Zhang suffix: 4 6842bf73ac6SHong Zhang nsize: 4 6852bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type simple -viewDM 686d5c9c0c4SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 6872bf73ac6SHong Zhang output_file: output/ex1_4.out 688c4762a1bSJed Brown 689c4762a1bSJed Brown TEST*/ 690