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) { 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)); 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)); 17663a3b9bcSJacob 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: 1850b121fc5SBarry Smith 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); 1862bf73ac6SHong Zhang break; 1872bf73ac6SHong Zhang case 1: 1880b121fc5SBarry Smith 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"); 1892bf73ac6SHong Zhang break; 1902bf73ac6SHong Zhang case 2: 1910b121fc5SBarry Smith PetscCheck(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; 19363a3b9bcSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "k %" PetscInt_FMT " is wrong",k); 1942bf73ac6SHong Zhang } 19563a3b9bcSJacob 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)); 20063a3b9bcSJacob 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)); 20463a3b9bcSJacob 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) { 20963a3b9bcSJacob 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 324*327415f7SBarry Smith PetscFunctionBeginUser; 3259566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc,&argv,"ex1options",help)); 3269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); 3279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size)); 328c4762a1bSJed Brown 329c4762a1bSJed Brown /* (1) Read Data - Only rank 0 reads the data */ 330c4762a1bSJed Brown /*--------------------------------------------*/ 3319566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Read Data",&stage[0])); 3329566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[0])); 333c4762a1bSJed Brown 3342bf73ac6SHong Zhang for (i=0; i<Nsubnet; i++) { 335c4762a1bSJed Brown numVertices[i] = 0; 336c4762a1bSJed Brown numEdges[i] = 0; 337c4762a1bSJed Brown } 338c4762a1bSJed Brown 3392bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE FIRST SUBNETWORK: Electric Power Grid */ 3402bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 3419566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL,NULL,"-pfdata",pfdata_file,PETSC_MAX_PATH_LEN-1,NULL)); 3429566063dSJacob Faibussowitsch PetscCall(PetscNew(&pfdata)); 3439566063dSJacob Faibussowitsch PetscCall(PFReadMatPowerData(pfdata,pfdata_file)); 344dd400576SPatrick Sanan if (rank == 0) { 34563a3b9bcSJacob 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)); 3462bf73ac6SHong Zhang } 347c4762a1bSJed Brown Sbase = pfdata->sbase; 3482bf73ac6SHong Zhang if (rank == 0) { /* proc[0] will create Electric Power Grid */ 349c4762a1bSJed Brown numEdges[0] = pfdata->nbranch; 350c4762a1bSJed Brown numVertices[0] = pfdata->nbus; 351c4762a1bSJed Brown 3529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2*numEdges[0],&edgelist_power)); 3539566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Power(pfdata,edgelist_power)); 354c4762a1bSJed Brown } 355c4762a1bSJed Brown /* Broadcast power Sbase to all processors */ 3569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&Sbase,1,MPIU_SCALAR,0,PETSC_COMM_WORLD)); 357c4762a1bSJed Brown appctx_power->Sbase = Sbase; 358c4762a1bSJed Brown appctx_power->jac_error = PETSC_FALSE; 359c4762a1bSJed Brown /* If external option activated. Introduce error in jacobian */ 3609566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL,NULL, "-jac_error", &appctx_power->jac_error)); 361c4762a1bSJed Brown 3622bf73ac6SHong Zhang /* All processes READ THE DATA FOR THE SECOND SUBNETWORK: Water */ 3632bf73ac6SHong Zhang /* Used for shared vertex, because currently the coupling info must be available in all processes!!! */ 3649566063dSJacob Faibussowitsch PetscCall(PetscNew(&waterdata)); 3659566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL,NULL,"-waterdata",waterdata_file,PETSC_MAX_PATH_LEN-1,NULL)); 3669566063dSJacob Faibussowitsch PetscCall(WaterReadData(waterdata,waterdata_file)); 3672bf73ac6SHong Zhang if (size == 1 || (size > 1 && rank == 1)) { 3689566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(2*waterdata->nedge,&edgelist_water)); 3699566063dSJacob Faibussowitsch PetscCall(GetListofEdges_Water(waterdata,edgelist_water)); 370c4762a1bSJed Brown numEdges[1] = waterdata->nedge; 371c4762a1bSJed Brown numVertices[1] = waterdata->nvertex; 372c4762a1bSJed Brown } 3732bf73ac6SHong Zhang PetscLogStagePop(); 374c4762a1bSJed Brown 3752bf73ac6SHong Zhang /* (2) Create a network consist of two subnetworks */ 3762bf73ac6SHong Zhang /*-------------------------------------------------*/ 3779566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Net Setup",&stage[1])); 3789566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[1])); 379c4762a1bSJed Brown 3809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-viewDM",&viewDM,NULL)); 3819566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-test",&test,NULL)); 3829566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-distribute",&distribute,NULL)); 383c4762a1bSJed Brown 384c4762a1bSJed Brown /* Create an empty network object */ 3859566063dSJacob Faibussowitsch PetscCall(DMNetworkCreate(PETSC_COMM_WORLD,&networkdm)); 386c4762a1bSJed Brown 387c4762a1bSJed Brown /* Register the components in the network */ 3889566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"branchstruct",sizeof(struct _p_EDGE_Power),&appctx_power->compkey_branch)); 3899566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"busstruct",sizeof(struct _p_VERTEX_Power),&appctx_power->compkey_bus)); 3909566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"genstruct",sizeof(struct _p_GEN),&appctx_power->compkey_gen)); 3919566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"loadstruct",sizeof(struct _p_LOAD),&appctx_power->compkey_load)); 392c4762a1bSJed Brown 3939566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"edge_water",sizeof(struct _p_EDGE_Water),&appctx_water->compkey_edge)); 3949566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm,"vertex_water",sizeof(struct _p_VERTEX_Water),&appctx_water->compkey_vtx)); 3952bf73ac6SHong Zhang #if 0 3969566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_branch %d\n",appctx_power->compkey_branch)); 3979566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_bus %d\n",appctx_power->compkey_bus)); 3989566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_gen %d\n",appctx_power->compkey_gen)); 3999566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"power->compkey_load %d\n",appctx_power->compkey_load)); 4009566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"water->compkey_edge %d\n",appctx_water->compkey_edge)); 4019566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"water->compkey_vtx %d\n",appctx_water->compkey_vtx)); 4022bf73ac6SHong Zhang #endif 40363a3b9bcSJacob 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])); 4049566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT)); 405c4762a1bSJed Brown 4069566063dSJacob Faibussowitsch PetscCall(DMNetworkSetNumSubNetworks(networkdm,PETSC_DECIDE,Nsubnet)); 4079566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm,"power",numEdges[0],edgelist_power,&power_netnum)); 4089566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm,"water",numEdges[1],edgelist_water,&water_netnum)); 409c4762a1bSJed Brown 4102bf73ac6SHong Zhang /* vertex subnet[0].4 shares with vertex subnet[1].0 */ 4112bf73ac6SHong Zhang power_svtx = 4; water_svtx = 0; 4129566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSharedVertices(networkdm,power_netnum,water_netnum,1,&power_svtx,&water_svtx)); 413c4762a1bSJed Brown 414c4762a1bSJed Brown /* Set up the network layout */ 4159566063dSJacob Faibussowitsch PetscCall(DMNetworkLayoutSetUp(networkdm)); 416c4762a1bSJed Brown 417c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE POWER SUBNETWORK */ 4182bf73ac6SHong Zhang /*-------------------------------------------------------*/ 419c4762a1bSJed Brown genj = 0; loadj = 0; 4209566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm,power_netnum,&nv,&ne,&vtx,&edges)); 4212bf73ac6SHong Zhang 422c4762a1bSJed Brown for (i = 0; i < ne; i++) { 4239566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,edges[i],appctx_power->compkey_branch,&pfdata->branch[i],0)); 424c4762a1bSJed Brown } 425c4762a1bSJed Brown 426c4762a1bSJed Brown for (i = 0; i < nv; i++) { 4279566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm,vtx[i],&flg)); 4282bf73ac6SHong Zhang if (flg) continue; 4292bf73ac6SHong Zhang 4309566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_power->compkey_bus,&pfdata->bus[i],2)); 431c4762a1bSJed Brown if (pfdata->bus[i].ngen) { 432c4762a1bSJed Brown for (j = 0; j < pfdata->bus[i].ngen; j++) { 4339566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_power->compkey_gen,&pfdata->gen[genj++],0)); 434c4762a1bSJed Brown } 435c4762a1bSJed Brown } 436c4762a1bSJed Brown if (pfdata->bus[i].nload) { 437c4762a1bSJed Brown for (j=0; j < pfdata->bus[i].nload; j++) { 4389566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_power->compkey_load,&pfdata->load[loadj++],0)); 439c4762a1bSJed Brown } 440c4762a1bSJed Brown } 441c4762a1bSJed Brown } 442c4762a1bSJed Brown 443c4762a1bSJed Brown /* ADD VARIABLES AND COMPONENTS FOR THE WATER SUBNETWORK */ 4442bf73ac6SHong Zhang /*-------------------------------------------------------*/ 4459566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm,water_netnum,&nv,&ne,&vtx,&edges)); 446c4762a1bSJed Brown for (i = 0; i < ne; i++) { 4479566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,edges[i],appctx_water->compkey_edge,&waterdata->edge[i],0)); 448c4762a1bSJed Brown } 449c4762a1bSJed Brown 450c4762a1bSJed Brown for (i = 0; i < nv; i++) { 4519566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm,vtx[i],&flg)); 4522bf73ac6SHong Zhang if (flg) continue; 4532bf73ac6SHong Zhang 4549566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_water->compkey_vtx,&waterdata->vertex[i],1)); 455c4762a1bSJed Brown } 4562bf73ac6SHong Zhang 457eac198afSGetnet /* 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 */ 4582bf73ac6SHong Zhang /*----------------------------------------------------------------------------------------------------------------------------*/ 4599566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm,&nv,&vtx)); 4602bf73ac6SHong Zhang for (i = 0; i < nv; i++) { 4612bf73ac6SHong Zhang /* power */ 4629566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_power->compkey_bus,&pfdata->bus[4],2)); 4632bf73ac6SHong Zhang /* bus[4] is a load, add its component */ 4649566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_power->compkey_load,&pfdata->load[0],0)); 4652bf73ac6SHong Zhang 4662bf73ac6SHong Zhang /* water */ 4679566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm,vtx[i],appctx_water->compkey_vtx,&waterdata->vertex[0],1)); 468c4762a1bSJed Brown } 469c4762a1bSJed Brown 470c4762a1bSJed Brown /* Set up DM for use */ 4719566063dSJacob Faibussowitsch PetscCall(DMSetUp(networkdm)); 472c4762a1bSJed Brown if (viewDM) { 4739566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nAfter DMSetUp, DMView:\n")); 4749566063dSJacob Faibussowitsch PetscCall(DMView(networkdm,PETSC_VIEWER_STDOUT_WORLD)); 475c4762a1bSJed Brown } 476c4762a1bSJed Brown 477c4762a1bSJed Brown /* Free user objects */ 4789566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_power)); 4799566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->bus)); 4809566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->gen)); 4819566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->branch)); 4829566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata->load)); 4839566063dSJacob Faibussowitsch PetscCall(PetscFree(pfdata)); 4842bf73ac6SHong Zhang 4859566063dSJacob Faibussowitsch PetscCall(PetscFree(edgelist_water)); 4869566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->vertex)); 4879566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata->edge)); 4889566063dSJacob Faibussowitsch PetscCall(PetscFree(waterdata)); 489c4762a1bSJed Brown 490d5c9c0c4SHong Zhang /* Re-distribute networkdm to multiple processes for better job balance */ 4912bf73ac6SHong Zhang if (size >1 && distribute) { 4929566063dSJacob Faibussowitsch PetscCall(DMNetworkDistribute(&networkdm,0)); 493c4762a1bSJed Brown if (viewDM) { 4949566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nAfter DMNetworkDistribute, DMView:\n")); 4959566063dSJacob Faibussowitsch PetscCall(DMView(networkdm,PETSC_VIEWER_STDOUT_WORLD)); 496c4762a1bSJed Brown } 497d5c9c0c4SHong Zhang } 498c4762a1bSJed Brown 4992bf73ac6SHong Zhang /* Test DMNetworkGetSubnetwork() and DMNetworkGetSubnetworkSharedVertices() */ 500c4762a1bSJed Brown if (test) { 5012bf73ac6SHong Zhang PetscInt v,gidx; 5029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 5032bf73ac6SHong Zhang for (i=0; i<Nsubnet; i++) { 5049566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm,i,&nv,&ne,&vtx,&edges)); 50563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] After distribute, subnet[%" PetscInt_FMT "] ne %" PetscInt_FMT ", nv %" PetscInt_FMT "\n",rank,i,ne,nv)); 5069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 507c4762a1bSJed Brown 5082bf73ac6SHong Zhang for (v=0; v<nv; v++) { 5099566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm,vtx[v],&ghost)); 5109566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm,vtx[v],&gidx)); 51163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] subnet[%" PetscInt_FMT "] v %" PetscInt_FMT " %" PetscInt_FMT "; ghost %d\n",rank,i,vtx[v],gidx,ghost)); 512c4762a1bSJed Brown } 5139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 514c4762a1bSJed Brown } 5159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 5162bf73ac6SHong Zhang 5179566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSharedVertices(networkdm,&nv,&vtx)); 51863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] After distribute, num of shared vertices nsv = %" PetscInt_FMT "\n",rank,nv)); 5192bf73ac6SHong Zhang for (v=0; v<nv; v++) { 5209566063dSJacob Faibussowitsch PetscCall(DMNetworkGetGlobalVertexIndex(networkdm,vtx[v],&gidx)); 52163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] sv %" PetscInt_FMT ", gidx=%" PetscInt_FMT "\n",rank,vtx[v],gidx)); 5222bf73ac6SHong Zhang } 5239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD)); 524c4762a1bSJed Brown } 525c4762a1bSJed Brown 5262bf73ac6SHong Zhang /* Create solution vector X */ 5279566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(networkdm,&X)); 5289566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X,&F)); 5299566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm,&user.localXold)); 5302bf73ac6SHong Zhang PetscLogStagePop(); 531c4762a1bSJed Brown 532c4762a1bSJed Brown /* (3) Setup Solvers */ 533c4762a1bSJed Brown /*-------------------*/ 5349566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-viewJ",&viewJ,NULL)); 5359566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-viewX",&viewX,NULL)); 536c4762a1bSJed Brown 5379566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Setup",&stage[2])); 5389566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[2])); 539c4762a1bSJed Brown 5409566063dSJacob Faibussowitsch PetscCall(SetInitialGuess(networkdm,X,&user)); 541c4762a1bSJed Brown 542c4762a1bSJed Brown /* Create coupled snes */ 543c4762a1bSJed Brown /*-------------------- */ 5449566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"SNES_coupled setup ......\n")); 5452bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 5469566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD,&snes)); 5479566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes,networkdm)); 5489566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes,"coupled_")); 5499566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes,F,FormFunction,&user)); 5509566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes,UserMonitor,&user,NULL)); 5519566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes)); 552c4762a1bSJed Brown 553c4762a1bSJed Brown if (viewJ) { 554c4762a1bSJed Brown /* View Jac structure */ 5559566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes,&Jac,NULL,NULL,NULL)); 5569566063dSJacob Faibussowitsch PetscCall(MatView(Jac,PETSC_VIEWER_DRAW_WORLD)); 557c4762a1bSJed Brown } 558c4762a1bSJed Brown 559c4762a1bSJed Brown if (viewX) { 5609566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Solution:\n")); 5619566063dSJacob Faibussowitsch PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); 562c4762a1bSJed Brown } 563c4762a1bSJed Brown 564c4762a1bSJed Brown if (viewJ) { 565c4762a1bSJed Brown /* View assembled Jac */ 5669566063dSJacob Faibussowitsch PetscCall(MatView(Jac,PETSC_VIEWER_DRAW_WORLD)); 567c4762a1bSJed Brown } 568c4762a1bSJed Brown 569c4762a1bSJed Brown /* Create snes_power */ 570c4762a1bSJed Brown /*-------------------*/ 5719566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"SNES_power setup ......\n")); 572c4762a1bSJed Brown 573c4762a1bSJed Brown user.subsnes_id = 0; 5749566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD,&snes_power)); 5759566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_power,networkdm)); 5769566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_power,"power_")); 5779566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_power,F,FormFunction,&user)); 5789566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_power,UserMonitor,&user,NULL)); 579c4762a1bSJed Brown 580c4762a1bSJed Brown /* Use user-provide Jacobian */ 5819566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(networkdm,&Jac)); 5829566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes_power,Jac,Jac,FormJacobian_subPower,&user)); 5839566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_power)); 584c4762a1bSJed Brown 585c4762a1bSJed Brown if (viewX) { 5869566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Power Solution:\n")); 5879566063dSJacob Faibussowitsch PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); 588c4762a1bSJed Brown } 589c4762a1bSJed Brown if (viewJ) { 5909566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Power Jac:\n")); 5919566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes_power,&Jac,NULL,NULL,NULL)); 5929566063dSJacob Faibussowitsch PetscCall(MatView(Jac,PETSC_VIEWER_DRAW_WORLD)); 5939566063dSJacob Faibussowitsch /* PetscCall(MatView(Jac,PETSC_VIEWER_STDOUT_WORLD)); */ 594c4762a1bSJed Brown } 595c4762a1bSJed Brown 596c4762a1bSJed Brown /* Create snes_water */ 597c4762a1bSJed Brown /*-------------------*/ 5989566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"SNES_water setup......\n")); 599c4762a1bSJed Brown 600c4762a1bSJed Brown user.subsnes_id = 1; 6019566063dSJacob Faibussowitsch PetscCall(SNESCreate(PETSC_COMM_WORLD,&snes_water)); 6029566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes_water,networkdm)); 6039566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes_water,"water_")); 6049566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes_water,F,FormFunction,&user)); 6059566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes_water,UserMonitor,&user,NULL)); 6069566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes_water)); 607c4762a1bSJed Brown 608c4762a1bSJed Brown if (viewX) { 6099566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Water Solution:\n")); 6109566063dSJacob Faibussowitsch PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); 611c4762a1bSJed Brown } 6129566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 613c4762a1bSJed Brown 614c4762a1bSJed Brown /* (4) Solve */ 615c4762a1bSJed Brown /*-----------*/ 6169566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("SNES Solve",&stage[3])); 6179566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage[3])); 618c4762a1bSJed Brown user.it = 0; 619c4762a1bSJed Brown reason = SNES_DIVERGED_DTOL; 620c4762a1bSJed Brown while (user.it < it_max && (PetscInt)reason<0) { 621c4762a1bSJed Brown #if 0 622c4762a1bSJed Brown user.subsnes_id = 0; 6239566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_power,NULL,X)); 624c4762a1bSJed Brown 625c4762a1bSJed Brown user.subsnes_id = 1; 6269566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes_water,NULL,X)); 627c4762a1bSJed Brown #endif 6282bf73ac6SHong Zhang user.subsnes_id = Nsubnet; 6299566063dSJacob Faibussowitsch PetscCall(SNESSolve(snes,NULL,X)); 630c4762a1bSJed Brown 6319566063dSJacob Faibussowitsch PetscCall(SNESGetConvergedReason(snes,&reason)); 632c4762a1bSJed Brown user.it++; 633c4762a1bSJed Brown } 63463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Coupled_SNES converged in %" PetscInt_FMT " iterations\n",user.it)); 635c4762a1bSJed Brown if (viewX) { 6369566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Final Solution:\n")); 6379566063dSJacob Faibussowitsch PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); 638c4762a1bSJed Brown } 6399566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 640c4762a1bSJed Brown 641c4762a1bSJed Brown /* Free objects */ 642c4762a1bSJed Brown /* -------------*/ 6439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X)); 6449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&F)); 6459566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm,&user.localXold)); 646c4762a1bSJed Brown 6479566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes)); 6489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Jac)); 6499566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_power)); 6509566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes_water)); 651c4762a1bSJed Brown 6529566063dSJacob Faibussowitsch PetscCall(DMDestroy(&networkdm)); 6539566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 654b122ec5aSJacob Faibussowitsch return 0; 655c4762a1bSJed Brown } 656c4762a1bSJed Brown 657c4762a1bSJed Brown /*TEST 658c4762a1bSJed Brown 659c4762a1bSJed Brown build: 660dfd57a17SPierre Jolivet requires: !complex double defined(PETSC_HAVE_ATTRIBUTEALIGNED) 661c4762a1bSJed Brown depends: power/PFReadData.c power/pffunctions.c water/waterreaddata.c water/waterfunctions.c 662c4762a1bSJed Brown 663c4762a1bSJed Brown test: 6642bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -viewDM 665c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 666c4762a1bSJed Brown output_file: output/ex1.out 667c4762a1bSJed Brown 668c4762a1bSJed Brown test: 669c4762a1bSJed Brown suffix: 2 670c4762a1bSJed Brown nsize: 3 6712bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type parmetis 672c4762a1bSJed Brown localrunfiles: ex1options power/case9.m water/sample1.inp 673d5c9c0c4SHong Zhang output_file: output/ex1_2.out 6742bf73ac6SHong Zhang requires: parmetis 6752bf73ac6SHong Zhang 6762bf73ac6SHong Zhang # test: 6772bf73ac6SHong Zhang # suffix: 3 6782bf73ac6SHong Zhang # nsize: 3 6792bf73ac6SHong Zhang # args: -coupled_snes_converged_reason -options_left no -distribute false 6802bf73ac6SHong Zhang # localrunfiles: ex1options power/case9.m water/sample1.inp 6812bf73ac6SHong Zhang # output_file: output/ex1_2.out 682d5c9c0c4SHong Zhang 683d5c9c0c4SHong Zhang test: 6842bf73ac6SHong Zhang suffix: 4 6852bf73ac6SHong Zhang nsize: 4 6862bf73ac6SHong Zhang args: -coupled_snes_converged_reason -options_left no -petscpartitioner_type simple -viewDM 687d5c9c0c4SHong Zhang localrunfiles: ex1options power/case9.m water/sample1.inp 6882bf73ac6SHong Zhang output_file: output/ex1_4.out 689c4762a1bSJed Brown 690c4762a1bSJed Brown TEST*/ 691