142dc13f1SHong Zhang static char help[] = "This example demonstrates DMNetwork. It is used for testing parallel generation of dmnetwork, then redistribute. \n\\n"; 242dc13f1SHong Zhang /* 342dc13f1SHong Zhang Example: mpiexec -n <np> ./pipes -ts_max_steps 10 442dc13f1SHong Zhang */ 542dc13f1SHong Zhang 642dc13f1SHong Zhang #include "wash.h" 742dc13f1SHong Zhang 842dc13f1SHong Zhang /* 942dc13f1SHong Zhang WashNetworkDistribute - proc[0] distributes sequential wash object 1042dc13f1SHong Zhang Input Parameters: 1142dc13f1SHong Zhang . comm - MPI communicator 1242dc13f1SHong Zhang . wash - wash context with all network data in proc[0] 1342dc13f1SHong Zhang 1442dc13f1SHong Zhang Output Parameter: 1542dc13f1SHong Zhang . wash - wash context with nedge, nvertex and edgelist distributed 1642dc13f1SHong Zhang 1742dc13f1SHong Zhang Note: The routine is used for testing parallel generation of dmnetwork, then redistribute. 1842dc13f1SHong Zhang */ 199371c9d4SSatish Balay PetscErrorCode WashNetworkDistribute(MPI_Comm comm, Wash wash) { 2042dc13f1SHong Zhang PetscMPIInt rank, size, tag = 0; 2142dc13f1SHong Zhang PetscInt i, e, v, numEdges, numVertices, nedges, *eowners = NULL, estart, eend, *vtype = NULL, nvertices; 2242dc13f1SHong Zhang PetscInt *edgelist = wash->edgelist, *nvtx = NULL, *vtxDone = NULL; 2342dc13f1SHong Zhang 2442dc13f1SHong Zhang PetscFunctionBegin; 259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 2642dc13f1SHong Zhang if (size == 1) PetscFunctionReturn(0); 2742dc13f1SHong Zhang 289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2942dc13f1SHong Zhang numEdges = wash->nedge; 3042dc13f1SHong Zhang numVertices = wash->nvertex; 3142dc13f1SHong Zhang 3242dc13f1SHong Zhang /* (1) all processes get global and local number of edges */ 339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numEdges, 1, MPIU_INT, 0, comm)); 3442dc13f1SHong Zhang nedges = numEdges / size; /* local nedges */ 359371c9d4SSatish Balay if (rank == 0) { nedges += numEdges - size * (numEdges / size); } 3642dc13f1SHong Zhang wash->Nedge = numEdges; 3742dc13f1SHong Zhang wash->nedge = nedges; 389566063dSJacob Faibussowitsch /* PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] nedges %d, numEdges %d\n",rank,nedges,numEdges)); */ 3942dc13f1SHong Zhang 409566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(size + 1, &eowners, size, &nvtx, numVertices, &vtxDone)); 419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&nedges, 1, MPIU_INT, eowners + 1, 1, MPIU_INT, PETSC_COMM_WORLD)); 4242dc13f1SHong Zhang eowners[0] = 0; 439371c9d4SSatish Balay for (i = 2; i <= size; i++) { eowners[i] += eowners[i - 1]; } 4442dc13f1SHong Zhang 4542dc13f1SHong Zhang estart = eowners[rank]; 4642dc13f1SHong Zhang eend = eowners[rank + 1]; 479566063dSJacob Faibussowitsch /* PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] own lists row %d - %d\n",rank,estart,eend)); */ 4842dc13f1SHong Zhang 4942dc13f1SHong Zhang /* (2) distribute row block edgelist to all processors */ 50dd400576SPatrick Sanan if (rank == 0) { 5142dc13f1SHong Zhang vtype = wash->vtype; 5242dc13f1SHong Zhang for (i = 1; i < size; i++) { 5342dc13f1SHong Zhang /* proc[0] sends edgelist to proc[i] */ 549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(edgelist + 2 * eowners[i], 2 * (eowners[i + 1] - eowners[i]), MPIU_INT, i, tag, comm)); 5542dc13f1SHong Zhang 5642dc13f1SHong Zhang /* proc[0] sends vtype to proc[i] */ 579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vtype + 2 * eowners[i], 2 * (eowners[i + 1] - eowners[i]), MPIU_INT, i, tag, comm)); 5842dc13f1SHong Zhang } 5942dc13f1SHong Zhang } else { 6042dc13f1SHong Zhang MPI_Status status; 619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * (eend - estart), &vtype)); 629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * (eend - estart), &edgelist)); 6342dc13f1SHong Zhang 649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(edgelist, 2 * (eend - estart), MPIU_INT, 0, tag, comm, &status)); 659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(vtype, 2 * (eend - estart), MPIU_INT, 0, tag, comm, &status)); 6642dc13f1SHong Zhang } 6742dc13f1SHong Zhang 6842dc13f1SHong Zhang wash->edgelist = edgelist; 6942dc13f1SHong Zhang 7042dc13f1SHong Zhang /* (3) all processes get global and local number of vertices, without ghost vertices */ 71dd400576SPatrick Sanan if (rank == 0) { 7242dc13f1SHong Zhang for (i = 0; i < size; i++) { 7342dc13f1SHong Zhang for (e = eowners[i]; e < eowners[i + 1]; e++) { 7442dc13f1SHong Zhang v = edgelist[2 * e]; 7542dc13f1SHong Zhang if (!vtxDone[v]) { 769371c9d4SSatish Balay nvtx[i]++; 779371c9d4SSatish Balay vtxDone[v] = 1; 7842dc13f1SHong Zhang } 7942dc13f1SHong Zhang v = edgelist[2 * e + 1]; 8042dc13f1SHong Zhang if (!vtxDone[v]) { 819371c9d4SSatish Balay nvtx[i]++; 829371c9d4SSatish Balay vtxDone[v] = 1; 8342dc13f1SHong Zhang } 8442dc13f1SHong Zhang } 8542dc13f1SHong Zhang } 8642dc13f1SHong Zhang } 879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numVertices, 1, MPIU_INT, 0, PETSC_COMM_WORLD)); 889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scatter(nvtx, 1, MPIU_INT, &nvertices, 1, MPIU_INT, 0, PETSC_COMM_WORLD)); 899566063dSJacob Faibussowitsch PetscCall(PetscFree3(eowners, nvtx, vtxDone)); 9042dc13f1SHong Zhang 9142dc13f1SHong Zhang wash->Nvertex = numVertices; 9242dc13f1SHong Zhang wash->nvertex = nvertices; 9342dc13f1SHong Zhang wash->vtype = vtype; 9442dc13f1SHong Zhang PetscFunctionReturn(0); 9542dc13f1SHong Zhang } 9642dc13f1SHong Zhang 979371c9d4SSatish Balay PetscErrorCode WASHIFunction(TS ts, PetscReal t, Vec X, Vec Xdot, Vec F, void *ctx) { 9842dc13f1SHong Zhang Wash wash = (Wash)ctx; 9942dc13f1SHong Zhang DM networkdm; 10042dc13f1SHong Zhang Vec localX, localXdot, localF, localXold; 10142dc13f1SHong Zhang const PetscInt *cone; 10242dc13f1SHong Zhang PetscInt vfrom, vto, offsetfrom, offsetto, varoffset; 10342dc13f1SHong Zhang PetscInt v, vStart, vEnd, e, eStart, eEnd; 10442dc13f1SHong Zhang PetscInt nend, type; 10542dc13f1SHong Zhang PetscBool ghost; 10642dc13f1SHong Zhang PetscScalar *farr, *juncf, *pipef; 10742dc13f1SHong Zhang PetscReal dt; 10842dc13f1SHong Zhang Pipe pipe; 10942dc13f1SHong Zhang PipeField *pipex, *pipexdot, *juncx; 11042dc13f1SHong Zhang Junction junction; 11142dc13f1SHong Zhang DMDALocalInfo info; 11242dc13f1SHong Zhang const PetscScalar *xarr, *xdotarr, *xoldarr; 11342dc13f1SHong Zhang 11442dc13f1SHong Zhang PetscFunctionBegin; 11542dc13f1SHong Zhang localX = wash->localX; 11642dc13f1SHong Zhang localXdot = wash->localXdot; 11742dc13f1SHong Zhang 1189566063dSJacob Faibussowitsch PetscCall(TSGetSolution(ts, &localXold)); 1199566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &networkdm)); 1209566063dSJacob Faibussowitsch PetscCall(TSGetTimeStep(ts, &dt)); 1219566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localF)); 12242dc13f1SHong Zhang 12342dc13f1SHong Zhang /* Set F and localF as zero */ 1249566063dSJacob Faibussowitsch PetscCall(VecSet(F, 0.0)); 1259566063dSJacob Faibussowitsch PetscCall(VecSet(localF, 0.0)); 12642dc13f1SHong Zhang 12742dc13f1SHong Zhang /* Update ghost values of locaX and locaXdot */ 1289566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX)); 1299566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX)); 13042dc13f1SHong Zhang 1319566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, Xdot, INSERT_VALUES, localXdot)); 1329566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, Xdot, INSERT_VALUES, localXdot)); 13342dc13f1SHong Zhang 1349566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localX, &xarr)); 1359566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localXdot, &xdotarr)); 1369566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localXold, &xoldarr)); 1379566063dSJacob Faibussowitsch PetscCall(VecGetArray(localF, &farr)); 13842dc13f1SHong Zhang 13942dc13f1SHong Zhang /* junction->type == JUNCTION: 14042dc13f1SHong Zhang juncf[0] = -qJ + sum(qin); juncf[1] = qJ - sum(qout) 14142dc13f1SHong Zhang junction->type == RESERVOIR (upper stream): 14242dc13f1SHong Zhang juncf[0] = -hJ + H0; juncf[1] = qJ - sum(qout) 14342dc13f1SHong Zhang junction->type == VALVE (down stream): 14442dc13f1SHong Zhang juncf[0] = -qJ + sum(qin); juncf[1] = qJ 14542dc13f1SHong Zhang */ 14642dc13f1SHong Zhang /* Vertex/junction initialization */ 1479566063dSJacob Faibussowitsch PetscCall(DMNetworkGetVertexRange(networkdm, &vStart, &vEnd)); 14842dc13f1SHong Zhang for (v = vStart; v < vEnd; v++) { 1499566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, v, &ghost)); 15042dc13f1SHong Zhang if (ghost) continue; 15142dc13f1SHong Zhang 1529566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, v, 0, &type, (void **)&junction, NULL)); 1539566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, v, ALL_COMPONENTS, &varoffset)); 15442dc13f1SHong Zhang juncx = (PipeField *)(xarr + varoffset); 15542dc13f1SHong Zhang juncf = (PetscScalar *)(farr + varoffset); 15642dc13f1SHong Zhang 15742dc13f1SHong Zhang juncf[0] = -juncx[0].q; 15842dc13f1SHong Zhang juncf[1] = juncx[0].q; 15942dc13f1SHong Zhang 16042dc13f1SHong Zhang if (junction->type == RESERVOIR) { /* upstream reservoir */ 16142dc13f1SHong Zhang juncf[0] = juncx[0].h - wash->H0; 16242dc13f1SHong Zhang } 16342dc13f1SHong Zhang } 16442dc13f1SHong Zhang 16542dc13f1SHong Zhang /* Edge/pipe */ 1669566063dSJacob Faibussowitsch PetscCall(DMNetworkGetEdgeRange(networkdm, &eStart, &eEnd)); 16742dc13f1SHong Zhang for (e = eStart; e < eEnd; e++) { 1689566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, e, 0, &type, (void **)&pipe, NULL)); 1699566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, e, ALL_COMPONENTS, &varoffset)); 17042dc13f1SHong Zhang pipex = (PipeField *)(xarr + varoffset); 17142dc13f1SHong Zhang pipexdot = (PipeField *)(xdotarr + varoffset); 17242dc13f1SHong Zhang pipef = (PetscScalar *)(farr + varoffset); 17342dc13f1SHong Zhang 17442dc13f1SHong Zhang /* Get some data into the pipe structure: note, some of these operations 17542dc13f1SHong Zhang * might be redundant. Will it consume too much time? */ 17642dc13f1SHong Zhang pipe->dt = dt; 17742dc13f1SHong Zhang pipe->xold = (PipeField *)(xoldarr + varoffset); 17842dc13f1SHong Zhang 17942dc13f1SHong Zhang /* Evaluate F over this edge/pipe: pipef[1], ...,pipef[2*nend] */ 1809566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(pipe->da, &info)); 1819566063dSJacob Faibussowitsch PetscCall(PipeIFunctionLocal_Lax(&info, t, pipex, pipexdot, pipef, pipe)); 18242dc13f1SHong Zhang 18342dc13f1SHong Zhang /* Get boundary values from connected vertices */ 1849566063dSJacob Faibussowitsch PetscCall(DMNetworkGetConnectedVertices(networkdm, e, &cone)); 18542dc13f1SHong Zhang vfrom = cone[0]; /* local ordering */ 18642dc13f1SHong Zhang vto = cone[1]; 1879566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vfrom, ALL_COMPONENTS, &offsetfrom)); 1889566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vto, ALL_COMPONENTS, &offsetto)); 18942dc13f1SHong Zhang 19042dc13f1SHong Zhang /* Evaluate upstream boundary */ 1919566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vfrom, 0, &type, (void **)&junction, NULL)); 192cad9d221SBarry Smith PetscCheck(junction->type == JUNCTION || junction->type == RESERVOIR, PETSC_COMM_SELF, PETSC_ERR_SUP, "junction type is not supported"); 19342dc13f1SHong Zhang juncx = (PipeField *)(xarr + offsetfrom); 19442dc13f1SHong Zhang juncf = (PetscScalar *)(farr + offsetfrom); 19542dc13f1SHong Zhang 19642dc13f1SHong Zhang pipef[0] = pipex[0].h - juncx[0].h; 19742dc13f1SHong Zhang juncf[1] -= pipex[0].q; 19842dc13f1SHong Zhang 19942dc13f1SHong Zhang /* Evaluate downstream boundary */ 2009566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vto, 0, &type, (void **)&junction, NULL)); 201cad9d221SBarry Smith PetscCheck(junction->type == JUNCTION || junction->type == VALVE, PETSC_COMM_SELF, PETSC_ERR_SUP, "junction type is not supported"); 20242dc13f1SHong Zhang juncx = (PipeField *)(xarr + offsetto); 20342dc13f1SHong Zhang juncf = (PetscScalar *)(farr + offsetto); 20442dc13f1SHong Zhang nend = pipe->nnodes - 1; 20542dc13f1SHong Zhang 20642dc13f1SHong Zhang pipef[2 * nend + 1] = pipex[nend].h - juncx[0].h; 20742dc13f1SHong Zhang juncf[0] += pipex[nend].q; 20842dc13f1SHong Zhang } 20942dc13f1SHong Zhang 2109566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localX, &xarr)); 2119566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localXdot, &xdotarr)); 2129566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localF, &farr)); 21342dc13f1SHong Zhang 2149566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localF, ADD_VALUES, F)); 2159566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localF, ADD_VALUES, F)); 2169566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localF)); 21742dc13f1SHong Zhang /* 2189566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD("F:\n")); 2199566063dSJacob Faibussowitsch PetscCall(VecView(F,PETSC_VIEWER_STDOUT_WORLD)); 22042dc13f1SHong Zhang */ 22142dc13f1SHong Zhang PetscFunctionReturn(0); 22242dc13f1SHong Zhang } 22342dc13f1SHong Zhang 2249371c9d4SSatish Balay PetscErrorCode WASHSetInitialSolution(DM networkdm, Vec X, Wash wash) { 22542dc13f1SHong Zhang PetscInt k, nx, vkey, vfrom, vto, offsetfrom, offsetto; 22642dc13f1SHong Zhang PetscInt type, varoffset; 22742dc13f1SHong Zhang PetscInt e, eStart, eEnd; 22842dc13f1SHong Zhang Vec localX; 22942dc13f1SHong Zhang PetscScalar *xarr; 23042dc13f1SHong Zhang Pipe pipe; 23142dc13f1SHong Zhang Junction junction; 23242dc13f1SHong Zhang const PetscInt *cone; 23342dc13f1SHong Zhang const PetscScalar *xarray; 23442dc13f1SHong Zhang 23542dc13f1SHong Zhang PetscFunctionBegin; 2369566063dSJacob Faibussowitsch PetscCall(VecSet(X, 0.0)); 2379566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localX)); 2389566063dSJacob Faibussowitsch PetscCall(VecGetArray(localX, &xarr)); 23942dc13f1SHong Zhang 24042dc13f1SHong Zhang /* Edge */ 2419566063dSJacob Faibussowitsch PetscCall(DMNetworkGetEdgeRange(networkdm, &eStart, &eEnd)); 24242dc13f1SHong Zhang for (e = eStart; e < eEnd; e++) { 2439566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, e, ALL_COMPONENTS, &varoffset)); 2449566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, e, 0, &type, (void **)&pipe, NULL)); 24542dc13f1SHong Zhang 24642dc13f1SHong Zhang /* set initial values for this pipe */ 2479566063dSJacob Faibussowitsch PetscCall(PipeComputeSteadyState(pipe, wash->Q0, wash->H0)); 2489566063dSJacob Faibussowitsch PetscCall(VecGetSize(pipe->x, &nx)); 24942dc13f1SHong Zhang 2509566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pipe->x, &xarray)); 25142dc13f1SHong Zhang /* copy pipe->x to xarray */ 2529371c9d4SSatish Balay for (k = 0; k < nx; k++) { (xarr + varoffset)[k] = xarray[k]; } 25342dc13f1SHong Zhang 25442dc13f1SHong Zhang /* set boundary values into vfrom and vto */ 2559566063dSJacob Faibussowitsch PetscCall(DMNetworkGetConnectedVertices(networkdm, e, &cone)); 25642dc13f1SHong Zhang vfrom = cone[0]; /* local ordering */ 25742dc13f1SHong Zhang vto = cone[1]; 2589566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vfrom, ALL_COMPONENTS, &offsetfrom)); 2599566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vto, ALL_COMPONENTS, &offsetto)); 26042dc13f1SHong Zhang 26142dc13f1SHong Zhang /* if vform is a head vertex: */ 2629566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vfrom, 0, &vkey, (void **)&junction, NULL)); 2639371c9d4SSatish Balay if (junction->type == RESERVOIR) { (xarr + offsetfrom)[1] = wash->H0; /* 1st H */ } 26442dc13f1SHong Zhang 26542dc13f1SHong Zhang /* if vto is an end vertex: */ 2669566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vto, 0, &vkey, (void **)&junction, NULL)); 2679371c9d4SSatish Balay if (junction->type == VALVE) { (xarr + offsetto)[0] = wash->QL; /* last Q */ } 2689566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pipe->x, &xarray)); 26942dc13f1SHong Zhang } 27042dc13f1SHong Zhang 2719566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localX, &xarr)); 2729566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localX, ADD_VALUES, X)); 2739566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localX, ADD_VALUES, X)); 2749566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localX)); 27542dc13f1SHong Zhang 27642dc13f1SHong Zhang #if 0 27742dc13f1SHong Zhang PetscInt N; 2789566063dSJacob Faibussowitsch PetscCall(VecGetSize(X,&N)); 2799566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"initial solution %d:\n",N)); 2809566063dSJacob Faibussowitsch PetscCall(VecView(X,PETSC_VIEWER_STDOUT_WORLD)); 28142dc13f1SHong Zhang #endif 28242dc13f1SHong Zhang PetscFunctionReturn(0); 28342dc13f1SHong Zhang } 28442dc13f1SHong Zhang 2859371c9d4SSatish Balay PetscErrorCode TSDMNetworkMonitor(TS ts, PetscInt step, PetscReal t, Vec x, void *context) { 28642dc13f1SHong Zhang DMNetworkMonitor monitor; 28742dc13f1SHong Zhang 28842dc13f1SHong Zhang PetscFunctionBegin; 28942dc13f1SHong Zhang monitor = (DMNetworkMonitor)context; 2909566063dSJacob Faibussowitsch PetscCall(DMNetworkMonitorView(monitor, x)); 29142dc13f1SHong Zhang PetscFunctionReturn(0); 29242dc13f1SHong Zhang } 29342dc13f1SHong Zhang 2949371c9d4SSatish Balay PetscErrorCode PipesView(DM networkdm, PetscInt KeyPipe, Vec X) { 29542dc13f1SHong Zhang PetscInt i, numkeys = 1, *blocksize, *numselectedvariable, **selectedvariables, n; 29642dc13f1SHong Zhang IS isfrom_q, isfrom_h, isfrom; 29742dc13f1SHong Zhang Vec Xto; 29842dc13f1SHong Zhang VecScatter ctx; 29942dc13f1SHong Zhang MPI_Comm comm; 30042dc13f1SHong Zhang 30142dc13f1SHong Zhang PetscFunctionBegin; 3029566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)networkdm, &comm)); 30342dc13f1SHong Zhang 30442dc13f1SHong Zhang /* 1. Create isfrom_q for q-variable of pipes */ 3059566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(numkeys, &blocksize, numkeys, &numselectedvariable, numkeys, &selectedvariables)); 30642dc13f1SHong Zhang for (i = 0; i < numkeys; i++) { 30742dc13f1SHong Zhang blocksize[i] = 2; 30842dc13f1SHong Zhang numselectedvariable[i] = 1; 3099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numselectedvariable[i], &selectedvariables[i])); 31042dc13f1SHong Zhang selectedvariables[i][0] = 0; /* q-variable */ 31142dc13f1SHong Zhang } 3129566063dSJacob Faibussowitsch PetscCall(DMNetworkCreateIS(networkdm, numkeys, &KeyPipe, blocksize, numselectedvariable, selectedvariables, &isfrom_q)); 31342dc13f1SHong Zhang 31442dc13f1SHong Zhang /* 2. Create Xto and isto */ 3159566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isfrom_q, &n)); 3169566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, &Xto)); 3179566063dSJacob Faibussowitsch PetscCall(VecSetSizes(Xto, n, PETSC_DECIDE)); 3189566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(Xto)); 3199566063dSJacob Faibussowitsch PetscCall(VecSet(Xto, 0.0)); 32042dc13f1SHong Zhang 32142dc13f1SHong Zhang /* 3. Create scatter */ 3229566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(X, isfrom_q, Xto, NULL, &ctx)); 32342dc13f1SHong Zhang 32442dc13f1SHong Zhang /* 4. Scatter to Xq */ 3259566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(ctx, X, Xto, INSERT_VALUES, SCATTER_FORWARD)); 3269566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(ctx, X, Xto, INSERT_VALUES, SCATTER_FORWARD)); 3279566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 3289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isfrom_q)); 32942dc13f1SHong Zhang 3309566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Xq:\n")); 3319566063dSJacob Faibussowitsch PetscCall(VecView(Xto, PETSC_VIEWER_STDOUT_WORLD)); 33242dc13f1SHong Zhang 33342dc13f1SHong Zhang /* 5. Create isfrom_h for h-variable of pipes; Create scatter; Scatter to Xh */ 3349371c9d4SSatish Balay for (i = 0; i < numkeys; i++) { selectedvariables[i][0] = 1; /* h-variable */ } 3359566063dSJacob Faibussowitsch PetscCall(DMNetworkCreateIS(networkdm, numkeys, &KeyPipe, blocksize, numselectedvariable, selectedvariables, &isfrom_h)); 33642dc13f1SHong Zhang 3379566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(X, isfrom_h, Xto, NULL, &ctx)); 3389566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(ctx, X, Xto, INSERT_VALUES, SCATTER_FORWARD)); 3399566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(ctx, X, Xto, INSERT_VALUES, SCATTER_FORWARD)); 3409566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 3419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isfrom_h)); 34242dc13f1SHong Zhang 3439566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Xh:\n")); 3449566063dSJacob Faibussowitsch PetscCall(VecView(Xto, PETSC_VIEWER_STDOUT_WORLD)); 3459566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Xto)); 34642dc13f1SHong Zhang 34742dc13f1SHong Zhang /* 6. Create isfrom for all pipe variables; Create scatter; Scatter to Xpipes */ 3489371c9d4SSatish Balay for (i = 0; i < numkeys; i++) { blocksize[i] = -1; /* select all the variables of the i-th component */ } 3499566063dSJacob Faibussowitsch PetscCall(DMNetworkCreateIS(networkdm, numkeys, &KeyPipe, blocksize, NULL, NULL, &isfrom)); 3509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isfrom)); 3519566063dSJacob Faibussowitsch PetscCall(DMNetworkCreateIS(networkdm, numkeys, &KeyPipe, NULL, NULL, NULL, &isfrom)); 35242dc13f1SHong Zhang 3539566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isfrom, &n)); 3549566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, &Xto)); 3559566063dSJacob Faibussowitsch PetscCall(VecSetSizes(Xto, n, PETSC_DECIDE)); 3569566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(Xto)); 3579566063dSJacob Faibussowitsch PetscCall(VecSet(Xto, 0.0)); 35842dc13f1SHong Zhang 3599566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(X, isfrom, Xto, NULL, &ctx)); 3609566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(ctx, X, Xto, INSERT_VALUES, SCATTER_FORWARD)); 3619566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(ctx, X, Xto, INSERT_VALUES, SCATTER_FORWARD)); 3629566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 3639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isfrom)); 36442dc13f1SHong Zhang 3659566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Xpipes:\n")); 3669566063dSJacob Faibussowitsch PetscCall(VecView(Xto, PETSC_VIEWER_STDOUT_WORLD)); 36742dc13f1SHong Zhang 36842dc13f1SHong Zhang /* 7. Free spaces */ 369*48a46eb9SPierre Jolivet for (i = 0; i < numkeys; i++) PetscCall(PetscFree(selectedvariables[i])); 3709566063dSJacob Faibussowitsch PetscCall(PetscFree3(blocksize, numselectedvariable, selectedvariables)); 3719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Xto)); 37242dc13f1SHong Zhang PetscFunctionReturn(0); 37342dc13f1SHong Zhang } 37442dc13f1SHong Zhang 3759371c9d4SSatish Balay PetscErrorCode ISJunctionsView(DM networkdm, PetscInt KeyJunc) { 37642dc13f1SHong Zhang PetscInt numkeys = 1; 37742dc13f1SHong Zhang IS isfrom; 37842dc13f1SHong Zhang MPI_Comm comm; 37942dc13f1SHong Zhang PetscMPIInt rank; 38042dc13f1SHong Zhang 38142dc13f1SHong Zhang PetscFunctionBegin; 3829566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)networkdm, &comm)); 3839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 38442dc13f1SHong Zhang 38542dc13f1SHong Zhang /* Create a global isfrom for all junction variables */ 3869566063dSJacob Faibussowitsch PetscCall(DMNetworkCreateIS(networkdm, numkeys, &KeyJunc, NULL, NULL, NULL, &isfrom)); 3879566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "ISJunctions:\n")); 3889566063dSJacob Faibussowitsch PetscCall(ISView(isfrom, PETSC_VIEWER_STDOUT_WORLD)); 3899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isfrom)); 39042dc13f1SHong Zhang 39142dc13f1SHong Zhang /* Create a local isfrom for all junction variables */ 3929566063dSJacob Faibussowitsch PetscCall(DMNetworkCreateLocalIS(networkdm, numkeys, &KeyJunc, NULL, NULL, NULL, &isfrom)); 393c5853193SPierre Jolivet if (rank == 0) { 3949566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] ISLocalJunctions:\n", rank)); 3959566063dSJacob Faibussowitsch PetscCall(ISView(isfrom, PETSC_VIEWER_STDOUT_SELF)); 39642dc13f1SHong Zhang } 3979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isfrom)); 39842dc13f1SHong Zhang PetscFunctionReturn(0); 39942dc13f1SHong Zhang } 40042dc13f1SHong Zhang 4019371c9d4SSatish Balay PetscErrorCode WashNetworkCleanUp(Wash wash) { 40242dc13f1SHong Zhang PetscMPIInt rank; 40342dc13f1SHong Zhang 40442dc13f1SHong Zhang PetscFunctionBegin; 4059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(wash->comm, &rank)); 4069566063dSJacob Faibussowitsch PetscCall(PetscFree(wash->edgelist)); 4079566063dSJacob Faibussowitsch PetscCall(PetscFree(wash->vtype)); 408*48a46eb9SPierre Jolivet if (rank == 0) PetscCall(PetscFree2(wash->junction, wash->pipe)); 40942dc13f1SHong Zhang PetscFunctionReturn(0); 41042dc13f1SHong Zhang } 41142dc13f1SHong Zhang 4129371c9d4SSatish Balay PetscErrorCode WashNetworkCreate(MPI_Comm comm, PetscInt pipesCase, Wash *wash_ptr) { 41342dc13f1SHong Zhang PetscInt npipes; 41442dc13f1SHong Zhang PetscMPIInt rank; 41542dc13f1SHong Zhang Wash wash = NULL; 41642dc13f1SHong Zhang PetscInt i, numVertices, numEdges, *vtype; 41742dc13f1SHong Zhang PetscInt *edgelist; 41842dc13f1SHong Zhang Junction junctions = NULL; 41942dc13f1SHong Zhang Pipe pipes = NULL; 42042dc13f1SHong Zhang PetscBool washdist = PETSC_TRUE; 42142dc13f1SHong Zhang 42242dc13f1SHong Zhang PetscFunctionBegin; 4239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 42442dc13f1SHong Zhang 4259566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(1, &wash)); 42642dc13f1SHong Zhang wash->comm = comm; 42742dc13f1SHong Zhang *wash_ptr = wash; 42842dc13f1SHong Zhang wash->Q0 = 0.477432; /* RESERVOIR */ 42942dc13f1SHong Zhang wash->H0 = 150.0; 43042dc13f1SHong Zhang wash->HL = 143.488; /* VALVE */ 43142dc13f1SHong Zhang wash->QL = 0.0; 43242dc13f1SHong Zhang wash->nnodes_loc = 0; 43342dc13f1SHong Zhang 43442dc13f1SHong Zhang numVertices = 0; 43542dc13f1SHong Zhang numEdges = 0; 43642dc13f1SHong Zhang edgelist = NULL; 43742dc13f1SHong Zhang 43842dc13f1SHong Zhang /* proc[0] creates a sequential wash and edgelist */ 43963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Setup pipesCase %" PetscInt_FMT "\n", pipesCase)); 44042dc13f1SHong Zhang 44142dc13f1SHong Zhang /* Set global number of pipes, edges, and junctions */ 44242dc13f1SHong Zhang /*-------------------------------------------------*/ 44342dc13f1SHong Zhang switch (pipesCase) { 44442dc13f1SHong Zhang case 0: 44542dc13f1SHong Zhang /* pipeCase 0: */ 44642dc13f1SHong Zhang /* ================================================= 44742dc13f1SHong Zhang (RESERVOIR) v0 --E0--> v1--E1--> v2 --E2-->v3 (VALVE) 44842dc13f1SHong Zhang ==================================================== */ 44942dc13f1SHong Zhang npipes = 3; 4509566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-npipes", &npipes, NULL)); 45142dc13f1SHong Zhang wash->nedge = npipes; 45242dc13f1SHong Zhang wash->nvertex = npipes + 1; 45342dc13f1SHong Zhang 45442dc13f1SHong Zhang /* Set local edges and vertices -- proc[0] sets entire network, then distributes */ 45542dc13f1SHong Zhang numVertices = 0; 45642dc13f1SHong Zhang numEdges = 0; 45742dc13f1SHong Zhang edgelist = NULL; 458dd400576SPatrick Sanan if (rank == 0) { 45942dc13f1SHong Zhang numVertices = wash->nvertex; 46042dc13f1SHong Zhang numEdges = wash->nedge; 46142dc13f1SHong Zhang 4629566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(2 * numEdges, &edgelist)); 46342dc13f1SHong Zhang for (i = 0; i < numEdges; i++) { 4649371c9d4SSatish Balay edgelist[2 * i] = i; 4659371c9d4SSatish Balay edgelist[2 * i + 1] = i + 1; 46642dc13f1SHong Zhang } 46742dc13f1SHong Zhang 46842dc13f1SHong Zhang /* Add network components */ 46942dc13f1SHong Zhang /*------------------------*/ 4709566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(numVertices, &junctions, numEdges, &pipes)); 47142dc13f1SHong Zhang 47242dc13f1SHong Zhang /* vertex */ 47342dc13f1SHong Zhang for (i = 0; i < numVertices; i++) { 47442dc13f1SHong Zhang junctions[i].id = i; 47542dc13f1SHong Zhang junctions[i].type = JUNCTION; 47642dc13f1SHong Zhang } 47742dc13f1SHong Zhang 47842dc13f1SHong Zhang junctions[0].type = RESERVOIR; 47942dc13f1SHong Zhang junctions[numVertices - 1].type = VALVE; 48042dc13f1SHong Zhang } 48142dc13f1SHong Zhang break; 48242dc13f1SHong Zhang case 1: 48342dc13f1SHong Zhang /* pipeCase 1: */ 48442dc13f1SHong Zhang /* ========================== 48542dc13f1SHong Zhang v2 (VALVE) 48642dc13f1SHong Zhang ^ 48742dc13f1SHong Zhang | 48842dc13f1SHong Zhang E2 48942dc13f1SHong Zhang | 49042dc13f1SHong Zhang v0 --E0--> v3--E1--> v1 49142dc13f1SHong Zhang (RESERVOIR) (RESERVOIR) 49242dc13f1SHong Zhang ============================= */ 49342dc13f1SHong Zhang npipes = 3; 49442dc13f1SHong Zhang wash->nedge = npipes; 49542dc13f1SHong Zhang wash->nvertex = npipes + 1; 49642dc13f1SHong Zhang 49742dc13f1SHong Zhang /* Set local edges and vertices -- proc[0] sets entire network, then distributes */ 498dd400576SPatrick Sanan if (rank == 0) { 49942dc13f1SHong Zhang numVertices = wash->nvertex; 50042dc13f1SHong Zhang numEdges = wash->nedge; 50142dc13f1SHong Zhang 5029566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(2 * numEdges, &edgelist)); 5039371c9d4SSatish Balay edgelist[0] = 0; 5049371c9d4SSatish Balay edgelist[1] = 3; /* edge[0] */ 5059371c9d4SSatish Balay edgelist[2] = 3; 5069371c9d4SSatish Balay edgelist[3] = 1; /* edge[1] */ 5079371c9d4SSatish Balay edgelist[4] = 3; 5089371c9d4SSatish Balay edgelist[5] = 2; /* edge[2] */ 50942dc13f1SHong Zhang 51042dc13f1SHong Zhang /* Add network components */ 51142dc13f1SHong Zhang /*------------------------*/ 5129566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(numVertices, &junctions, numEdges, &pipes)); 51342dc13f1SHong Zhang /* vertex */ 51442dc13f1SHong Zhang for (i = 0; i < numVertices; i++) { 51542dc13f1SHong Zhang junctions[i].id = i; 51642dc13f1SHong Zhang junctions[i].type = JUNCTION; 51742dc13f1SHong Zhang } 51842dc13f1SHong Zhang 51942dc13f1SHong Zhang junctions[0].type = RESERVOIR; 52042dc13f1SHong Zhang junctions[1].type = VALVE; 52142dc13f1SHong Zhang junctions[2].type = VALVE; 52242dc13f1SHong Zhang } 52342dc13f1SHong Zhang break; 52442dc13f1SHong Zhang case 2: 52542dc13f1SHong Zhang /* pipeCase 2: */ 52642dc13f1SHong Zhang /* ========================== 52742dc13f1SHong Zhang (RESERVOIR) v2--> E2 52842dc13f1SHong Zhang | 52942dc13f1SHong Zhang v0 --E0--> v3--E1--> v1 53042dc13f1SHong Zhang (RESERVOIR) (VALVE) 53142dc13f1SHong Zhang ============================= */ 53242dc13f1SHong Zhang 53342dc13f1SHong Zhang /* Set application parameters -- to be used in function evalutions */ 53442dc13f1SHong Zhang npipes = 3; 53542dc13f1SHong Zhang wash->nedge = npipes; 53642dc13f1SHong Zhang wash->nvertex = npipes + 1; 53742dc13f1SHong Zhang 53842dc13f1SHong Zhang /* Set local edges and vertices -- proc[0] sets entire network, then distributes */ 539dd400576SPatrick Sanan if (rank == 0) { 54042dc13f1SHong Zhang numVertices = wash->nvertex; 54142dc13f1SHong Zhang numEdges = wash->nedge; 54242dc13f1SHong Zhang 5439566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(2 * numEdges, &edgelist)); 5449371c9d4SSatish Balay edgelist[0] = 0; 5459371c9d4SSatish Balay edgelist[1] = 3; /* edge[0] */ 5469371c9d4SSatish Balay edgelist[2] = 3; 5479371c9d4SSatish Balay edgelist[3] = 1; /* edge[1] */ 5489371c9d4SSatish Balay edgelist[4] = 2; 5499371c9d4SSatish Balay edgelist[5] = 3; /* edge[2] */ 55042dc13f1SHong Zhang 55142dc13f1SHong Zhang /* Add network components */ 55242dc13f1SHong Zhang /*------------------------*/ 5539566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(numVertices, &junctions, numEdges, &pipes)); 55442dc13f1SHong Zhang /* vertex */ 55542dc13f1SHong Zhang for (i = 0; i < numVertices; i++) { 55642dc13f1SHong Zhang junctions[i].id = i; 55742dc13f1SHong Zhang junctions[i].type = JUNCTION; 55842dc13f1SHong Zhang } 55942dc13f1SHong Zhang 56042dc13f1SHong Zhang junctions[0].type = RESERVOIR; 56142dc13f1SHong Zhang junctions[1].type = VALVE; 56242dc13f1SHong Zhang junctions[2].type = RESERVOIR; 56342dc13f1SHong Zhang } 56442dc13f1SHong Zhang break; 5659371c9d4SSatish Balay default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "not done yet"); 56642dc13f1SHong Zhang } 56742dc13f1SHong Zhang 56842dc13f1SHong Zhang /* set edge global id */ 56942dc13f1SHong Zhang for (i = 0; i < numEdges; i++) pipes[i].id = i; 57042dc13f1SHong Zhang 571dd400576SPatrick Sanan if (rank == 0) { /* set vtype for proc[0] */ 57242dc13f1SHong Zhang PetscInt v; 5739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * numEdges, &vtype)); 57442dc13f1SHong Zhang for (i = 0; i < 2 * numEdges; i++) { 57542dc13f1SHong Zhang v = edgelist[i]; 57642dc13f1SHong Zhang vtype[i] = junctions[v].type; 57742dc13f1SHong Zhang } 57842dc13f1SHong Zhang wash->vtype = vtype; 57942dc13f1SHong Zhang } 58042dc13f1SHong Zhang 58142dc13f1SHong Zhang *wash_ptr = wash; 58242dc13f1SHong Zhang wash->nedge = numEdges; 58342dc13f1SHong Zhang wash->nvertex = numVertices; 58442dc13f1SHong Zhang wash->edgelist = edgelist; 58542dc13f1SHong Zhang wash->junction = junctions; 58642dc13f1SHong Zhang wash->pipe = pipes; 58742dc13f1SHong Zhang 58842dc13f1SHong Zhang /* Distribute edgelist to other processors */ 5899566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-wash_distribute", &washdist, NULL)); 59042dc13f1SHong Zhang if (washdist) { 59142dc13f1SHong Zhang /* 5929566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD," Distribute sequential wash ...\n")); 59342dc13f1SHong Zhang */ 5949566063dSJacob Faibussowitsch PetscCall(WashNetworkDistribute(comm, wash)); 59542dc13f1SHong Zhang } 59642dc13f1SHong Zhang PetscFunctionReturn(0); 59742dc13f1SHong Zhang } 59842dc13f1SHong Zhang 59942dc13f1SHong Zhang /* ------------------------------------------------------- */ 6009371c9d4SSatish Balay int main(int argc, char **argv) { 60142dc13f1SHong Zhang Wash wash; 60242dc13f1SHong Zhang Junction junctions, junction; 60342dc13f1SHong Zhang Pipe pipe, pipes; 604f11a936eSBarry Smith PetscInt KeyPipe, KeyJunction, *edgelist = NULL, *vtype = NULL; 605f11a936eSBarry Smith PetscInt i, e, v, eStart, eEnd, vStart, vEnd, key, vkey, type; 606f11a936eSBarry Smith PetscInt steps = 1, nedges, nnodes = 6; 60742dc13f1SHong Zhang const PetscInt *cone; 60842dc13f1SHong Zhang DM networkdm; 60942dc13f1SHong Zhang PetscMPIInt size, rank; 61042dc13f1SHong Zhang PetscReal ftime; 61142dc13f1SHong Zhang Vec X; 61242dc13f1SHong Zhang TS ts; 61342dc13f1SHong Zhang TSConvergedReason reason; 61442dc13f1SHong Zhang PetscBool viewpipes, viewjuncs, monipipes = PETSC_FALSE, userJac = PETSC_TRUE, viewdm = PETSC_FALSE, viewX = PETSC_FALSE; 61542dc13f1SHong Zhang PetscInt pipesCase = 0; 61642dc13f1SHong Zhang DMNetworkMonitor monitor; 61742dc13f1SHong Zhang MPI_Comm comm; 61842dc13f1SHong Zhang 619327415f7SBarry Smith PetscFunctionBeginUser; 6209566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, "pOption", help)); 62142dc13f1SHong Zhang 62242dc13f1SHong Zhang /* Read runtime options */ 6239566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-case", &pipesCase, NULL)); 6249566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-user_Jac", &userJac, NULL)); 6259566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-pipe_monitor", &monipipes, NULL)); 6269566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewdm", &viewdm, NULL)); 6279566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewX", &viewX, NULL)); 6289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-npipenodes", &nnodes, NULL)); 62942dc13f1SHong Zhang 63042dc13f1SHong Zhang /* Create networkdm */ 63142dc13f1SHong Zhang /*------------------*/ 6329566063dSJacob Faibussowitsch PetscCall(DMNetworkCreate(PETSC_COMM_WORLD, &networkdm)); 6339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)networkdm, &comm)); 6349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 6359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 63642dc13f1SHong Zhang 637*48a46eb9SPierre Jolivet if (size == 1 && monipipes) PetscCall(DMNetworkMonitorCreate(networkdm, &monitor)); 63842dc13f1SHong Zhang 63942dc13f1SHong Zhang /* Register the components in the network */ 6409566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "junctionstruct", sizeof(struct _p_Junction), &KeyJunction)); 6419566063dSJacob Faibussowitsch PetscCall(DMNetworkRegisterComponent(networkdm, "pipestruct", sizeof(struct _p_Pipe), &KeyPipe)); 64242dc13f1SHong Zhang 64342dc13f1SHong Zhang /* Create a distributed wash network (user-specific) */ 6449566063dSJacob Faibussowitsch PetscCall(WashNetworkCreate(comm, pipesCase, &wash)); 64542dc13f1SHong Zhang nedges = wash->nedge; 64642dc13f1SHong Zhang edgelist = wash->edgelist; 64742dc13f1SHong Zhang vtype = wash->vtype; 64842dc13f1SHong Zhang junctions = wash->junction; 64942dc13f1SHong Zhang pipes = wash->pipe; 65042dc13f1SHong Zhang 65142dc13f1SHong Zhang /* Set up the network layout */ 6529566063dSJacob Faibussowitsch PetscCall(DMNetworkSetNumSubNetworks(networkdm, PETSC_DECIDE, 1)); 6539566063dSJacob Faibussowitsch PetscCall(DMNetworkAddSubnetwork(networkdm, NULL, nedges, edgelist, NULL)); 65442dc13f1SHong Zhang 6559566063dSJacob Faibussowitsch PetscCall(DMNetworkLayoutSetUp(networkdm)); 65642dc13f1SHong Zhang 6579566063dSJacob Faibussowitsch PetscCall(DMNetworkGetEdgeRange(networkdm, &eStart, &eEnd)); 6589566063dSJacob Faibussowitsch PetscCall(DMNetworkGetVertexRange(networkdm, &vStart, &vEnd)); 6599566063dSJacob Faibussowitsch /* PetscCall(PetscPrintf(PETSC_COMM_SELF,"[%d] eStart/End: %d - %d; vStart/End: %d - %d\n",rank,eStart,eEnd,vStart,vEnd)); */ 66042dc13f1SHong Zhang 66142dc13f1SHong Zhang if (rank) { /* junctions[] and pipes[] for proc[0] are allocated in WashNetworkCreate() */ 66242dc13f1SHong Zhang /* vEnd - vStart = nvertices + number of ghost vertices! */ 6639566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(vEnd - vStart, &junctions, nedges, &pipes)); 66442dc13f1SHong Zhang } 66542dc13f1SHong Zhang 66642dc13f1SHong Zhang /* Add Pipe component and number of variables to all local edges */ 66742dc13f1SHong Zhang for (e = eStart; e < eEnd; e++) { 66842dc13f1SHong Zhang pipes[e - eStart].nnodes = nnodes; 6699566063dSJacob Faibussowitsch PetscCall(DMNetworkAddComponent(networkdm, e, KeyPipe, &pipes[e - eStart], 2 * pipes[e - eStart].nnodes)); 67042dc13f1SHong Zhang 67142dc13f1SHong Zhang if (size == 1 && monipipes) { /* Add monitor -- show Q_{pipes[e-eStart].id}? */ 67242dc13f1SHong Zhang pipes[e - eStart].length = 600.0; 6739566063dSJacob Faibussowitsch PetscCall(DMNetworkMonitorAdd(monitor, "Pipe Q", e, pipes[e - eStart].nnodes, 0, 2, 0.0, pipes[e - eStart].length, -0.8, 0.8, PETSC_TRUE)); 6749566063dSJacob Faibussowitsch PetscCall(DMNetworkMonitorAdd(monitor, "Pipe H", e, pipes[e - eStart].nnodes, 1, 2, 0.0, pipes[e - eStart].length, -400.0, 800.0, PETSC_TRUE)); 67542dc13f1SHong Zhang } 67642dc13f1SHong Zhang } 67742dc13f1SHong Zhang 678eac198afSGetnet /* Add Junction component and number of variables to all local vertices */ 679*48a46eb9SPierre Jolivet for (v = vStart; v < vEnd; v++) PetscCall(DMNetworkAddComponent(networkdm, v, KeyJunction, &junctions[v - vStart], 2)); 68042dc13f1SHong Zhang 68142dc13f1SHong Zhang if (size > 1) { /* must be called before DMSetUp()???. Other partitioners do not work yet??? -- cause crash in proc[0]! */ 68242dc13f1SHong Zhang DM plexdm; 68342dc13f1SHong Zhang PetscPartitioner part; 6849566063dSJacob Faibussowitsch PetscCall(DMNetworkGetPlex(networkdm, &plexdm)); 6859566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(plexdm, &part)); 6869566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetType(part, PETSCPARTITIONERSIMPLE)); 6879566063dSJacob Faibussowitsch PetscCall(PetscOptionsSetValue(NULL, "-dm_plex_csr_alg", "mat")); /* for parmetis */ 68842dc13f1SHong Zhang } 68942dc13f1SHong Zhang 69042dc13f1SHong Zhang /* Set up DM for use */ 6919566063dSJacob Faibussowitsch PetscCall(DMSetUp(networkdm)); 69242dc13f1SHong Zhang if (viewdm) { 6939566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nOriginal networkdm, DMView:\n")); 6949566063dSJacob Faibussowitsch PetscCall(DMView(networkdm, PETSC_VIEWER_STDOUT_WORLD)); 69542dc13f1SHong Zhang } 69642dc13f1SHong Zhang 69742dc13f1SHong Zhang /* Set user physical parameters to the components */ 69842dc13f1SHong Zhang for (e = eStart; e < eEnd; e++) { 6999566063dSJacob Faibussowitsch PetscCall(DMNetworkGetConnectedVertices(networkdm, e, &cone)); 70042dc13f1SHong Zhang /* vfrom */ 7019566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, cone[0], 0, &vkey, (void **)&junction, NULL)); 70242dc13f1SHong Zhang junction->type = (VertexType)vtype[2 * e]; 70342dc13f1SHong Zhang 70442dc13f1SHong Zhang /* vto */ 7059566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, cone[1], 0, &vkey, (void **)&junction, NULL)); 70642dc13f1SHong Zhang junction->type = (VertexType)vtype[2 * e + 1]; 70742dc13f1SHong Zhang } 70842dc13f1SHong Zhang 7099566063dSJacob Faibussowitsch PetscCall(WashNetworkCleanUp(wash)); 71042dc13f1SHong Zhang 71142dc13f1SHong Zhang /* Network partitioning and distribution of data */ 7129566063dSJacob Faibussowitsch PetscCall(DMNetworkDistribute(&networkdm, 0)); 71342dc13f1SHong Zhang if (viewdm) { 7149566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nAfter DMNetworkDistribute, DMView:\n")); 7159566063dSJacob Faibussowitsch PetscCall(DMView(networkdm, PETSC_VIEWER_STDOUT_WORLD)); 71642dc13f1SHong Zhang } 71742dc13f1SHong Zhang 71842dc13f1SHong Zhang /* create vectors */ 7199566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(networkdm, &X)); 7209566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(networkdm, &wash->localX)); 7219566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(networkdm, &wash->localXdot)); 72242dc13f1SHong Zhang 72342dc13f1SHong Zhang /* PipeSetUp -- each process only sets its own pipes */ 72442dc13f1SHong Zhang /*---------------------------------------------------*/ 7259566063dSJacob Faibussowitsch PetscCall(DMNetworkGetVertexRange(networkdm, &vStart, &vEnd)); 72642dc13f1SHong Zhang 72742dc13f1SHong Zhang userJac = PETSC_TRUE; 7289566063dSJacob Faibussowitsch PetscCall(DMNetworkHasJacobian(networkdm, userJac, userJac)); 7299566063dSJacob Faibussowitsch PetscCall(DMNetworkGetEdgeRange(networkdm, &eStart, &eEnd)); 73042dc13f1SHong Zhang for (e = eStart; e < eEnd; e++) { /* each edge has only one component, pipe */ 7319566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, e, 0, &type, (void **)&pipe, NULL)); 73242dc13f1SHong Zhang 73342dc13f1SHong Zhang wash->nnodes_loc += pipe->nnodes; /* local total number of nodes, will be used by PipesView() */ 7349371c9d4SSatish Balay PetscCall(PipeSetParameters(pipe, 600.0, /* length */ 73542dc13f1SHong Zhang 0.5, /* diameter */ 73642dc13f1SHong Zhang 1200.0, /* a */ 737b122ec5aSJacob Faibussowitsch 0.018)); /* friction */ 7389566063dSJacob Faibussowitsch PetscCall(PipeSetUp(pipe)); 73942dc13f1SHong Zhang 74042dc13f1SHong Zhang if (userJac) { 74142dc13f1SHong Zhang /* Create Jacobian matrix structures for a Pipe */ 74242dc13f1SHong Zhang Mat *J; 7439566063dSJacob Faibussowitsch PetscCall(PipeCreateJacobian(pipe, NULL, &J)); 7449566063dSJacob Faibussowitsch PetscCall(DMNetworkEdgeSetMatrix(networkdm, e, J)); 74542dc13f1SHong Zhang } 74642dc13f1SHong Zhang } 74742dc13f1SHong Zhang 74842dc13f1SHong Zhang if (userJac) { 7499566063dSJacob Faibussowitsch PetscCall(DMNetworkGetVertexRange(networkdm, &vStart, &vEnd)); 75042dc13f1SHong Zhang for (v = vStart; v < vEnd; v++) { 75142dc13f1SHong Zhang Mat *J; 7529566063dSJacob Faibussowitsch PetscCall(JunctionCreateJacobian(networkdm, v, NULL, &J)); 7539566063dSJacob Faibussowitsch PetscCall(DMNetworkVertexSetMatrix(networkdm, v, J)); 75442dc13f1SHong Zhang 7559566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, v, 0, &vkey, (void **)&junction, NULL)); 75642dc13f1SHong Zhang junction->jacobian = J; 75742dc13f1SHong Zhang } 75842dc13f1SHong Zhang } 75942dc13f1SHong Zhang 76042dc13f1SHong Zhang /* Setup solver */ 76142dc13f1SHong Zhang /*--------------------------------------------------------*/ 7629566063dSJacob Faibussowitsch PetscCall(TSCreate(PETSC_COMM_WORLD, &ts)); 76342dc13f1SHong Zhang 7649566063dSJacob Faibussowitsch PetscCall(TSSetDM(ts, (DM)networkdm)); 7659566063dSJacob Faibussowitsch PetscCall(TSSetIFunction(ts, NULL, WASHIFunction, wash)); 76642dc13f1SHong Zhang 7679566063dSJacob Faibussowitsch PetscCall(TSSetMaxSteps(ts, steps)); 7689566063dSJacob Faibussowitsch PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER)); 7699566063dSJacob Faibussowitsch PetscCall(TSSetTimeStep(ts, 0.1)); 7709566063dSJacob Faibussowitsch PetscCall(TSSetType(ts, TSBEULER)); 7719566063dSJacob Faibussowitsch if (size == 1 && monipipes) PetscCall(TSMonitorSet(ts, TSDMNetworkMonitor, monitor, NULL)); 7729566063dSJacob Faibussowitsch PetscCall(TSSetFromOptions(ts)); 77342dc13f1SHong Zhang 7749566063dSJacob Faibussowitsch PetscCall(WASHSetInitialSolution(networkdm, X, wash)); 77542dc13f1SHong Zhang 7769566063dSJacob Faibussowitsch PetscCall(TSSolve(ts, X)); 77742dc13f1SHong Zhang 7789566063dSJacob Faibussowitsch PetscCall(TSGetSolveTime(ts, &ftime)); 7799566063dSJacob Faibussowitsch PetscCall(TSGetStepNumber(ts, &steps)); 7809566063dSJacob Faibussowitsch PetscCall(TSGetConvergedReason(ts, &reason)); 78163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%s at time %g after %" PetscInt_FMT " steps\n", TSConvergedReasons[reason], (double)ftime, steps)); 7821baa6e33SBarry Smith if (viewX) PetscCall(VecView(X, PETSC_VIEWER_STDOUT_WORLD)); 78342dc13f1SHong Zhang 78442dc13f1SHong Zhang viewpipes = PETSC_FALSE; 7859566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-Jac_view", &viewpipes, NULL)); 78642dc13f1SHong Zhang if (viewpipes) { 78742dc13f1SHong Zhang SNES snes; 78842dc13f1SHong Zhang Mat Jac; 7899566063dSJacob Faibussowitsch PetscCall(TSGetSNES(ts, &snes)); 7909566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &Jac, NULL, NULL, NULL)); 7919566063dSJacob Faibussowitsch PetscCall(MatView(Jac, PETSC_VIEWER_DRAW_WORLD)); 79242dc13f1SHong Zhang } 79342dc13f1SHong Zhang 79442dc13f1SHong Zhang /* View solutions */ 79542dc13f1SHong Zhang /* -------------- */ 79642dc13f1SHong Zhang viewpipes = PETSC_FALSE; 7979566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-pipe_view", &viewpipes, NULL)); 7981baa6e33SBarry Smith if (viewpipes) PetscCall(PipesView(networkdm, KeyPipe, X)); 79942dc13f1SHong Zhang 80042dc13f1SHong Zhang /* Test IS */ 80142dc13f1SHong Zhang viewjuncs = PETSC_FALSE; 8029566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-isjunc_view", &viewjuncs, NULL)); 8031baa6e33SBarry Smith if (viewjuncs) PetscCall(ISJunctionsView(networkdm, KeyJunction)); 80442dc13f1SHong Zhang 80542dc13f1SHong Zhang /* Free spaces */ 80642dc13f1SHong Zhang /* ----------- */ 8079566063dSJacob Faibussowitsch PetscCall(TSDestroy(&ts)); 8089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X)); 8099566063dSJacob Faibussowitsch PetscCall(VecDestroy(&wash->localX)); 8109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&wash->localXdot)); 81142dc13f1SHong Zhang 81242dc13f1SHong Zhang /* Destroy objects from each pipe that are created in PipeSetUp() */ 8139566063dSJacob Faibussowitsch PetscCall(DMNetworkGetEdgeRange(networkdm, &eStart, &eEnd)); 81442dc13f1SHong Zhang for (i = eStart; i < eEnd; i++) { 8159566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, i, 0, &key, (void **)&pipe, NULL)); 8169566063dSJacob Faibussowitsch PetscCall(PipeDestroy(&pipe)); 81742dc13f1SHong Zhang } 81842dc13f1SHong Zhang if (userJac) { 81942dc13f1SHong Zhang for (v = vStart; v < vEnd; v++) { 8209566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, v, 0, &vkey, (void **)&junction, NULL)); 8219566063dSJacob Faibussowitsch PetscCall(JunctionDestroyJacobian(networkdm, v, junction)); 82242dc13f1SHong Zhang } 82342dc13f1SHong Zhang } 82442dc13f1SHong Zhang 825*48a46eb9SPierre Jolivet if (size == 1 && monipipes) PetscCall(DMNetworkMonitorDestroy(&monitor)); 8269566063dSJacob Faibussowitsch PetscCall(DMDestroy(&networkdm)); 8279566063dSJacob Faibussowitsch PetscCall(PetscFree(wash)); 82842dc13f1SHong Zhang 8291baa6e33SBarry Smith if (rank) PetscCall(PetscFree2(junctions, pipes)); 8309566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 831b122ec5aSJacob Faibussowitsch return 0; 83242dc13f1SHong Zhang } 83342dc13f1SHong Zhang 83442dc13f1SHong Zhang /*TEST 83542dc13f1SHong Zhang 83642dc13f1SHong Zhang build: 83742dc13f1SHong Zhang depends: pipeInterface.c pipeImpls.c 83842dc13f1SHong Zhang requires: mumps 83942dc13f1SHong Zhang 84042dc13f1SHong Zhang test: 84142dc13f1SHong Zhang args: -ts_monitor -case 1 -ts_max_steps 1 -pc_factor_mat_solver_type mumps -options_left no -viewX 84242dc13f1SHong Zhang localrunfiles: pOption 84342dc13f1SHong Zhang output_file: output/pipes_1.out 84442dc13f1SHong Zhang 84542dc13f1SHong Zhang test: 84642dc13f1SHong Zhang suffix: 2 84742dc13f1SHong Zhang nsize: 2 84842dc13f1SHong Zhang args: -ts_monitor -case 1 -ts_max_steps 1 -pc_factor_mat_solver_type mumps -petscpartitioner_type simple -options_left no -viewX 84942dc13f1SHong Zhang localrunfiles: pOption 85042dc13f1SHong Zhang output_file: output/pipes_2.out 85142dc13f1SHong Zhang 85242dc13f1SHong Zhang test: 85342dc13f1SHong Zhang suffix: 3 85442dc13f1SHong Zhang nsize: 2 85542dc13f1SHong Zhang args: -ts_monitor -case 0 -ts_max_steps 1 -pc_factor_mat_solver_type mumps -petscpartitioner_type simple -options_left no -viewX 85642dc13f1SHong Zhang localrunfiles: pOption 85742dc13f1SHong Zhang output_file: output/pipes_3.out 85842dc13f1SHong Zhang 85942dc13f1SHong Zhang test: 86042dc13f1SHong Zhang suffix: 4 86142dc13f1SHong Zhang args: -ts_monitor -case 2 -ts_max_steps 1 -pc_factor_mat_solver_type mumps -options_left no -viewX 86242dc13f1SHong Zhang localrunfiles: pOption 86342dc13f1SHong Zhang output_file: output/pipes_4.out 86442dc13f1SHong Zhang 86542dc13f1SHong Zhang test: 86642dc13f1SHong Zhang suffix: 5 86742dc13f1SHong Zhang nsize: 3 86842dc13f1SHong Zhang args: -ts_monitor -case 2 -ts_max_steps 10 -pc_factor_mat_solver_type mumps -petscpartitioner_type simple -options_left no -viewX 86942dc13f1SHong Zhang localrunfiles: pOption 87042dc13f1SHong Zhang output_file: output/pipes_5.out 87142dc13f1SHong Zhang 87242dc13f1SHong Zhang test: 87342dc13f1SHong Zhang suffix: 6 87442dc13f1SHong Zhang nsize: 2 87542dc13f1SHong Zhang args: -ts_monitor -case 1 -ts_max_steps 1 -pc_factor_mat_solver_type mumps -petscpartitioner_type simple -options_left no -wash_distribute 0 -viewX 87642dc13f1SHong Zhang localrunfiles: pOption 87742dc13f1SHong Zhang output_file: output/pipes_6.out 87842dc13f1SHong Zhang 87942dc13f1SHong Zhang test: 88042dc13f1SHong Zhang suffix: 7 88142dc13f1SHong Zhang nsize: 2 88242dc13f1SHong Zhang args: -ts_monitor -case 2 -ts_max_steps 1 -pc_factor_mat_solver_type mumps -petscpartitioner_type simple -options_left no -wash_distribute 0 -viewX 88342dc13f1SHong Zhang localrunfiles: pOption 88442dc13f1SHong Zhang output_file: output/pipes_7.out 88542dc13f1SHong Zhang 88642dc13f1SHong Zhang test: 88742dc13f1SHong Zhang suffix: 8 88842dc13f1SHong Zhang nsize: 2 88942dc13f1SHong Zhang requires: parmetis 89042dc13f1SHong Zhang args: -ts_monitor -case 2 -ts_max_steps 1 -pc_factor_mat_solver_type mumps -petscpartitioner_type parmetis -options_left no -wash_distribute 1 89142dc13f1SHong Zhang localrunfiles: pOption 89242dc13f1SHong Zhang output_file: output/pipes_8.out 89342dc13f1SHong Zhang 89442dc13f1SHong Zhang test: 89542dc13f1SHong Zhang suffix: 9 89642dc13f1SHong Zhang nsize: 2 89742dc13f1SHong Zhang args: -case 0 -ts_max_steps 1 -pc_factor_mat_solver_type mumps -petscpartitioner_type simple -options_left no -wash_distribute 0 -pipe_view 89842dc13f1SHong Zhang localrunfiles: pOption 89942dc13f1SHong Zhang output_file: output/pipes_9.out 90042dc13f1SHong Zhang 90142dc13f1SHong Zhang test: 90242dc13f1SHong Zhang suffix: 10 90342dc13f1SHong Zhang nsize: 2 90442dc13f1SHong Zhang args: -case 0 -ts_max_steps 1 -pc_factor_mat_solver_type mumps -petscpartitioner_type simple -options_left no -wash_distribute 0 -isjunc_view 90542dc13f1SHong Zhang localrunfiles: pOption 90642dc13f1SHong Zhang output_file: output/pipes_10.out 90742dc13f1SHong Zhang 90842dc13f1SHong Zhang TEST*/ 909