1c4762a1bSJed Brown /* function subroutines used by water.c */ 2c4762a1bSJed Brown 3c4762a1bSJed Brown #include "water.h" 4c4762a1bSJed Brown #include <petscdmnetwork.h> 5c4762a1bSJed Brown 69371c9d4SSatish Balay PetscScalar Flow_Pipe(Pipe *pipe, PetscScalar hf, PetscScalar ht) { 7c4762a1bSJed Brown PetscScalar flow_pipe; 8c4762a1bSJed Brown 9c4762a1bSJed Brown flow_pipe = PetscSign(hf - ht) * PetscPowScalar(PetscAbsScalar(hf - ht) / pipe->k, (1 / pipe->n)); 10c4762a1bSJed Brown return flow_pipe; 11c4762a1bSJed Brown } 12c4762a1bSJed Brown 139371c9d4SSatish Balay PetscScalar Flow_Pump(Pump *pump, PetscScalar hf, PetscScalar ht) { 14c4762a1bSJed Brown PetscScalar flow_pump; 15c4762a1bSJed Brown flow_pump = PetscPowScalar((hf - ht + pump->h0) / pump->r, (1 / pump->n)); 16c4762a1bSJed Brown return flow_pump; 17c4762a1bSJed Brown } 18c4762a1bSJed Brown 199371c9d4SSatish Balay PetscErrorCode FormFunction_Water(DM networkdm, Vec localX, Vec localF, PetscInt nv, PetscInt ne, const PetscInt *vtx, const PetscInt *edges, void *appctx) { 20c4762a1bSJed Brown const PetscScalar *xarr; 21c4762a1bSJed Brown const PetscInt *cone; 22c4762a1bSJed Brown PetscScalar *farr, hf, ht, flow; 232bf73ac6SHong Zhang PetscInt i, key, vnode1, vnode2, offsetnode1, offsetnode2, offset, ncomp; 24c4762a1bSJed Brown PetscBool ghostvtex; 25c4762a1bSJed Brown VERTEX_Water vertex, vertexnode1, vertexnode2; 26c4762a1bSJed Brown EDGE_Water edge; 27c4762a1bSJed Brown Pipe *pipe; 28c4762a1bSJed Brown Pump *pump; 29c4762a1bSJed Brown Reservoir *reservoir; 30c4762a1bSJed Brown Tank *tank; 31c4762a1bSJed Brown 32c4762a1bSJed Brown PetscFunctionBegin; 33c4762a1bSJed Brown /* Get arrays for the vectors */ 349566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localX, &xarr)); 359566063dSJacob Faibussowitsch PetscCall(VecGetArray(localF, &farr)); 36c4762a1bSJed Brown 37c4762a1bSJed Brown for (i = 0; i < ne; i++) { /* for each edge */ 38c4762a1bSJed Brown /* Get the offset and the key for the component for edge number e[i] */ 399566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, edges[i], 0, &key, (void **)&edge, NULL)); 40c4762a1bSJed Brown 41c4762a1bSJed Brown /* Get the numbers for the vertices covering this edge */ 429566063dSJacob Faibussowitsch PetscCall(DMNetworkGetConnectedVertices(networkdm, edges[i], &cone)); 43c4762a1bSJed Brown vnode1 = cone[0]; 44c4762a1bSJed Brown vnode2 = cone[1]; 45c4762a1bSJed Brown 462bf73ac6SHong Zhang /* Get the components at the two vertices, their variable offsets */ 479566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, vnode1, &ncomp)); 489566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vnode1, ncomp - 1, &key, (void **)&vertexnode1, NULL)); 499566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vnode1, ncomp - 1, &offsetnode1)); 50c4762a1bSJed Brown 519566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, vnode2, &ncomp)); 529566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vnode2, ncomp - 1, &key, (void **)&vertexnode2, NULL)); 539566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vnode2, ncomp - 1, &offsetnode2)); 54c4762a1bSJed Brown 55c4762a1bSJed Brown /* Variables at node1 and node 2 */ 56c4762a1bSJed Brown hf = xarr[offsetnode1]; 57c4762a1bSJed Brown ht = xarr[offsetnode2]; 58c4762a1bSJed Brown 59c4762a1bSJed Brown flow = 0.0; 60c4762a1bSJed Brown if (edge->type == EDGE_TYPE_PIPE) { 61c4762a1bSJed Brown pipe = &edge->pipe; 62c4762a1bSJed Brown flow = Flow_Pipe(pipe, hf, ht); 63c4762a1bSJed Brown } else if (edge->type == EDGE_TYPE_PUMP) { 64c4762a1bSJed Brown pump = &edge->pump; 65c4762a1bSJed Brown flow = Flow_Pump(pump, hf, ht); 66c4762a1bSJed Brown } 67c4762a1bSJed Brown /* Convention: Node 1 has outgoing flow and Node 2 has incoming flow */ 68c4762a1bSJed Brown if (vertexnode1->type == VERTEX_TYPE_JUNCTION) farr[offsetnode1] -= flow; 69c4762a1bSJed Brown if (vertexnode2->type == VERTEX_TYPE_JUNCTION) farr[offsetnode2] += flow; 70c4762a1bSJed Brown } 71c4762a1bSJed Brown 72c4762a1bSJed Brown /* Subtract Demand flows at the vertices */ 73c4762a1bSJed Brown for (i = 0; i < nv; i++) { 749566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghostvtex)); 75c4762a1bSJed Brown if (ghostvtex) continue; 76c4762a1bSJed Brown 779566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vtx[i], ALL_COMPONENTS, &offset)); 789566063dSJacob Faibussowitsch PetscCall(DMNetworkGetNumComponents(networkdm, vtx[i], &ncomp)); 799566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[i], ncomp - 1, &key, (void **)&vertex, NULL)); 80c4762a1bSJed Brown 81c4762a1bSJed Brown if (vertex->type == VERTEX_TYPE_JUNCTION) { 82c4762a1bSJed Brown farr[offset] -= vertex->junc.demand; 83c4762a1bSJed Brown } else if (vertex->type == VERTEX_TYPE_RESERVOIR) { 84c4762a1bSJed Brown reservoir = &vertex->res; 85c4762a1bSJed Brown farr[offset] = xarr[offset] - reservoir->head; 86c4762a1bSJed Brown } else if (vertex->type == VERTEX_TYPE_TANK) { 87c4762a1bSJed Brown tank = &vertex->tank; 88c4762a1bSJed Brown farr[offset] = xarr[offset] - (tank->elev + tank->initlvl); 89c4762a1bSJed Brown } 90c4762a1bSJed Brown } 91c4762a1bSJed Brown 929566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localX, &xarr)); 939566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localF, &farr)); 94c4762a1bSJed Brown PetscFunctionReturn(0); 95c4762a1bSJed Brown } 96c4762a1bSJed Brown 979371c9d4SSatish Balay PetscErrorCode WaterFormFunction(SNES snes, Vec X, Vec F, void *user) { 98c4762a1bSJed Brown DM networkdm; 99c4762a1bSJed Brown Vec localX, localF; 100c4762a1bSJed Brown const PetscInt *v, *e; 101c4762a1bSJed Brown PetscInt nv, ne; 102c4762a1bSJed Brown 103c4762a1bSJed Brown PetscFunctionBegin; 104c4762a1bSJed Brown /* Get the DM attached with the SNES */ 1059566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &networkdm)); 106c4762a1bSJed Brown 107c4762a1bSJed Brown /* Get local vertices and edges */ 1089566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &v, &e)); 109c4762a1bSJed Brown 110c4762a1bSJed Brown /* Get local vectors */ 1119566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localX)); 1129566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localF)); 113c4762a1bSJed Brown 114c4762a1bSJed Brown /* Scatter values from global to local vector */ 1159566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX)); 1169566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX)); 117c4762a1bSJed Brown 118c4762a1bSJed Brown /* Initialize residual */ 1199566063dSJacob Faibussowitsch PetscCall(VecSet(F, 0.0)); 1209566063dSJacob Faibussowitsch PetscCall(VecSet(localF, 0.0)); 121c4762a1bSJed Brown 1229566063dSJacob Faibussowitsch PetscCall(FormFunction_Water(networkdm, localX, localF, nv, ne, v, e, NULL)); 123c4762a1bSJed Brown 1249566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localX)); 1259566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localF, ADD_VALUES, F)); 1269566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localF, ADD_VALUES, F)); 127c4762a1bSJed Brown 1289566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localF)); 129c4762a1bSJed Brown PetscFunctionReturn(0); 130c4762a1bSJed Brown } 131c4762a1bSJed Brown 1329371c9d4SSatish Balay PetscErrorCode WaterSetInitialGuess(DM networkdm, Vec X) { 133c4762a1bSJed Brown PetscInt nv, ne; 134c4762a1bSJed Brown const PetscInt *vtx, *edges; 135c4762a1bSJed Brown Vec localX; 136c4762a1bSJed Brown 137c4762a1bSJed Brown PetscFunctionBegin; 1389566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(networkdm, &localX)); 139c4762a1bSJed Brown 1409566063dSJacob Faibussowitsch PetscCall(VecSet(X, 0.0)); 1419566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(networkdm, X, INSERT_VALUES, localX)); 1429566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(networkdm, X, INSERT_VALUES, localX)); 143c4762a1bSJed Brown 1442bf73ac6SHong Zhang /* Get subnetwork */ 1459566063dSJacob Faibussowitsch PetscCall(DMNetworkGetSubnetwork(networkdm, 0, &nv, &ne, &vtx, &edges)); 1469566063dSJacob Faibussowitsch PetscCall(SetInitialGuess_Water(networkdm, localX, nv, ne, vtx, edges, NULL)); 147c4762a1bSJed Brown 1489566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(networkdm, localX, ADD_VALUES, X)); 1499566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(networkdm, localX, ADD_VALUES, X)); 1509566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(networkdm, &localX)); 151c4762a1bSJed Brown PetscFunctionReturn(0); 152c4762a1bSJed Brown } 153c4762a1bSJed Brown 1549371c9d4SSatish Balay PetscErrorCode GetListofEdges_Water(WATERDATA *water, PetscInt *edgelist) { 155c4762a1bSJed Brown PetscInt i, j, node1, node2; 156c4762a1bSJed Brown Pipe *pipe; 157c4762a1bSJed Brown Pump *pump; 158c4762a1bSJed Brown PetscBool netview = PETSC_FALSE; 159c4762a1bSJed Brown 160c4762a1bSJed Brown PetscFunctionBegin; 1619566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-water_view", &netview)); 162c4762a1bSJed Brown for (i = 0; i < water->nedge; i++) { 163c4762a1bSJed Brown if (water->edge[i].type == EDGE_TYPE_PIPE) { 164c4762a1bSJed Brown pipe = &water->edge[i].pipe; 165c4762a1bSJed Brown node1 = pipe->node1; 166c4762a1bSJed Brown node2 = pipe->node2; 167*48a46eb9SPierre Jolivet if (netview) PetscCall(PetscPrintf(PETSC_COMM_SELF, "edge %" PetscInt_FMT ", pipe v[%" PetscInt_FMT "] -> v[%" PetscInt_FMT "]\n", i, node1, node2)); 168c4762a1bSJed Brown } else { 169c4762a1bSJed Brown pump = &water->edge[i].pump; 170c4762a1bSJed Brown node1 = pump->node1; 171c4762a1bSJed Brown node2 = pump->node2; 172*48a46eb9SPierre Jolivet if (netview) PetscCall(PetscPrintf(PETSC_COMM_SELF, "edge %" PetscInt_FMT ", pump v[%" PetscInt_FMT "] -> v[%" PetscInt_FMT "]\n", i, node1, node2)); 173c4762a1bSJed Brown } 174c4762a1bSJed Brown 175c4762a1bSJed Brown for (j = 0; j < water->nvertex; j++) { 176c4762a1bSJed Brown if (water->vertex[j].id == node1) { 177c4762a1bSJed Brown edgelist[2 * i] = j; 178c4762a1bSJed Brown break; 179c4762a1bSJed Brown } 180c4762a1bSJed Brown } 181c4762a1bSJed Brown 182c4762a1bSJed Brown for (j = 0; j < water->nvertex; j++) { 183c4762a1bSJed Brown if (water->vertex[j].id == node2) { 184c4762a1bSJed Brown edgelist[2 * i + 1] = j; 185c4762a1bSJed Brown break; 186c4762a1bSJed Brown } 187c4762a1bSJed Brown } 188c4762a1bSJed Brown } 189c4762a1bSJed Brown PetscFunctionReturn(0); 190c4762a1bSJed Brown } 191c4762a1bSJed Brown 1929371c9d4SSatish Balay PetscErrorCode SetInitialGuess_Water(DM networkdm, Vec localX, PetscInt nv, PetscInt ne, const PetscInt *vtx, const PetscInt *edges, void *appctx) { 193c4762a1bSJed Brown PetscInt i, offset, key; 1942bf73ac6SHong Zhang PetscBool ghostvtex, sharedv; 195c4762a1bSJed Brown VERTEX_Water vertex; 196c4762a1bSJed Brown PetscScalar *xarr; 197c4762a1bSJed Brown 198c4762a1bSJed Brown PetscFunctionBegin; 1999566063dSJacob Faibussowitsch PetscCall(VecGetArray(localX, &xarr)); 200c4762a1bSJed Brown for (i = 0; i < nv; i++) { 2019566063dSJacob Faibussowitsch PetscCall(DMNetworkIsGhostVertex(networkdm, vtx[i], &ghostvtex)); 2029566063dSJacob Faibussowitsch PetscCall(DMNetworkIsSharedVertex(networkdm, vtx[i], &sharedv)); 2032bf73ac6SHong Zhang if (ghostvtex || sharedv) continue; 204c4762a1bSJed Brown 2059566063dSJacob Faibussowitsch PetscCall(DMNetworkGetComponent(networkdm, vtx[i], 0, &key, (void **)&vertex, NULL)); 2069566063dSJacob Faibussowitsch PetscCall(DMNetworkGetLocalVecOffset(networkdm, vtx[i], 0, &offset)); 207c4762a1bSJed Brown if (vertex->type == VERTEX_TYPE_JUNCTION) { 208c4762a1bSJed Brown xarr[offset] = 100; 209c4762a1bSJed Brown } else if (vertex->type == VERTEX_TYPE_RESERVOIR) { 210c4762a1bSJed Brown xarr[offset] = vertex->res.head; 211c4762a1bSJed Brown } else { 212c4762a1bSJed Brown xarr[offset] = vertex->tank.initlvl + vertex->tank.elev; 213c4762a1bSJed Brown } 214c4762a1bSJed Brown } 2159566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(localX, &xarr)); 216c4762a1bSJed Brown PetscFunctionReturn(0); 217c4762a1bSJed Brown } 218