PetscErrorCode SetInitialGuess_Water(DM networkdm,Vec localX,PetscInt nv,PetscInt ne, const PetscInt *vtx, const PetscInt *edges,void* appctx) { PetscErrorCode ierr; PetscInt i,offset,key; PetscBool ghostvtex; VERTEX_Water vertex; PetscScalar *xarr; PetscFunctionBegin; ierr = VecGetArray(localX,&xarr);CHKERRQ(ierr); for (i=0; i < nv; i++) { ierr = DMNetworkIsGhostVertex(networkdm,vtx[i],&ghostvtex);CHKERRQ(ierr); if (ghostvtex) continue; ierr = DMNetworkGetVariableOffset(networkdm,vtx[i],&offset);CHKERRQ(ierr); ierr = DMNetworkGetComponent(networkdm,vtx[i],0,&key,(void**)&vertex);CHKERRQ(ierr); if (vertex->type == VERTEX_TYPE_JUNCTION) { xarr[offset] = 100; } else if (vertex->type == VERTEX_TYPE_RESERVOIR) { xarr[offset] = vertex->res.head; } else { xarr[offset] = vertex->tank.initlvl + vertex->tank.elev; } } ierr = VecRestoreArray(localX,&xarr);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode SetInitialValues(DM networkdm,Vec X,void* appctx) { PetscErrorCode ierr; VERTEXDATA bus; GEN gen; PetscInt v, vStart, vEnd, offset; PetscBool ghostvtex; Vec localX; PetscScalar *xarr; PetscInt key,numComps,j,offsetd; DMNetworkComponentGenericDataType *arr; PetscFunctionBegin; ierr = DMNetworkGetVertexRange(networkdm,&vStart, &vEnd);CHKERRQ(ierr); ierr = DMGetLocalVector(networkdm,&localX);CHKERRQ(ierr); ierr = VecSet(X,0.0);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = VecGetArray(localX,&xarr);CHKERRQ(ierr); ierr = DMNetworkGetComponentDataArray(networkdm,&arr);CHKERRQ(ierr); for (v = vStart; v < vEnd; v++) { ierr = DMNetworkIsGhostVertex(networkdm,v,&ghostvtex);CHKERRQ(ierr); if (ghostvtex) continue; ierr = DMNetworkGetVariableOffset(networkdm,v,&offset);CHKERRQ(ierr); ierr = DMNetworkGetNumComponents(networkdm,v,&numComps);CHKERRQ(ierr); for (j=0; j < numComps; j++) { ierr = DMNetworkGetComponentTypeOffset(networkdm,v,j,&key,&offsetd);CHKERRQ(ierr); if (key == 1) { bus = (VERTEXDATA)(arr+offsetd); xarr[offset] = bus->va*PETSC_PI/180.0; xarr[offset+1] = bus->vm; } else if(key == 2) { gen = (GEN)(arr+offsetd); if (!gen->status) continue; xarr[offset+1] = gen->vs; break; } } } ierr = VecRestoreArray(localX,&xarr);CHKERRQ(ierr); ierr = DMLocalToGlobalBegin(networkdm,localX,ADD_VALUES,X);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(networkdm,localX,ADD_VALUES,X);CHKERRQ(ierr); ierr = DMRestoreLocalVector(networkdm,&localX);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormFunction(SNES snes,Vec X, Vec F,void *appctx) { PetscErrorCode ierr; DM networkdm; UserCtx *User=(UserCtx*)appctx; Vec localX,localF; PetscInt e; PetscInt v,vStart,vEnd,vfrom,vto; const PetscScalar *xarr; PetscScalar *farr; PetscInt offsetfrom,offsetto,offset; DMNetworkComponentGenericDataType *arr; PetscFunctionBegin; ierr = SNESGetDM(snes,&networkdm);CHKERRQ(ierr); ierr = DMGetLocalVector(networkdm,&localX);CHKERRQ(ierr); ierr = DMGetLocalVector(networkdm,&localF);CHKERRQ(ierr); ierr = VecSet(F,0.0);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(networkdm,F,INSERT_VALUES,localF);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(networkdm,F,INSERT_VALUES,localF);CHKERRQ(ierr); ierr = VecGetArrayRead(localX,&xarr);CHKERRQ(ierr); ierr = VecGetArray(localF,&farr);CHKERRQ(ierr); ierr = DMNetworkGetVertexRange(networkdm,&vStart,&vEnd);CHKERRQ(ierr); ierr = DMNetworkGetComponentDataArray(networkdm,&arr);CHKERRQ(ierr); for (v=vStart; v < vEnd; v++) { PetscInt i,j,offsetd,key; PetscScalar Vm; PetscScalar Sbase=User->Sbase; VERTEXDATA bus=NULL; GEN gen; LOAD load; PetscBool ghostvtex; PetscInt numComps; ierr = DMNetworkIsGhostVertex(networkdm,v,&ghostvtex);CHKERRQ(ierr); ierr = DMNetworkGetNumComponents(networkdm,v,&numComps);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,v,&offset);CHKERRQ(ierr); for (j = 0; j < numComps; j++) { ierr = DMNetworkGetComponentTypeOffset(networkdm,v,j,&key,&offsetd);CHKERRQ(ierr); if (key == 1) { PetscInt nconnedges; const PetscInt *connedges; bus = (VERTEXDATA)(arr+offsetd); /* Handle reference bus constrained dofs */ if (bus->ide == REF_BUS || bus->ide == ISOLATED_BUS) { farr[offset] = xarr[offset] - bus->va*PETSC_PI/180.0; farr[offset+1] = xarr[offset+1] - bus->vm; break; } if (!ghostvtex) { Vm = xarr[offset+1]; /* Shunt injections */ farr[offset] += Vm*Vm*bus->gl/Sbase; if(bus->ide != PV_BUS) farr[offset+1] += -Vm*Vm*bus->bl/Sbase; } ierr = DMNetworkGetSupportingEdges(networkdm,v,&nconnedges,&connedges);CHKERRQ(ierr); for (i=0; i < nconnedges; i++) { EDGEDATA branch; PetscInt keye; PetscScalar Gff,Bff,Gft,Bft,Gtf,Btf,Gtt,Btt; const PetscInt *cone; PetscScalar Vmf,Vmt,thetaf,thetat,thetaft,thetatf; e = connedges[i]; ierr = DMNetworkGetComponentTypeOffset(networkdm,e,0,&keye,&offsetd);CHKERRQ(ierr); branch = (EDGEDATA)(arr+offsetd); if (!branch->status) continue; Gff = branch->yff[0]; Bff = branch->yff[1]; Gft = branch->yft[0]; Bft = branch->yft[1]; Gtf = branch->ytf[0]; Btf = branch->ytf[1]; Gtt = branch->ytt[0]; Btt = branch->ytt[1]; ierr = DMNetworkGetConnectedNodes(networkdm,e,&cone);CHKERRQ(ierr); vfrom = cone[0]; vto = cone[1]; ierr = DMNetworkGetVariableOffset(networkdm,vfrom,&offsetfrom);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,vto,&offsetto);CHKERRQ(ierr); thetaf = xarr[offsetfrom]; Vmf = xarr[offsetfrom+1]; thetat = xarr[offsetto]; Vmt = xarr[offsetto+1]; thetaft = thetaf - thetat; thetatf = thetat - thetaf; if (vfrom == v) { farr[offsetfrom] += Gff*Vmf*Vmf + Vmf*Vmt*(Gft*PetscCosScalar(thetaft) + Bft*PetscSinScalar(thetaft)); farr[offsetfrom+1] += -Bff*Vmf*Vmf + Vmf*Vmt*(-Bft*PetscCosScalar(thetaft) + Gft*PetscSinScalar(thetaft)); } else { farr[offsetto] += Gtt*Vmt*Vmt + Vmt*Vmf*(Gtf*PetscCosScalar(thetatf) + Btf*PetscSinScalar(thetatf)); farr[offsetto+1] += -Btt*Vmt*Vmt + Vmt*Vmf*(-Btf*PetscCosScalar(thetatf) + Gtf*PetscSinScalar(thetatf)); } } } else if (key == 2) { if (!ghostvtex) { gen = (GEN)(arr+offsetd); if (!gen->status) continue; farr[offset] += -gen->pg/Sbase; farr[offset+1] += -gen->qg/Sbase; } } else if (key == 3) { if (!ghostvtex) { load = (LOAD)(arr+offsetd); farr[offset] += load->pl/Sbase; farr[offset+1] += load->ql/Sbase; } } } if (bus && bus->ide == PV_BUS) { farr[offset+1] = xarr[offset+1] - bus->vm; } } ierr = VecRestoreArrayRead(localX,&xarr);CHKERRQ(ierr); ierr = VecRestoreArray(localF,&farr);CHKERRQ(ierr); ierr = DMRestoreLocalVector(networkdm,&localX);CHKERRQ(ierr); ierr = DMLocalToGlobalBegin(networkdm,localF,ADD_VALUES,F);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(networkdm,localF,ADD_VALUES,F);CHKERRQ(ierr); ierr = DMRestoreLocalVector(networkdm,&localF);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormJacobian(SNES snes,Vec X, Mat J,Mat Jpre,void *appctx) { PetscErrorCode ierr; DM networkdm; UserCtx *User=(UserCtx*)appctx; Vec localX; PetscInt e; PetscInt v,vStart,vEnd,vfrom,vto; const PetscScalar *xarr; PetscInt offsetfrom,offsetto,goffsetfrom,goffsetto; DMNetworkComponentGenericDataType *arr; PetscInt row[2],col[8]; PetscScalar values[8]; PetscFunctionBegin; ierr = MatZeroEntries(J);CHKERRQ(ierr); ierr = SNESGetDM(snes,&networkdm);CHKERRQ(ierr); ierr = DMGetLocalVector(networkdm,&localX);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = VecGetArrayRead(localX,&xarr);CHKERRQ(ierr); ierr = DMNetworkGetVertexRange(networkdm,&vStart,&vEnd);CHKERRQ(ierr); ierr = DMNetworkGetComponentDataArray(networkdm,&arr);CHKERRQ(ierr); for (v=vStart; v < vEnd; v++) { PetscInt i,j,offsetd,key; PetscInt offset,goffset; PetscScalar Vm; PetscScalar Sbase=User->Sbase; VERTEXDATA bus; PetscBool ghostvtex; PetscInt numComps; ierr = DMNetworkIsGhostVertex(networkdm,v,&ghostvtex);CHKERRQ(ierr); ierr = DMNetworkGetNumComponents(networkdm,v,&numComps);CHKERRQ(ierr); for (j = 0; j < numComps; j++) { ierr = DMNetworkGetVariableOffset(networkdm,v,&offset);CHKERRQ(ierr); ierr = DMNetworkGetVariableGlobalOffset(networkdm,v,&goffset);CHKERRQ(ierr); ierr = DMNetworkGetComponentTypeOffset(networkdm,v,j,&key,&offsetd);CHKERRQ(ierr); if (key == 1) { PetscInt nconnedges; const PetscInt *connedges; bus = (VERTEXDATA)(arr+offsetd); if (!ghostvtex) { /* Handle reference bus constrained dofs */ if (bus->ide == REF_BUS || bus->ide == ISOLATED_BUS) { row[0] = goffset; row[1] = goffset+1; col[0] = goffset; col[1] = goffset+1; col[2] = goffset; col[3] = goffset+1; values[0] = 1.0; values[1] = 0.0; values[2] = 0.0; values[3] = 1.0; ierr = MatSetValues(J,2,row,2,col,values,ADD_VALUES);CHKERRQ(ierr); break; } Vm = xarr[offset+1]; /* Shunt injections */ row[0] = goffset; row[1] = goffset+1; col[0] = goffset; col[1] = goffset+1; values[0] = values[1] = values[2] = values[3] = 0.0; if (bus->ide != PV_BUS) { values[1] = 2.0*Vm*bus->gl/Sbase; values[3] = -2.0*Vm*bus->bl/Sbase; } ierr = MatSetValues(J,2,row,2,col,values,ADD_VALUES);CHKERRQ(ierr); } ierr = DMNetworkGetSupportingEdges(networkdm,v,&nconnedges,&connedges);CHKERRQ(ierr); for (i=0; i < nconnedges; i++) { EDGEDATA branch; VERTEXDATA busf,bust; PetscInt offsetfd,offsettd,keyf,keyt; PetscScalar Gff,Bff,Gft,Bft,Gtf,Btf,Gtt,Btt; const PetscInt *cone; PetscScalar Vmf,Vmt,thetaf,thetat,thetaft,thetatf; e = connedges[i]; ierr = DMNetworkGetComponentTypeOffset(networkdm,e,0,&key,&offsetd);CHKERRQ(ierr); branch = (EDGEDATA)(arr+offsetd); if (!branch->status) continue; Gff = branch->yff[0]; Bff = branch->yff[1]; Gft = branch->yft[0]; Bft = branch->yft[1]; Gtf = branch->ytf[0]; Btf = branch->ytf[1]; Gtt = branch->ytt[0]; Btt = branch->ytt[1]; ierr = DMNetworkGetConnectedNodes(networkdm,e,&cone);CHKERRQ(ierr); vfrom = cone[0]; vto = cone[1]; ierr = DMNetworkGetVariableOffset(networkdm,vfrom,&offsetfrom);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,vto,&offsetto);CHKERRQ(ierr); ierr = DMNetworkGetVariableGlobalOffset(networkdm,vfrom,&goffsetfrom);CHKERRQ(ierr); ierr = DMNetworkGetVariableGlobalOffset(networkdm,vto,&goffsetto);CHKERRQ(ierr); if (goffsetto < 0) goffsetto = -goffsetto - 1; thetaf = xarr[offsetfrom]; Vmf = xarr[offsetfrom+1]; thetat = xarr[offsetto]; Vmt = xarr[offsetto+1]; thetaft = thetaf - thetat; thetatf = thetat - thetaf; ierr = DMNetworkGetComponentTypeOffset(networkdm,vfrom,0,&keyf,&offsetfd);CHKERRQ(ierr); ierr = DMNetworkGetComponentTypeOffset(networkdm,vto,0,&keyt,&offsettd);CHKERRQ(ierr); busf = (VERTEXDATA)(arr+offsetfd); bust = (VERTEXDATA)(arr+offsettd); if (vfrom == v) { if (busf->ide != REF_BUS) { /* farr[offsetfrom] += Gff*Vmf*Vmf + Vmf*Vmt*(Gft*PetscCosScalar(thetaft) + Bft*PetscSinScalar(thetaft)); */ row[0] = goffsetfrom; col[0] = goffsetfrom; col[1] = goffsetfrom+1; col[2] = goffsetto; col[3] = goffsetto+1; values[0] = Vmf*Vmt*(Gft*-PetscSinScalar(thetaft) + Bft*PetscCosScalar(thetaft)); /* df_dthetaf */ values[1] = 2.0*Gff*Vmf + Vmt*(Gft*PetscCosScalar(thetaft) + Bft*PetscSinScalar(thetaft)); /* df_dVmf */ values[2] = Vmf*Vmt*(Gft*PetscSinScalar(thetaft) + Bft*-PetscCosScalar(thetaft)); /* df_dthetat */ values[3] = Vmf*(Gft*PetscCosScalar(thetaft) + Bft*PetscSinScalar(thetaft)); /* df_dVmt */ ierr = MatSetValues(J,1,row,4,col,values,ADD_VALUES);CHKERRQ(ierr); } if (busf->ide != PV_BUS && busf->ide != REF_BUS) { row[0] = goffsetfrom+1; col[0] = goffsetfrom; col[1] = goffsetfrom+1; col[2] = goffsetto; col[3] = goffsetto+1; /* farr[offsetfrom+1] += -Bff*Vmf*Vmf + Vmf*Vmt*(-Bft*PetscCosScalar(thetaft) + Gft*PetscSinScalar(thetaft)); */ values[0] = Vmf*Vmt*(Bft*PetscSinScalar(thetaft) + Gft*PetscCosScalar(thetaft)); values[1] = -2.0*Bff*Vmf + Vmt*(-Bft*PetscCosScalar(thetaft) + Gft*PetscSinScalar(thetaft)); values[2] = Vmf*Vmt*(-Bft*PetscSinScalar(thetaft) + Gft*-PetscCosScalar(thetaft)); values[3] = Vmf*(-Bft*PetscCosScalar(thetaft) + Gft*PetscSinScalar(thetaft)); ierr = MatSetValues(J,1,row,4,col,values,ADD_VALUES);CHKERRQ(ierr); } } else { if (bust->ide != REF_BUS) { row[0] = goffsetto; col[0] = goffsetto; col[1] = goffsetto+1; col[2] = goffsetfrom; col[3] = goffsetfrom+1; /* farr[offsetto] += Gtt*Vmt*Vmt + Vmt*Vmf*(Gtf*PetscCosScalar(thetatf) + Btf*PetscSinScalar(thetatf)); */ values[0] = Vmt*Vmf*(Gtf*-PetscSinScalar(thetatf) + Btf*PetscCosScalar(thetaft)); /* df_dthetat */ values[1] = 2.0*Gtt*Vmt + Vmf*(Gtf*PetscCosScalar(thetatf) + Btf*PetscSinScalar(thetatf)); /* df_dVmt */ values[2] = Vmt*Vmf*(Gtf*PetscSinScalar(thetatf) + Btf*-PetscCosScalar(thetatf)); /* df_dthetaf */ values[3] = Vmt*(Gtf*PetscCosScalar(thetatf) + Btf*PetscSinScalar(thetatf)); /* df_dVmf */ ierr = MatSetValues(J,1,row,4,col,values,ADD_VALUES);CHKERRQ(ierr); } if (bust->ide != PV_BUS && bust->ide != REF_BUS) { row[0] = goffsetto+1; col[0] = goffsetto; col[1] = goffsetto+1; col[2] = goffsetfrom; col[3] = goffsetfrom+1; /* farr[offsetto+1] += -Btt*Vmt*Vmt + Vmt*Vmf*(-Btf*PetscCosScalar(thetatf) + Gtf*PetscSinScalar(thetatf)); */ values[0] = Vmt*Vmf*(Btf*PetscSinScalar(thetatf) + Gtf*PetscCosScalar(thetatf)); values[1] = -2.0*Btt*Vmt + Vmf*(-Btf*PetscCosScalar(thetatf) + Gtf*PetscSinScalar(thetatf)); values[2] = Vmt*Vmf*(-Btf*PetscSinScalar(thetatf) + Gtf*-PetscCosScalar(thetatf)); values[3] = Vmt*(-Btf*PetscCosScalar(thetatf) + Gtf*PetscSinScalar(thetatf)); ierr = MatSetValues(J,1,row,4,col,values,ADD_VALUES);CHKERRQ(ierr); } } } if (!ghostvtex && bus->ide == PV_BUS) { row[0] = goffset+1; col[0] = goffset+1; values[0] = 1.0; ierr = MatSetValues(J,1,row,1,col,values,ADD_VALUES);CHKERRQ(ierr); } } } } ierr = VecRestoreArrayRead(localX,&xarr);CHKERRQ(ierr); ierr = DMRestoreLocalVector(networkdm,&localX);CHKERRQ(ierr); ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormOperator(DM networkdm,Mat A,Vec b) { PetscErrorCode ierr; Vec localb; Branch *branch; Node *node; PetscInt e,v,vStart,vEnd,eStart, eEnd; PetscInt lofst,lofst_to,lofst_fr,row[2],col[6]; PetscBool ghost; const PetscInt *cone; PetscScalar *barr,val[6]; PetscFunctionBegin; ierr = DMGetLocalVector(networkdm,&localb);CHKERRQ(ierr); ierr = VecSet(b,0.0);CHKERRQ(ierr); ierr = VecSet(localb,0.0);CHKERRQ(ierr); ierr = MatZeroEntries(A);CHKERRQ(ierr); ierr = VecGetArray(localb,&barr);CHKERRQ(ierr); /* We can define the current as a "edge characteristic" and the voltage and the voltage as a "vertex characteristic". With that, we can iterate the list of edges and vertices, query the associated voltages and currents and use them to write the Kirchoff equations. */ /* Branch equations: i/r + uj - ui = battery */ ierr = DMNetworkGetEdgeRange(networkdm,&eStart,&eEnd);CHKERRQ(ierr); for (e = 0; e < eEnd; e++) { ierr = DMNetworkGetComponent(networkdm,e,0,NULL,(void**)&branch);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,e,&lofst);CHKERRQ(ierr); ierr = DMNetworkGetConnectedVertices(networkdm,e,&cone);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,cone[0],&lofst_fr);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,cone[1],&lofst_to);CHKERRQ(ierr); barr[lofst] = branch->bat; row[0] = lofst; col[0] = lofst; val[0] = 1; col[1] = lofst_to; val[1] = 1; col[2] = lofst_fr; val[2] = -1; ierr = MatSetValuesLocal(A,1,row,3,col,val,ADD_VALUES);CHKERRQ(ierr); /* from node */ ierr = DMNetworkGetComponent(networkdm,cone[0],0,NULL,(void**)&node);CHKERRQ(ierr); if (!node->gr) { row[0] = lofst_fr; col[0] = lofst; val[0] = 1; ierr = MatSetValuesLocal(A,1,row,1,col,val,ADD_VALUES);CHKERRQ(ierr); } /* to node */ ierr = DMNetworkGetComponent(networkdm,cone[1],0,NULL,(void**)&node);CHKERRQ(ierr); if (!node->gr) { row[0] = lofst_to; col[0] = lofst; val[0] = -1; ierr = MatSetValuesLocal(A,1,row,1,col,val,ADD_VALUES);CHKERRQ(ierr); } } ierr = DMNetworkGetVertexRange(networkdm,&vStart,&vEnd);CHKERRQ(ierr); for (v = vStart; v < vEnd; v++) { ierr = DMNetworkIsGhostVertex(networkdm,v,&ghost);CHKERRQ(ierr); if (!ghost) { ierr = DMNetworkGetComponent(networkdm,v,0,NULL,(void**)&node);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,v,&lofst);CHKERRQ(ierr); if (node->gr) { row[0] = lofst; col[0] = lofst; val[0] = 1; ierr = MatSetValuesLocal(A,1,row,1,col,val,ADD_VALUES);CHKERRQ(ierr); } else { barr[lofst] -= node->inj; } } } ierr = VecRestoreArray(localb,&barr);CHKERRQ(ierr); ierr = DMLocalToGlobalBegin(networkdm,localb,ADD_VALUES,b);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(networkdm,localb,ADD_VALUES,b);CHKERRQ(ierr); ierr = DMRestoreLocalVector(networkdm,&localb);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode WASHIFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void* ctx) { PetscErrorCode ierr; Wash wash=(Wash)ctx; DM networkdm; Vec localX,localXdot,localF; const PetscInt *cone; PetscInt vfrom,vto,offsetfrom,offsetto,type,varoffset,voffset; PetscInt v,vStart,vEnd,e,eStart,eEnd,pipeoffset; PetscBool ghost; PetscScalar *farr,*vf,*juncx,*juncf; Pipe pipe; PipeField *pipex,*pipexdot,*pipef; DMDALocalInfo info; Junction junction; MPI_Comm comm; PetscMPIInt rank,size; const PetscScalar *xarr,*xdotarr; DMNetworkComponentGenericDataType *nwarr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); ierr = VecSet(F,0.0);CHKERRQ(ierr); localX = wash->localX; localXdot = wash->localXdot; ierr = TSGetDM(ts,&networkdm);CHKERRQ(ierr); ierr = DMGetLocalVector(networkdm,&localF);CHKERRQ(ierr); ierr = VecSet(localF,0.0);CHKERRQ(ierr); /* update ghost values of locaX and locaXdot */ ierr = DMGlobalToLocalBegin(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(networkdm,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(networkdm,Xdot,INSERT_VALUES,localXdot);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(networkdm,Xdot,INSERT_VALUES,localXdot);CHKERRQ(ierr); ierr = VecGetArrayRead(localX,&xarr);CHKERRQ(ierr); ierr = VecGetArrayRead(localXdot,&xdotarr);CHKERRQ(ierr); ierr = VecGetArray(localF,&farr);CHKERRQ(ierr); /* Initialize localF = localX at non-ghost vertices */ ierr = DMNetworkGetVertexRange(networkdm,&vStart,&vEnd);CHKERRQ(ierr); for (v=vStart; v<vEnd; v++) { ierr = DMNetworkIsGhostVertex(networkdm,v,&ghost);CHKERRQ(ierr); if (!ghost) { ierr = DMNetworkGetVariableOffset(networkdm,v,&varoffset);CHKERRQ(ierr); juncx = (PetscScalar*)(xarr+varoffset); juncf = (PetscScalar*)(farr+varoffset); juncf[0] = juncx[0]; juncf[1] = juncx[1]; } } /* Get component(application) data array */ ierr = DMNetworkGetComponentDataArray(networkdm,&nwarr);CHKERRQ(ierr); /* Edge */ ierr = DMNetworkGetEdgeRange(networkdm,&eStart,&eEnd);CHKERRQ(ierr); for (e=eStart; e<eEnd; e++) { ierr = DMNetworkGetComponentTypeOffset(networkdm,e,0,&type,&pipeoffset);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,e,&varoffset);CHKERRQ(ierr); pipe = (Pipe)(nwarr + pipeoffset); pipex = (PipeField*)(xarr + varoffset); pipexdot = (PipeField*)(xdotarr + varoffset); pipef = (PipeField*)(farr + varoffset); /* Get boundary values H0 and QL from connected vertices */ ierr = DMNetworkGetConnectedNodes(networkdm,e,&cone);CHKERRQ(ierr); vfrom = cone[0]; /* local ordering */ vto = cone[1]; ierr = DMNetworkGetVariableOffset(networkdm,vfrom,&offsetfrom);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,vto,&offsetto);CHKERRQ(ierr); if (pipe->boundary.Q0 == PIPE_CHARACTERISTIC) { pipe->boundary.H0 = (xarr+offsetfrom)[1]; /* h_from */ } else { pipe->boundary.Q0 = (xarr+offsetfrom)[0]; /* q_from */ } if (pipe->boundary.HL == PIPE_CHARACTERISTIC) { pipe->boundary.QL = (xarr+offsetto)[0]; /* q_to */ } else { pipe->boundary.HL = (xarr+offsetto)[1]; /* h_to */ } /* Evaluate PipeIFunctionLocal() */ ierr = DMDAGetLocalInfo(pipe->da,&info);CHKERRQ(ierr); ierr = PipeIFunctionLocal(&info, t, pipex, pipexdot, pipef, pipe);CHKERRQ(ierr); /* Set F at vfrom */ vf = (PetscScalar*)(farr+offsetfrom); if (pipe->boundary.Q0 == PIPE_CHARACTERISTIC) { vf[0] -= pipex[0].q; /* q_vfrom - q[0] */ } else { vf[1] -= pipex[0].h; /* h_vfrom - h[0] */ } /* Set F at vto */ vf = (PetscScalar*)(farr+offsetto); if (pipe->boundary.HL == PIPE_CHARACTERISTIC) { vf[1] -= pipex[pipe->nnodes-1].h; /* h_vto - h[last] */ } else { vf[0] -= pipex[pipe->nnodes-1].q; /* q_vto - q[last] */ } } /* Set F at boundary vertices */ for (v=vStart; v<vEnd; v++) { ierr = DMNetworkGetComponentTypeOffset(networkdm,v,0,&type,&voffset);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,v,&varoffset);CHKERRQ(ierr); junction = (Junction)(nwarr + voffset); juncf = (PetscScalar *)(farr + varoffset); if (junction->isEnd == -1) { juncf[1] -= wash->H0; } else if (junction->isEnd == 1) { juncf[0] -= wash->QL; } } ierr = VecRestoreArrayRead(localX,&xarr);CHKERRQ(ierr); ierr = VecRestoreArrayRead(localXdot,&xdotarr);CHKERRQ(ierr); ierr = VecRestoreArray(localF,&farr);CHKERRQ(ierr); ierr = DMLocalToGlobalBegin(networkdm,localF,ADD_VALUES,F);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(networkdm,localF,ADD_VALUES,F);CHKERRQ(ierr); ierr = DMRestoreLocalVector(networkdm,&localF);CHKERRQ(ierr); /* ierr = VecView(F,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ PetscFunctionReturn(0); }
/* ------------------------------------------------------- */ int main(int argc,char ** argv) { PetscErrorCode ierr; Wash wash; Junction junctions,junction; Pipe pipe,pipes; PetscInt numEdges,numVertices,KeyPipe,KeyJunction; int *edgelist = NULL; PetscInt i,e,v,eStart,eEnd,vStart,vEnd,pipeOffset,key,frombType,tobType; PetscInt vfrom,vto,vkey,fromOffset,toOffset,type,varoffset,pipeoffset; PetscInt from_nedge_in,from_nedge_out,to_nedge_in; const PetscInt *cone; DM networkdm; PetscMPIInt size,rank; PetscReal ftime = 2500.0; Vec X; TS ts; PetscInt maxsteps=-1,steps; TSConvergedReason reason; PetscBool viewpipes; PetscInt pipesCase; DMNetworkMonitor monitor; DMNetworkComponentGenericDataType *nwarr; ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); /* Create and setup network */ /*--------------------------*/ ierr = DMNetworkCreate(PETSC_COMM_WORLD,&networkdm);CHKERRQ(ierr); if (size == 1) { ierr = DMNetworkMonitorCreate(networkdm,&monitor);CHKERRQ(ierr); } /* Register the components in the network */ ierr = DMNetworkRegisterComponent(networkdm,"junctionstruct",sizeof(struct _p_Junction),&KeyJunction);CHKERRQ(ierr); ierr = DMNetworkRegisterComponent(networkdm,"pipestruct",sizeof(struct _p_Pipe),&KeyPipe);CHKERRQ(ierr); /* Set global number of pipes, edges, and vertices */ pipesCase = 2; ierr = PetscOptionsGetInt(NULL,NULL, "-case", &pipesCase, NULL);CHKERRQ(ierr); ierr = WashNetworkCreate(PETSC_COMM_WORLD,pipesCase,&wash,&edgelist);CHKERRQ(ierr); numEdges = wash->nedge; numVertices = wash->nvertex; junctions = wash->junction; pipes = wash->pipe; /* Set number of vertices and edges */ ierr = DMNetworkSetSizes(networkdm,numVertices,numEdges,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); /* Add edge connectivity */ ierr = DMNetworkSetEdgeList(networkdm,edgelist);CHKERRQ(ierr); /* Set up the network layout */ ierr = DMNetworkLayoutSetUp(networkdm);CHKERRQ(ierr); /* Add EDGEDATA component to all edges -- currently networkdm is a sequential network */ ierr = DMNetworkGetEdgeRange(networkdm,&eStart,&eEnd);CHKERRQ(ierr); ierr = DMNetworkGetVertexRange(networkdm,&vStart,&vEnd);CHKERRQ(ierr); for (e = eStart; e < eEnd; e++) { /* Add Pipe component to all edges -- create pipe here */ ierr = DMNetworkAddComponent(networkdm,e,KeyPipe,&pipes[e-eStart]);CHKERRQ(ierr); /* Add number of variables to each edge */ ierr = DMNetworkAddNumVariables(networkdm,e,2*pipes[e-eStart].nnodes);CHKERRQ(ierr); if (size == 1) { /* Add monitor -- show Q_{pipes[e-eStart].id}? */ ierr = DMNetworkMonitorAdd(monitor, "Pipe Q", e, pipes[e-eStart].nnodes, 0, 2, -0.8, 0.8, PETSC_TRUE);CHKERRQ(ierr); ierr = DMNetworkMonitorAdd(monitor, "Pipe H", e, pipes[e-eStart].nnodes, 1, 2, -400.0, 800.0, PETSC_TRUE);CHKERRQ(ierr); } } /* Add Junction component to all vertices */ for (v = vStart; v < vEnd; v++) { ierr = DMNetworkAddComponent(networkdm,v,KeyJunction,&junctions[v-vStart]);CHKERRQ(ierr); /* Add number of variables to vertex */ ierr = DMNetworkAddNumVariables(networkdm,v,2);CHKERRQ(ierr); } /* Set up DM for use */ ierr = DMSetUp(networkdm);CHKERRQ(ierr); ierr = WashNetworkCleanUp(wash,edgelist);CHKERRQ(ierr); /* Network partitioning and distribution of data */ if (size > 1) { DM distnetworkdm; ierr = DMNetworkDistribute(networkdm,0,&distnetworkdm);CHKERRQ(ierr); ierr = DMDestroy(&networkdm);CHKERRQ(ierr); networkdm = distnetworkdm; } /* PipeSetUp -- each process only sets its own pipes */ /*---------------------------------------------------*/ ierr = DMNetworkGetComponentDataArray(networkdm,&nwarr);CHKERRQ(ierr); ierr = DMNetworkGetEdgeRange(networkdm,&eStart,&eEnd);CHKERRQ(ierr); for (e=eStart; e<eEnd; e++) { /* each edge has only one component, pipe */ ierr = DMNetworkGetComponentTypeOffset(networkdm,e,0,&type,&pipeoffset);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,e,&varoffset);CHKERRQ(ierr); pipe = (Pipe)(nwarr + pipeoffset); /* Setup conntected vertices */ ierr = DMNetworkGetConnectedNodes(networkdm,e,&cone);CHKERRQ(ierr); vfrom = cone[0]; /* local ordering */ vto = cone[1]; /* vfrom */ ierr = DMNetworkGetComponentTypeOffset(networkdm,vfrom,0,&vkey,&fromOffset);CHKERRQ(ierr); junction = (Junction)(nwarr+fromOffset); from_nedge_in = junction->nedges_in; from_nedge_out = junction->nedges_out; /* vto */ ierr = DMNetworkGetComponentTypeOffset(networkdm,vto,0,&vkey,&toOffset);CHKERRQ(ierr); junction = (Junction)(nwarr+toOffset); to_nedge_in = junction->nedges_in; pipe->comm = PETSC_COMM_SELF; /* must be set here, otherwise crashes in my mac??? */ wash->nnodes_loc += pipe->nnodes; /* local total num of nodes, will be used by PipesView() */ ierr = PipeSetParameters(pipe, 600.0, /* length */ pipe->nnodes, /* nnodes -- rm from PipeSetParameters */ 0.5, /* diameter */ 1200.0, /* a */ 0.018);CHKERRQ(ierr); /* friction */ /* set boundary conditions for this pipe */ if (from_nedge_in <= 1 && from_nedge_out > 0) { frombType = 0; } else { frombType = 1; } if (to_nedge_in == 1) { tobType = 0; } else { tobType = 1; } if (frombType == 0) { pipe->boundary.Q0 = PIPE_CHARACTERISTIC; /* will be obtained from characteristic */ pipe->boundary.H0 = wash->H0; } else { pipe->boundary.Q0 = wash->Q0; pipe->boundary.H0 = PIPE_CHARACTERISTIC; /* will be obtained from characteristic */ } if (tobType == 0) { pipe->boundary.QL = wash->QL; pipe->boundary.HL = PIPE_CHARACTERISTIC; /* will be obtained from characteristic */ } else { pipe->boundary.QL = PIPE_CHARACTERISTIC; /* will be obtained from characteristic */ pipe->boundary.HL = wash->HL; } ierr = PipeSetUp(pipe);CHKERRQ(ierr); } /* create vectors */ ierr = DMCreateGlobalVector(networkdm,&X);CHKERRQ(ierr); ierr = DMCreateLocalVector(networkdm,&wash->localX);CHKERRQ(ierr); ierr = DMCreateLocalVector(networkdm,&wash->localXdot);CHKERRQ(ierr); /* Setup solver */ /*--------------------------------------------------------*/ ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr); ierr = TSSetDM(ts,(DM)networkdm);CHKERRQ(ierr); ierr = TSSetIFunction(ts,NULL,WASHIFunction,wash);CHKERRQ(ierr); ierr = TSSetDuration(ts,maxsteps,ftime);CHKERRQ(ierr); ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER);CHKERRQ(ierr); ierr = TSSetInitialTimeStep(ts,0.0,0.1);CHKERRQ(ierr); ierr = TSSetType(ts,TSBEULER);CHKERRQ(ierr); if (size == 1) { ierr = TSMonitorSet(ts, TSDMNetworkMonitor, monitor, NULL);CHKERRQ(ierr); } ierr = TSSetFromOptions(ts);CHKERRQ(ierr); ierr = WASHSetInitialSolution(networkdm,X,wash);CHKERRQ(ierr); ierr = TSSolve(ts,X);CHKERRQ(ierr); ierr = TSGetSolveTime(ts,&ftime);CHKERRQ(ierr); ierr = TSGetTimeStepNumber(ts,&steps);CHKERRQ(ierr); ierr = TSGetConvergedReason(ts,&reason);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"%s at time %g after %D steps\n",TSConvergedReasons[reason],(double)ftime,steps);CHKERRQ(ierr); /* ierr = VecView(X,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ /* View solution q and h */ /* --------------------- */ viewpipes = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,NULL, "-pipe_view", &viewpipes,NULL);CHKERRQ(ierr); if (viewpipes) { ierr = PipesView(X,networkdm,wash);CHKERRQ(ierr); } /* Free spaces */ /* ----------- */ ierr = TSDestroy(&ts);CHKERRQ(ierr); ierr = VecDestroy(&X);CHKERRQ(ierr); ierr = VecDestroy(&wash->localX);CHKERRQ(ierr); ierr = VecDestroy(&wash->localXdot);CHKERRQ(ierr); /* Destroy objects from each pipe that are created in PipeSetUp() */ ierr = DMNetworkGetEdgeRange(networkdm,&eStart, &eEnd);CHKERRQ(ierr); for (i = eStart; i < eEnd; i++) { ierr = DMNetworkGetComponentTypeOffset(networkdm,i,0,&key,&pipeOffset);CHKERRQ(ierr); pipe = (Pipe)(nwarr+pipeOffset); ierr = DMDestroy(&(pipe->da));CHKERRQ(ierr); ierr = VecDestroy(&pipe->x);CHKERRQ(ierr); } if (size == 1) { ierr = DMNetworkMonitorDestroy(&monitor);CHKERRQ(ierr); } ierr = DMDestroy(&networkdm);CHKERRQ(ierr); ierr = PetscFree(wash);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
PetscErrorCode WASHSetInitialSolution(DM networkdm,Vec X,Wash wash) { PetscErrorCode ierr; PetscInt k,nx,vkey,vOffset,vfrom,vto,offsetfrom,offsetto; PetscInt type,varoffset; PetscInt e,eStart,eEnd,pipeoffset; Vec localX; PetscScalar *xarr; Pipe pipe; Junction junction; const PetscInt *cone; const PetscScalar *xarray; DMNetworkComponentGenericDataType *nwarr; PetscFunctionBegin; ierr = VecSet(X,0.0);CHKERRQ(ierr); ierr = DMGetLocalVector(networkdm,&localX);CHKERRQ(ierr); ierr = VecGetArray(localX,&xarr);CHKERRQ(ierr); /* Get component(application) data array */ ierr = DMNetworkGetComponentDataArray(networkdm,&nwarr);CHKERRQ(ierr); /* Edge */ ierr = DMNetworkGetEdgeRange(networkdm,&eStart,&eEnd);CHKERRQ(ierr); for (e=eStart; e<eEnd; e++) { ierr = DMNetworkGetVariableOffset(networkdm,e,&varoffset);CHKERRQ(ierr); ierr = DMNetworkGetComponentTypeOffset(networkdm,e,0,&type,&pipeoffset);CHKERRQ(ierr); /* get from and to vertices */ ierr = DMNetworkGetConnectedNodes(networkdm,e,&cone);CHKERRQ(ierr); vfrom = cone[0]; /* local ordering */ vto = cone[1]; ierr = DMNetworkGetVariableOffset(networkdm,vfrom,&offsetfrom);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,vto,&offsetto);CHKERRQ(ierr); /* set initial values for this pipe */ /* Q0=0.477432; H0=150.0; needs to be updated by its succeeding pipe. Use SNESSolve()? */ pipe = (Pipe)(nwarr + pipeoffset); ierr = PipeComputeSteadyState(pipe, 0.477432, wash->H0);CHKERRQ(ierr); ierr = VecGetSize(pipe->x,&nx);CHKERRQ(ierr); ierr = VecGetArrayRead(pipe->x,&xarray);CHKERRQ(ierr); /* copy pipe->x to xarray */ for (k=0; k<nx; k++) { (xarr+varoffset)[k] = xarray[k]; } /* set boundary values into vfrom and vto */ if (pipe->boundary.Q0 == PIPE_CHARACTERISTIC) { (xarr+offsetfrom)[0] += xarray[0]; /* Q0 -> vfrom[0] */ } else { (xarr+offsetfrom)[1] += xarray[1]; /* H0 -> vfrom[1] */ } if (pipe->boundary.HL == PIPE_CHARACTERISTIC) { (xarr+offsetto)[1] += xarray[nx-1]; /* HL -> vto[1] */ } else { (xarr+offsetto)[0] += xarray[nx-2]; /* QL -> vto[0] */ } /* if vform is a head vertex: */ ierr = DMNetworkGetComponentTypeOffset(networkdm,vfrom,0,&vkey,&vOffset);CHKERRQ(ierr); junction = (Junction)(nwarr+vOffset); if (junction->isEnd == -1) { /* head junction */ (xarr+offsetfrom)[0] = 0.0; /* 1st Q -- not used */ (xarr+offsetfrom)[1] = wash->H0; /* 1st H */ } /* if vto is an end vertex: */ ierr = DMNetworkGetComponentTypeOffset(networkdm,vto,0,&vkey,&vOffset);CHKERRQ(ierr); junction = (Junction)(nwarr+vOffset); if (junction->isEnd == 1) { /* end junction */ (xarr+offsetto)[0] = wash->QL; /* last Q */ (xarr+offsetto)[1] = 0.0; /* last H -- not used */ } ierr = VecRestoreArrayRead(pipe->x,&xarray);CHKERRQ(ierr); } ierr = VecRestoreArray(localX,&xarr);CHKERRQ(ierr); ierr = DMLocalToGlobalBegin(networkdm,localX,ADD_VALUES,X);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(networkdm,localX,ADD_VALUES,X);CHKERRQ(ierr); ierr = DMRestoreLocalVector(networkdm,&localX);CHKERRQ(ierr); #if 0 PetscInt N; ierr = VecGetSize(X,&N);CHKERRQ(ierr); printf("initial solution %d:\n",N); ierr = VecView(X,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); #endif PetscFunctionReturn(0); }
PETSC_EXTERN void PETSC_STDCALL dmnetworkgetvariableoffset_(DM dm,PetscInt *p,PetscInt *offset, int *__ierr ){ *__ierr = DMNetworkGetVariableOffset( (DM)PetscToPointer((dm) ),*p,offset); }
PetscErrorCode FormFunction_Water(DM networkdm,Vec localX,Vec localF,PetscInt nv,PetscInt ne,const PetscInt* vtx,const PetscInt* edges,void* appctx) { PetscErrorCode ierr; const PetscScalar *xarr; const PetscInt *cone; PetscScalar *farr,hf,ht,flow; PetscInt i,key,vnode1,vnode2,offsetnode1,offsetnode2,offset; PetscBool ghostvtex; VERTEX_Water vertex,vertexnode1,vertexnode2; EDGE_Water edge; Pipe *pipe; Pump *pump; Reservoir *reservoir; Tank *tank; PetscFunctionBegin; /* Get arrays for the vectors */ ierr = VecGetArrayRead(localX,&xarr);CHKERRQ(ierr); ierr = VecGetArray(localF,&farr);CHKERRQ(ierr); for (i=0; i<ne; i++) { /* for each edge */ /* Get the offset and the key for the component for edge number e[i] */ ierr = DMNetworkGetComponent(networkdm,edges[i],0,&key,(void**)&edge);CHKERRQ(ierr); /* Get the numbers for the vertices covering this edge */ ierr = DMNetworkGetConnectedVertices(networkdm,edges[i],&cone);CHKERRQ(ierr); vnode1 = cone[0]; vnode2 = cone[1]; /* Get the components at the two vertices */ ierr = DMNetworkGetComponent(networkdm,vnode1,0,&key,(void**)&vertexnode1);CHKERRQ(ierr); ierr = DMNetworkGetComponent(networkdm,vnode2,0,&key,(void**)&vertexnode2);CHKERRQ(ierr); /* Get the variable offset (the starting location for the variables in the farr array) for node1 and node2 */ ierr = DMNetworkGetVariableOffset(networkdm,vnode1,&offsetnode1);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,vnode2,&offsetnode2);CHKERRQ(ierr); /* Variables at node1 and node 2 */ hf = xarr[offsetnode1]; ht = xarr[offsetnode2]; flow = 0.0; if (edge->type == EDGE_TYPE_PIPE) { pipe = &edge->pipe; flow = Flow_Pipe(pipe,hf,ht); } else if (edge->type == EDGE_TYPE_PUMP) { pump = &edge->pump; flow = Flow_Pump(pump,hf,ht); } /* Convention: Node 1 has outgoing flow and Node 2 has incoming flow */ if (vertexnode1->type == VERTEX_TYPE_JUNCTION) farr[offsetnode1] -= flow; if (vertexnode2->type == VERTEX_TYPE_JUNCTION) farr[offsetnode2] += flow; } /* Subtract Demand flows at the vertices */ for (i=0; i<nv; i++) { ierr = DMNetworkIsGhostVertex(networkdm,vtx[i],&ghostvtex);CHKERRQ(ierr); if(ghostvtex) continue; ierr = DMNetworkGetVariableOffset(networkdm,vtx[i],&offset);CHKERRQ(ierr); ierr = DMNetworkGetComponent(networkdm,vtx[i],0,&key,(void**)&vertex);CHKERRQ(ierr); if (vertex->type == VERTEX_TYPE_JUNCTION) { farr[offset] -= vertex->junc.demand; } else if (vertex->type == VERTEX_TYPE_RESERVOIR) { reservoir = &vertex->res; farr[offset] = xarr[offset] - reservoir->head; } else if(vertex->type == VERTEX_TYPE_TANK) { tank = &vertex->tank; farr[offset] = xarr[offset] - (tank->elev + tank->initlvl); } } ierr = VecRestoreArrayRead(localX,&xarr);CHKERRQ(ierr); ierr = VecRestoreArray(localF,&farr);CHKERRQ(ierr); PetscFunctionReturn(0); }