xref: /petsc/src/snes/tutorials/network/water/waterfunctions.c (revision 9566063d113dddea24716c546802770db7481bc0)
1c4762a1bSJed Brown /* function subroutines used by water.c */
2c4762a1bSJed Brown 
3c4762a1bSJed Brown #include "water.h"
4c4762a1bSJed Brown #include <petscdmnetwork.h>
5c4762a1bSJed Brown 
6c4762a1bSJed Brown PetscScalar Flow_Pipe(Pipe *pipe,PetscScalar hf,PetscScalar ht)
7c4762a1bSJed Brown {
8c4762a1bSJed Brown   PetscScalar flow_pipe;
9c4762a1bSJed Brown 
10c4762a1bSJed Brown   flow_pipe = PetscSign(hf-ht)*PetscPowScalar(PetscAbsScalar(hf - ht)/pipe->k,(1/pipe->n));
11c4762a1bSJed Brown   return flow_pipe;
12c4762a1bSJed Brown }
13c4762a1bSJed Brown 
14c4762a1bSJed Brown PetscScalar Flow_Pump(Pump *pump,PetscScalar hf, PetscScalar ht)
15c4762a1bSJed Brown {
16c4762a1bSJed Brown   PetscScalar flow_pump;
17c4762a1bSJed Brown   flow_pump = PetscPowScalar((hf - ht + pump->h0)/pump->r,(1/pump->n));
18c4762a1bSJed Brown   return flow_pump;
19c4762a1bSJed Brown }
20c4762a1bSJed Brown 
21c4762a1bSJed Brown PetscErrorCode FormFunction_Water(DM networkdm,Vec localX,Vec localF,PetscInt nv,PetscInt ne,const PetscInt* vtx,const PetscInt* edges,void* appctx)
22c4762a1bSJed Brown {
23c4762a1bSJed Brown   const PetscScalar *xarr;
24c4762a1bSJed Brown   const PetscInt    *cone;
25c4762a1bSJed Brown   PetscScalar       *farr,hf,ht,flow;
262bf73ac6SHong Zhang   PetscInt          i,key,vnode1,vnode2,offsetnode1,offsetnode2,offset,ncomp;
27c4762a1bSJed Brown   PetscBool         ghostvtex;
28c4762a1bSJed Brown   VERTEX_Water      vertex,vertexnode1,vertexnode2;
29c4762a1bSJed Brown   EDGE_Water        edge;
30c4762a1bSJed Brown   Pipe              *pipe;
31c4762a1bSJed Brown   Pump              *pump;
32c4762a1bSJed Brown   Reservoir         *reservoir;
33c4762a1bSJed Brown   Tank              *tank;
34c4762a1bSJed Brown 
35c4762a1bSJed Brown   PetscFunctionBegin;
36c4762a1bSJed Brown   /* Get arrays for the vectors */
37*9566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(localX,&xarr));
38*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(localF,&farr));
39c4762a1bSJed Brown 
40c4762a1bSJed Brown   for (i=0; i<ne; i++) { /* for each edge */
41c4762a1bSJed Brown     /* Get the offset and the key for the component for edge number e[i] */
42*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetComponent(networkdm,edges[i],0,&key,(void**)&edge,NULL));
43c4762a1bSJed Brown 
44c4762a1bSJed Brown     /* Get the numbers for the vertices covering this edge */
45*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetConnectedVertices(networkdm,edges[i],&cone));
46c4762a1bSJed Brown     vnode1 = cone[0];
47c4762a1bSJed Brown     vnode2 = cone[1];
48c4762a1bSJed Brown 
492bf73ac6SHong Zhang     /* Get the components at the two vertices, their variable offsets */
50*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetNumComponents(networkdm,vnode1,&ncomp));
51*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetComponent(networkdm,vnode1,ncomp-1,&key,(void**)&vertexnode1,NULL));
52*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetLocalVecOffset(networkdm,vnode1,ncomp-1,&offsetnode1));
53c4762a1bSJed Brown 
54*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetNumComponents(networkdm,vnode2,&ncomp));
55*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetComponent(networkdm,vnode2,ncomp-1,&key,(void**)&vertexnode2,NULL));
56*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetLocalVecOffset(networkdm,vnode2,ncomp-1,&offsetnode2));
57c4762a1bSJed Brown 
58c4762a1bSJed Brown     /* Variables at node1 and node 2 */
59c4762a1bSJed Brown     hf = xarr[offsetnode1];
60c4762a1bSJed Brown     ht = xarr[offsetnode2];
61c4762a1bSJed Brown 
62c4762a1bSJed Brown     flow = 0.0;
63c4762a1bSJed Brown     if (edge->type == EDGE_TYPE_PIPE) {
64c4762a1bSJed Brown       pipe = &edge->pipe;
65c4762a1bSJed Brown       flow = Flow_Pipe(pipe,hf,ht);
66c4762a1bSJed Brown     } else if (edge->type == EDGE_TYPE_PUMP) {
67c4762a1bSJed Brown       pump = &edge->pump;
68c4762a1bSJed Brown       flow = Flow_Pump(pump,hf,ht);
69c4762a1bSJed Brown     }
70c4762a1bSJed Brown     /* Convention: Node 1 has outgoing flow and Node 2 has incoming flow */
71c4762a1bSJed Brown     if (vertexnode1->type == VERTEX_TYPE_JUNCTION) farr[offsetnode1] -= flow;
72c4762a1bSJed Brown     if (vertexnode2->type == VERTEX_TYPE_JUNCTION) farr[offsetnode2] += flow;
73c4762a1bSJed Brown   }
74c4762a1bSJed Brown 
75c4762a1bSJed Brown   /* Subtract Demand flows at the vertices */
76c4762a1bSJed Brown   for (i=0; i<nv; i++) {
77*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkIsGhostVertex(networkdm,vtx[i],&ghostvtex));
78c4762a1bSJed Brown     if (ghostvtex) continue;
79c4762a1bSJed Brown 
80*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetLocalVecOffset(networkdm,vtx[i],ALL_COMPONENTS,&offset));
81*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetNumComponents(networkdm,vtx[i],&ncomp));
82*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetComponent(networkdm,vtx[i],ncomp-1,&key,(void**)&vertex,NULL));
83c4762a1bSJed Brown 
84c4762a1bSJed Brown     if (vertex->type == VERTEX_TYPE_JUNCTION) {
85c4762a1bSJed Brown       farr[offset] -= vertex->junc.demand;
86c4762a1bSJed Brown     } else if (vertex->type == VERTEX_TYPE_RESERVOIR) {
87c4762a1bSJed Brown       reservoir = &vertex->res;
88c4762a1bSJed Brown       farr[offset] = xarr[offset] - reservoir->head;
89c4762a1bSJed Brown     } else if (vertex->type == VERTEX_TYPE_TANK) {
90c4762a1bSJed Brown       tank = &vertex->tank;
91c4762a1bSJed Brown       farr[offset] = xarr[offset] - (tank->elev + tank->initlvl);
92c4762a1bSJed Brown     }
93c4762a1bSJed Brown   }
94c4762a1bSJed Brown 
95*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(localX,&xarr));
96*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(localF,&farr));
97c4762a1bSJed Brown   PetscFunctionReturn(0);
98c4762a1bSJed Brown }
99c4762a1bSJed Brown 
100c4762a1bSJed Brown PetscErrorCode WaterFormFunction(SNES snes,Vec X, Vec F, void *user)
101c4762a1bSJed Brown {
102c4762a1bSJed Brown   DM             networkdm;
103c4762a1bSJed Brown   Vec            localX,localF;
104c4762a1bSJed Brown   const PetscInt *v,*e;
105c4762a1bSJed Brown   PetscInt       nv,ne;
106c4762a1bSJed Brown 
107c4762a1bSJed Brown   PetscFunctionBegin;
108c4762a1bSJed Brown   /* Get the DM attached with the SNES */
109*9566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes,&networkdm));
110c4762a1bSJed Brown 
111c4762a1bSJed Brown   /* Get local vertices and edges */
112*9566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetSubnetwork(networkdm,0,&nv,&ne,&v,&e));
113c4762a1bSJed Brown 
114c4762a1bSJed Brown   /* Get local vectors */
115*9566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(networkdm,&localX));
116*9566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(networkdm,&localF));
117c4762a1bSJed Brown 
118c4762a1bSJed Brown   /* Scatter values from global to local vector */
119*9566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX));
120*9566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX));
121c4762a1bSJed Brown 
122c4762a1bSJed Brown   /* Initialize residual */
123*9566063dSJacob Faibussowitsch   PetscCall(VecSet(F,0.0));
124*9566063dSJacob Faibussowitsch   PetscCall(VecSet(localF,0.0));
125c4762a1bSJed Brown 
126*9566063dSJacob Faibussowitsch   PetscCall(FormFunction_Water(networkdm,localX,localF,nv,ne,v,e,NULL));
127c4762a1bSJed Brown 
128*9566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(networkdm,&localX));
129*9566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(networkdm,localF,ADD_VALUES,F));
130*9566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(networkdm,localF,ADD_VALUES,F));
131c4762a1bSJed Brown 
132*9566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(networkdm,&localF));
133c4762a1bSJed Brown   PetscFunctionReturn(0);
134c4762a1bSJed Brown }
135c4762a1bSJed Brown 
136c4762a1bSJed Brown PetscErrorCode WaterSetInitialGuess(DM networkdm,Vec X)
137c4762a1bSJed Brown {
138c4762a1bSJed Brown   PetscInt       nv,ne;
139c4762a1bSJed Brown   const PetscInt *vtx,*edges;
140c4762a1bSJed Brown   Vec            localX;
141c4762a1bSJed Brown 
142c4762a1bSJed Brown   PetscFunctionBegin;
143*9566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(networkdm,&localX));
144c4762a1bSJed Brown 
145*9566063dSJacob Faibussowitsch   PetscCall(VecSet(X,0.0));
146*9566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX));
147*9566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX));
148c4762a1bSJed Brown 
1492bf73ac6SHong Zhang   /* Get subnetwork */
150*9566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetSubnetwork(networkdm,0,&nv,&ne,&vtx,&edges));
151*9566063dSJacob Faibussowitsch   PetscCall(SetInitialGuess_Water(networkdm,localX,nv,ne,vtx,edges,NULL));
152c4762a1bSJed Brown 
153*9566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(networkdm,localX,ADD_VALUES,X));
154*9566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(networkdm,localX,ADD_VALUES,X));
155*9566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(networkdm,&localX));
156c4762a1bSJed Brown   PetscFunctionReturn(0);
157c4762a1bSJed Brown }
158c4762a1bSJed Brown 
159c4762a1bSJed Brown PetscErrorCode GetListofEdges_Water(WATERDATA *water,PetscInt *edgelist)
160c4762a1bSJed Brown {
161c4762a1bSJed Brown   PetscInt       i,j,node1,node2;
162c4762a1bSJed Brown   Pipe           *pipe;
163c4762a1bSJed Brown   Pump           *pump;
164c4762a1bSJed Brown   PetscBool      netview=PETSC_FALSE;
165c4762a1bSJed Brown 
166c4762a1bSJed Brown   PetscFunctionBegin;
167*9566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL,NULL, "-water_view",&netview));
168c4762a1bSJed Brown   for (i=0; i < water->nedge; i++) {
169c4762a1bSJed Brown     if (water->edge[i].type == EDGE_TYPE_PIPE) {
170c4762a1bSJed Brown       pipe  = &water->edge[i].pipe;
171c4762a1bSJed Brown       node1 = pipe->node1;
172c4762a1bSJed Brown       node2 = pipe->node2;
173c4762a1bSJed Brown       if (netview) {
174*9566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF,"edge %d, pipe v[%d] -> v[%d]\n",i,node1,node2));
175c4762a1bSJed Brown       }
176c4762a1bSJed Brown     } else {
177c4762a1bSJed Brown       pump  = &water->edge[i].pump;
178c4762a1bSJed Brown       node1 = pump->node1;
179c4762a1bSJed Brown       node2 = pump->node2;
180c4762a1bSJed Brown       if (netview) {
181*9566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF,"edge %d, pump v[%d] -> v[%d]\n",i,node1,node2));
182c4762a1bSJed Brown       }
183c4762a1bSJed Brown     }
184c4762a1bSJed Brown 
185c4762a1bSJed Brown     for (j=0; j < water->nvertex; j++) {
186c4762a1bSJed Brown       if (water->vertex[j].id == node1) {
187c4762a1bSJed Brown         edgelist[2*i] = j;
188c4762a1bSJed Brown         break;
189c4762a1bSJed Brown       }
190c4762a1bSJed Brown     }
191c4762a1bSJed Brown 
192c4762a1bSJed Brown     for (j=0; j < water->nvertex; j++) {
193c4762a1bSJed Brown       if (water->vertex[j].id == node2) {
194c4762a1bSJed Brown         edgelist[2*i+1] = j;
195c4762a1bSJed Brown         break;
196c4762a1bSJed Brown       }
197c4762a1bSJed Brown     }
198c4762a1bSJed Brown   }
199c4762a1bSJed Brown   PetscFunctionReturn(0);
200c4762a1bSJed Brown }
201c4762a1bSJed Brown 
202c4762a1bSJed Brown PetscErrorCode SetInitialGuess_Water(DM networkdm,Vec localX,PetscInt nv,PetscInt ne, const PetscInt *vtx, const PetscInt *edges,void* appctx)
203c4762a1bSJed Brown {
204c4762a1bSJed Brown   PetscInt       i,offset,key;
2052bf73ac6SHong Zhang   PetscBool      ghostvtex,sharedv;
206c4762a1bSJed Brown   VERTEX_Water   vertex;
207c4762a1bSJed Brown   PetscScalar    *xarr;
208c4762a1bSJed Brown 
209c4762a1bSJed Brown   PetscFunctionBegin;
210*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(localX,&xarr));
211c4762a1bSJed Brown   for (i=0; i < nv; i++) {
212*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkIsGhostVertex(networkdm,vtx[i],&ghostvtex));
213*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkIsSharedVertex(networkdm,vtx[i],&sharedv));
2142bf73ac6SHong Zhang     if (ghostvtex || sharedv) continue;
215c4762a1bSJed Brown 
216*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetComponent(networkdm,vtx[i],0,&key,(void**)&vertex,NULL));
217*9566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetLocalVecOffset(networkdm,vtx[i],0,&offset));
218c4762a1bSJed Brown     if (vertex->type == VERTEX_TYPE_JUNCTION) {
219c4762a1bSJed Brown       xarr[offset] = 100;
220c4762a1bSJed Brown     } else if (vertex->type == VERTEX_TYPE_RESERVOIR) {
221c4762a1bSJed Brown       xarr[offset] = vertex->res.head;
222c4762a1bSJed Brown     } else {
223c4762a1bSJed Brown       xarr[offset] = vertex->tank.initlvl + vertex->tank.elev;
224c4762a1bSJed Brown     }
225c4762a1bSJed Brown   }
226*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(localX,&xarr));
227c4762a1bSJed Brown   PetscFunctionReturn(0);
228c4762a1bSJed Brown }
229