EPANET中讀取INPUT文件的函數文件——INPUT3.C

   1 /*
   2 **********************************************************************
   3 
   4 INPUT3.C -- Input data parser for EPANET;
   5 
   6 VERSION:    2.00
   7 DATE:       5/30/00
   8             9/7/00
   9             10/25/00
  10             3/1/01
  11             6/24/02
  12             8/15/07    (2.00.11)
  13             2/14/08    (2.00.12)
  14 AUTHOR:     L. Rossman
  15             US EPA - NRMRL
  16 
  17 This module parses data from each line of input from file InFile.
  18 All functions in this module are called from newline() in INPUT2.C.
  19 該模塊逐行解析INPUT文件。
  20 該模塊中的全部函數都在INPUT2.C的newline(int sect, char *line)中被調用。
  21 
  22 同時該模塊也調用了INPUT2.C中的部分工具函數:addlinkID(int n, char *id)、addnodeID(int n, char *id)、addpattern(char *id)、
  23 addcurve(char *id)、*findID(char *id, STmplist *list)、match(char *str, char *substr)、hour(char *time, char *units)等
  24 
  25 **********************************************************************
  26 */
  27 
  28 #include <stdlib.h>
  29 #include <stdio.h>
  30 #include <string.h>
  31 #include <malloc.h>
  32 #include <math.h>
  33 #include "hash.h"
  34 #include "text.h"
  35 #include "types.h"
  36 #include "funcs.h"
  37 #define  EXTERN  extern
  38 #include "vars.h"
  39 
  40 /* Defined in enumstxt.h in EPANET.C */
  41 extern char *MixTxt[];
  42 extern char *Fldname[];            //字段名稱字符串數組
  43 
  44 /* Defined in INPUT2.C */
  45 extern char      *Tok[MAXTOKS];    /* Array of token strings            ;每一輸入行的項數組成的字符串數組*/
  46 extern STmplist  *PrevPat;         /* Pointer to pattern list element   ;指向模式的最近一個指針*/
  47 extern STmplist  *PrevCurve;       /* Pointer to curve list element     ;指向曲線的最近一個指針*/
  48 extern int       Ntokens;          /* Number of tokens in input line    ;每一輸入行的項數(項與項之間的分隔形式是:)*/
  49 
  50 
  51 int  juncdata()
  52 /*
  53 **--------------------------------------------------------------
  54 **  Input:   none                            ;輸入:無                    
  55 **  Output:  returns error code              ;輸出:錯誤編碼                    
  56 **  Purpose: processes junction data         ;做用:處理節點數據                    
  57 **  Format:                                  ;格式:                    
  58 **    [JUNCTIONS]                                              
  59 **      id  elev.  (demand)  (demand pattern)            數據項的列表      
  60 **--------------------------------------------------------------
  61 */
  62 {
  63    int      n, p = 0;//n表明待解析行中的數據項的個數;p表明該節點的用水模式鏈表中的index值;
  64    double    el,y = 0.0;//el表示該節點的高程值;y表示該節點的用水量值
  65    Pdemand  demand;//當該節點存在多個用水量及對應的用水模式曲線時,使用該變量保存
  66    STmplist *pat;
  67 
  68 /* Add new junction to data base ;增長一個新的節點數據*/
  69    n = Ntokens;
  70    if (Nnodes == MaxNodes) return(200);
  71    Njuncs++;
  72    Nnodes++;
  73    if (!addnodeID(Njuncs,Tok[0])) return(215);
  74 
  75 /* Check for valid data ;檢查該數據的正確性*/
  76    if (n < 2) return(201);//不存在高程信息
  77    if (!getfloat(Tok[1],&el)) return(202);//高程信息數據類型非法
  78    if (n >= 3  && !getfloat(Tok[2],&y)) return(202);//若需水量存在且需水量數據類型非法
  79    if (n >= 4)
  80    {
  81       pat = findID(Tok[3],Patlist);
  82       if (pat == NULL) return(205);
  83       p = pat->i;
  84    }
  85 
  86 /* Save junction data ;將節點的高程等信息保存下來*/
  87    Node[Njuncs].El  = el;
  88    Node[Njuncs].C0  = 0.0;
  89    Node[Njuncs].S   = NULL;
  90    Node[Njuncs].Ke  = 0.0;
  91    Node[Njuncs].Rpt = 0;
  92 
  93 /* Create a new demand record ;一個節點有一個指向該節點所掛的需水量指針D,將讀入的水量及模式掛接到D的鏈首*/
  94 /*** Updated 6/24/02 ***/
  95    if (n >= 3)
  96    {
  97       demand = (struct Sdemand *) malloc(sizeof(struct Sdemand));
  98       if (demand == NULL) return(101);
  99       demand->Base = y;
 100       demand->Pat = p;
 101       demand->next = Node[Njuncs].D;
 102       Node[Njuncs].D = demand;
 103       D[Njuncs] = y;//全局變量中的節點實際需水量
 104    }
 105    else D[Njuncs] = MISSING;   //標記該節點暫無以Junction節點中分配水量,若是Demand中有對該節點分水量,那麼也標記爲MISSING
 106 /*** end of update ***/
 107    return(0);
 108 }                        /* end of juncdata */
 109 
 110 
 111 int  tankdata()
 112 /*
 113 **--------------------------------------------------------------
 114 **  Input:   none                                              ;輸入:無
 115 **  Output:  returns error code                                ;輸出:錯誤代碼
 116 **  Purpose: processes tank & reservoir data                   ;做用:處理水塔和水池(水庫)數據
 117 **  Format:                                                    ;格式:
 118 **   [RESERVOIRS]                                              
 119 **     id elev (pattern)                                     
 120 **   [TANKS]                                                 
 121 **     id elev (pattern)                                     
 122 **     id elev initlevel minlevel maxlevel diam (minvol vcurve)         
 123 **--------------------------------------------------------------
 124 */
 125 {
 126    int   i,               /* Node index Node中的索引值*/
 127          n,               /* # data items 該數據行的數據項數 */
 128          p = 0,           /* Fixed grade time pattern index 時間模式中的索引值 */
 129          vcurve = 0;      /* Volume curve index 容積曲線的索引值*/
 130    double el        = 0.0, /* Elevation 高程值*/
 131          initlevel = 0.0, /* Initial level 初始水面高程*/
 132          minlevel  = 0.0, /* Minimum level 最小水池高程*/
 133          maxlevel  = 0.0, /* Maximum level 最大水池高程*/
 134          minvol    = 0.0, /* Minimum volume 最小容積*/
 135          diam      = 0.0, /* Diameter 口徑*/
 136          area;            /* X-sect. area 橫截面面積*/
 137    STmplist *t;
 138 
 139 /* Add new tank to data base 添加新的水塔數據*/
 140    n = Ntokens;
 141    if (Ntanks == MaxTanks
 142    ||  Nnodes == MaxNodes) return(200);
 143    Ntanks++;
 144    Nnodes++;
 145    i = MaxJuncs + Ntanks;                    /* i = node index.   i是水塔在Node中的索引  */
 146    if (!addnodeID(i,Tok[0])) return(215);    /* Add ID to database. 將"ID標識"及其Node的索引值添加到節點哈希表中*/
 147 
 148 /* Check for valid data 檢查數據的合法性*/
 149    if (n < 2) return(201);                   /* Too few fields.   字段個數過少,至少包含id與高程值*/
 150    if (!getfloat(Tok[1],&el)) return(202);   /* Read elevation    高程值沒法轉成數值型*/
 151    if (n <= 3)                               /* Tank is reservoir.水池是特殊的水塔,若是數據項小於3項,則將水塔認爲爲水庫*/
 152    {
 153       if (n == 3)                            /* Pattern supplied  找到指定時間模式值的索引值*/
 154       {
 155          t = findID(Tok[2],Patlist);
 156          if (t == NULL) return(205);
 157          p = t->i;
 158       }
 159    }
 160    else if (n < 6) return(201);              /* Too few fields for tank.水塔須要的字段數不能少於6個*/
 161    else
 162    {
 163       /* Check for valid input data 檢查水塔數據的正確性,進行類型檢查*/
 164       if (!getfloat(Tok[2],&initlevel)) return(202);
 165       if (!getfloat(Tok[3],&minlevel))  return(202);
 166       if (!getfloat(Tok[4],&maxlevel))  return(202);
 167       if (!getfloat(Tok[5],&diam))      return(202);
 168       if (diam < 0.0)                   return(202);//口徑非負檢查
 169       if (n >= 7
 170       && !getfloat(Tok[6],&minvol))     return(202);
 171 
 172       /* If volume curve supplied check it exists 若是容積曲線存在,則對容積曲線進行存在性檢查,若存在返回索引值*/
 173       if (n == 8)
 174       {                           
 175          t = findID(Tok[7],Curvelist);
 176          if (t == NULL) return(202);
 177          vcurve = t->i;
 178       }
 179    }
 180 
 181    Node[i].Rpt           = 0;
 182    Node[i].El            = el;               /* Elevation.           */
 183    Node[i].C0            = 0.0;              /* Init. quality.       */
 184    Node[i].S             = NULL;             /* WQ source data       */     
 185    Node[i].Ke            = 0.0;              /* Emitter coeff.       */
 186    Tank[Ntanks].Node     = i;                /* Node index.          */
 187    Tank[Ntanks].H0       = initlevel;        /* Init. level.         */
 188    Tank[Ntanks].Hmin     = minlevel;         /* Min. level.          */
 189    Tank[Ntanks].Hmax     = maxlevel;         /* Max level.           */
 190    Tank[Ntanks].A        = diam;             /* Diameter.            */
 191    Tank[Ntanks].Pat      = p;                /* Fixed grade pattern. */
 192    Tank[Ntanks].Kb       = MISSING;          /* Reaction coeff.      */
 193    /*
 194    *******************************************************************
 195     NOTE: The min, max, & initial volumes set here are based on a     
 196        nominal tank diameter. They will be modified in INPUT1.C if    
 197        a volume curve is supplied for this tank. 
 198        這裏的最小、最大和初始容積的計算是基於水塔的口徑來的。
 199        它們會在INPUT1.C文件中被修改,若是這個水塔存在一個容積曲線。
 200    *******************************************************************
 201    */
 202    area = PI*SQR(diam)/4.0;//橫截面積
 203    Tank[Ntanks].Vmin = area*minlevel;//最小容積
 204    if (minvol > 0.0) Tank[Ntanks].Vmin = minvol;
 205    Tank[Ntanks].V0 = Tank[Ntanks].Vmin + area*(initlevel - minlevel);
 206    Tank[Ntanks].Vmax = Tank[Ntanks].Vmin + area*(maxlevel - minlevel);//最大容積
 207 
 208    Tank[Ntanks].Vcurve   = vcurve;           /* Volume curve         容積曲線索引值*/
 209    Tank[Ntanks].MixModel = MIX1;             /* Completely mixed     水池出水模式*/
 210    Tank[Ntanks].V1max    = 1.0;              /* Compart. size ratio  */
 211    return(0);
 212 }                        /* end of tankdata */
 213 
 214 
 215 int  pipedata()
 216 /*
 217 **--------------------------------------------------------------
 218 **  Input:   none                                              ;輸入:無
 219 **  Output:  returns error code                                ;輸出:錯誤代碼
 220 **  Purpose: processes pipe data                               :做用:處理管段數據
 221 **  Format:                                                    ;格式:狀態能夠不須要,默認都是OPEN
 222 **    [PIPE]                                                
 223 **    id  node1  node2  length  diam  rcoeff (lcoeff) (status)          
 224 **--------------------------------------------------------------
 225 */
 226 {
 227    int   j1,                     /* Start-node index  起始junction在Node鏈表中的索引值*/
 228          j2,                     /* End-node index    終點junction在Node鏈表中的索引值*/
 229          n;                      /* # data items      當前行數據項個數*/
 230    char  type = PIPE,            /* Link type         管段類型,默認爲Pipe*/
 231          status = OPEN;          /* Link status       管段狀態(OPEN, CLOSED或CV),默認是開啓狀態*/
 232    double length,                /* Link length       管長*/
 233          diam,                   /* Link diameter     管徑*/
 234          rcoeff,                 /* Roughness coeff.  粗糙係數*/
 235          lcoeff = 0.0;           /* Minor loss coeff. 局部損失係數*/
 236 
 237 /* Add new pipe to data base 將新管段添加進來*/
 238    n = Ntokens;
 239    if (Nlinks == MaxLinks) return(200);
 240    Npipes++;
 241    Nlinks++;
 242    if (!addlinkID(Nlinks,Tok[0])) return(215);
 243 
 244 /* Check for valid data 檢查管段數據的正確性*/
 245    if (n < 6) return(201);              //數據項個數至少有6個
 246    if ((j1 = findnode(Tok[1])) == 0 ||  //獲取始末點的索引值   
 247        (j2 = findnode(Tok[2])) == 0
 248       ) return(203);
 249 
 250 /*** Updated 10/25/00 ***/
 251    if (j1 == j2) return(222);           //若是起點與終點相同則返回出錯信息
 252 
 253    if (!getfloat(Tok[3],&length) ||     //進行長度、口徑、粗糙係數的數據類型檢查
 254        !getfloat(Tok[4],&diam)   ||     
 255        !getfloat(Tok[5],&rcoeff)        
 256       ) return(202);
 257 
 258    if (length <= 0.0 ||                 //進行長度、口徑、粗糙係數的數據的非負檢查
 259        diam   <= 0.0 ||
 260        rcoeff <= 0.0
 261       ) return(202);
 262 
 263    /* Case where either loss coeff. or status supplied 獲取局部損失係數或者狀態*/
 264    if (n == 7)
 265    {
 266       if      (match(Tok[6],w_CV))        type = CV;
 267       else if (match(Tok[6],w_CLOSED))    status = CLOSED;
 268       else if (match(Tok[6],w_OPEN))      status = OPEN;
 269       else if (!getfloat(Tok[6],&lcoeff)) return(202);
 270    }
 271 
 272    /* Case where both loss coeff. and status supplied 獲取局部損失係數和狀態*/
 273    if (n == 8)
 274    {
 275       if (!getfloat(Tok[6],&lcoeff))   return(202);
 276       if      (match(Tok[7],w_CV))     type = CV;
 277       else if (match(Tok[7],w_CLOSED)) status = CLOSED;
 278       else if (match(Tok[7],w_OPEN))   status = OPEN;
 279       else return(202);
 280    }
 281    if (lcoeff < 0.0) return(202);
 282 
 283 /* Save pipe data 保存該管段的數據*/
 284    Link[Nlinks].N1    = j1;                  /* Start-node index */
 285    Link[Nlinks].N2    = j2;                  /* End-node index   */
 286    Link[Nlinks].Len   = length;              /* Length           */
 287    Link[Nlinks].Diam  = diam;                /* Diameter         */
 288    Link[Nlinks].Kc    = rcoeff;              /* Rough. coeff     */
 289    Link[Nlinks].Km    = lcoeff;              /* Loss coeff       */
 290    Link[Nlinks].Kb    = MISSING;             /* Bulk coeff       */
 291    Link[Nlinks].Kw    = MISSING;             /* Wall coeff       */
 292    Link[Nlinks].Type  = type;                /* Link type        */
 293    Link[Nlinks].Stat  = status;              /* Link status      */
 294    Link[Nlinks].Rpt   = 0;                   /* Report flag      */
 295    return(0);
 296 }                        /* end of pipedata */
 297 
 298 
 299 int  pumpdata()
 300 /*
 301 **--------------------------------------------------------------;備註:水泵被認爲是特殊的管段數據
 302 ** Input:   none                                                ;輸入:無 
 303 ** Output:  returns error code                                  ;輸出:錯誤代碼
 304 ** Purpose: processes pump data                                 ;目的:處理水泵數據
 305 ** Formats:                                                     ;格式:
 306 **  [PUMP]                                                     
 307 **   (Version 1.x Format):                                              
 308 **   id  node1  node2  power                                   
 309 **   id  node1  node2  h1    q1                                
 310 **   id  node1  node2  h0    h1   q1   h2   q2                 
 311 **   (Version 2 Format):                                              
 312 **   id  node1  node2  KEYWORD value {KEYWORD value ...}       
 313 **   where KEYWORD = [POWER,HEAD,PATTERN,SPEED]            
 314 ;ID                  Node1               Node2               Parameters
 315  9                   9                   10                  HEAD 1    ;
 316 **--------------------------------------------------------------
 317 */
 318 {
 319    int   j,
 320          j1,                    /* Start-node index 起始junction在Node鏈表中的索引值*/
 321          j2,                    /* End-node index   終點junction在Node鏈表中的索引值*/
 322          m, n;                  /* # data items     當前行數據項個數*/
 323    double y;
 324    STmplist *t;                 /* Pattern record   */
 325 
 326 /* Add new pump to data base 將新水泵數據添加進來*/
 327    n = Ntokens;
 328    if (Nlinks == MaxLinks ||
 329        Npumps == MaxPumps
 330       ) return(200);
 331    Nlinks++;
 332    Npumps++;
 333    if (!addlinkID(Nlinks,Tok[0])) return(215);
 334 
 335 /* Check for valid data 檢查數據合法性*/
 336    if (n < 4) return(201);                    //字段個數至少4個
 337    if ((j1 = findnode(Tok[1])) == 0 ||        //獲取始末junction在Node鏈表中的索引值
 338        (j2 = findnode(Tok[2])) == 0
 339       ) return(203);
 340 
 341 /*** Updated 10/25/00 ***/
 342    if (j1 == j2) return(222);                 //若是起點與終點相同則返回出錯信息
 343 
 344 /* Save pump data 保存水泵數據*/
 345    Link[Nlinks].N1    = j1;               /* Start-node index.  */
 346    Link[Nlinks].N2    = j2;               /* End-node index.    */
 347    Link[Nlinks].Diam  = Npumps;           /* Pump index.        */
 348    Link[Nlinks].Len   = 0.0;              /* Link length.       */
 349    Link[Nlinks].Kc    = 1.0;              /* Speed factor.      */
 350    Link[Nlinks].Km    = 0.0;              /* Horsepower.        */
 351    Link[Nlinks].Kb    = 0.0;
 352    Link[Nlinks].Kw    = 0.0;
 353    Link[Nlinks].Type  = PUMP;             /* Link type.         */
 354    Link[Nlinks].Stat  = OPEN;             /* Link status.       */
 355    Link[Nlinks].Rpt   = 0;                /* Report flag.       */
 356    Pump[Npumps].Link = Nlinks;            /* Link index.        */
 357    Pump[Npumps].Ptype = NOCURVE;          /* Type of pump curve 默認無水泵曲線*/
 358    Pump[Npumps].Hcurve = 0;               /* Pump curve index   */
 359    Pump[Npumps].Ecurve = 0;               /* Effic. curve index */
 360    Pump[Npumps].Upat   = 0;               /* Utilization pattern*/
 361    Pump[Npumps].Ecost  = 0.0;             /* Unit energy cost   */
 362    Pump[Npumps].Epat   = 0;               /* Energy cost pattern*/
 363 
 364 /* If 4-th token is a number then input follows Version 1.x format 若第4個數據項是一個數字則按版本1.x來解讀水泵曲線*/
 365 /* so retrieve pump curve parameters 獲取水泵參數曲線;通常如今都是按2.x版本,因此能夠跳過不作細究*/
 366    if (getfloat(Tok[3],&X[0]))
 367    {
 368       m = 1;
 369       for (j=4; j<n; j++)
 370       {
 371          if (!getfloat(Tok[j],&X[m])) return(202);
 372          m++;
 373       }
 374       return(getpumpcurve(m));          /* Get pump curve params */
 375    }
 376 
 377 /* Otherwise input follows Version 2 format */
 378 /* so retrieve keyword/value pairs.         版本2是採用鍵值對的方式來定義水泵曲線*/
 379 /*
 380     關鍵詞和數值(能夠重複)
 381 a.  關鍵詞包括: 
 382 * POWER——定速能量水泵的功率數值,hp (kW) 
 383 * HEAD——描述了水泵揚程與流量關係的曲線ID 
 384 * SPEED——相對速度設置(額定速度爲1.0 ,0意味着水泵關閉) 
 385 * PATTERN——時間模式的ID,描述了速度設置怎樣隨時間變化 
 386 b.  對於每一臺水泵,必須提供POWER 或者HEAD。其它關鍵詞是可選的。 
 387 */
 388    m = 4;
 389    while (m < n)
 390    {
 391       if (match(Tok[m-1],w_POWER))          /* Const. HP curve       定速能量水泵的功率數值,hp (kW)*/
 392       {
 393          y = atof(Tok[m]);
 394          if (y <= 0.0) return(202);
 395          Pump[Npumps].Ptype = CONST_HP;    //水泵曲線類型
 396          Link[Nlinks].Km = y;              //Minor loss coeff. 局部損失係數
 397       }
 398       else if (match(Tok[m-1],w_HEAD))      /* Custom pump curve      描述了水泵揚程與流量關係的曲線ID*/
 399       {
 400          t = findID(Tok[m],Curvelist);
 401          if (t == NULL) return(206);
 402          Pump[Npumps].Hcurve = t->i;
 403       }
 404       else if (match(Tok[m-1],w_PATTERN))   /* Speed/status pattern 時間模式的ID,描述了速度設置怎樣隨時間變化 */
 405       {
 406          t = findID(Tok[m],Patlist);
 407          if (t == NULL) return(205);
 408          Pump[Npumps].Upat = t->i;
 409       }
 410       else if (match(Tok[m-1],w_SPEED))     /* Speed setting 相對速度設置(額定速度爲1.0 ,0意味着水泵關閉)*/
 411       {
 412          if (!getfloat(Tok[m],&y)) return(202);
 413          if (y < 0.0) return(202); 
 414          Link[Nlinks].Kc = y;
 415       }
 416       else return(201);
 417       m = m + 2;                          /* Skip to next keyword token 鍵值對都是2個一組的,能夠重複*/
 418    }
 419    return(0);
 420 }                        /* end of pumpdata */
 421 
 422 
 423 int  valvedata()
 424 /*
 425 **--------------------------------------------------------------
 426 **  Input:   none                                                ;輸入:無 
 427 **  Output:  returns error code                                  ;輸出:錯誤代碼
 428 **  Purpose: processes valve data                                ;做用:處理閥門數據
 429 **  Format:                                                      ;格式:
 430 **     [VALVE]                                                   
 431 **        id  node1  node2  diam  type  setting (lcoeff)       
 432 **--------------------------------------------------------------
 433 */
 434 {
 435    int   j1,                    /* Start-node index   起始junction在Node鏈表中的索引值*/
 436          j2,                    /* End-node index     終點junction在Node鏈表中的索引值*/
 437          n;                     /* # data items       當前行數據項個數*/
 438    char  status = ACTIVE,       /* Valve status       閥門狀態*/
 439          type;                  /* Valve type         閥門類型*/
 440    double diam = 0.0,           /* Valve diameter     閥門口徑*/
 441          setting,               /* Valve setting      閥門設置*/
 442          lcoeff = 0.0;          /* Minor loss coeff.  局部損失係數*/
 443    STmplist *t;                 /* Curve record       閥門曲線*/
 444 
 445 /* Add new valve to data base 添加閥門數據*/
 446    n = Ntokens;
 447    if (Nlinks == MaxLinks ||
 448        Nvalves == MaxValves
 449       ) return(200);
 450    Nvalves++;
 451    Nlinks++;
 452    if (!addlinkID(Nlinks,Tok[0])) return(215);
 453 
 454 /* Check for valid data 檢查閥門數據的合法性*/
 455    if (n < 6) return(201);                            //至少須要6個字段,第7個字段"局部損失係數"可選
 456    if ((j1 = findnode(Tok[1])) == 0 ||                
 457        (j2 = findnode(Tok[2])) == 0
 458       ) return(203);
 459 
 460 /*** Updated 10/25/00 ***/
 461    if (j1 == j2) return(222);                    //起點與終點相同,返回錯誤代碼
 462 //獲取閥門類型                              閥門                              設置
 463    if      (match(Tok[4],w_PRV)) type = PRV;//PRV (減壓閥)                    壓力,m(psi) 
 464    else if (match(Tok[4],w_PSV)) type = PSV;//PSV  (穩壓閥)                        壓力,m(psi)
 465    else if (match(Tok[4],w_PBV)) type = PBV;//PBV (壓力制動閥)                壓力,m(psi)
 466    else if (match(Tok[4],w_FCV)) type = FCV;//FCV (流量控制閥)                流量(流量單位)
 467    else if (match(Tok[4],w_TCV)) type = TCV;//TCV (節流控制閥)                損失係數
 468    else if (match(Tok[4],w_GPV)) type = GPV;//GPV (常規閥門)                  水頭損失曲線的ID 
 469    else    return(201);                      /* Illegal valve type.*/
 470    if (!getfloat(Tok[3],&diam)) return(202);
 471    if (diam <= 0.0) return(202);             /* Illegal diameter.*/
 472    if (type == GPV)                          /* Headloss curve for GPV 獲取水頭損失曲線ID在曲線表中的索引值*/
 473    {
 474       t = findID(Tok[5],Curvelist);
 475       if (t == NULL) return(206);
 476       setting = t->i;
 477 
 478 /*** Updated 9/7/00 ***/
 479       status = OPEN;                        //閥門狀態設置爲開啓
 480 
 481    }
 482    else if (!getfloat(Tok[5],&setting)) return(202);
 483    if (n >= 7 &&                           //獲取
 484        !getfloat(Tok[6],&lcoeff)
 485       ) return(202);
 486 
 487 /* Check that PRV, PSV, or FCV not connected to a tank & */
 488 /* check for illegal connections between pairs of valves.*/
 489    if ((j1 > Njuncs || j2 > Njuncs) &&
 490        (type == PRV || type == PSV || type == FCV)
 491       ) return(219);
 492    if (!valvecheck(type,j1,j2)) return(220);
 493 
 494 /* Save valve data 設置閥門數據,注意閥門是特殊的管段數據*/
 495    Link[Nlinks].N1     = j1;                 /* Start-node index. 設置起始節點索引值*/
 496    Link[Nlinks].N2     = j2;                 /* End-node index.   設置終點節點索引值*/
 497    Link[Nlinks].Diam   = diam;               /* Valve diameter.   閥門口徑*/
 498    Link[Nlinks].Len    = 0.0;                /* Link length.      */
 499    Link[Nlinks].Kc     = setting;            /* Valve setting.    */
 500    Link[Nlinks].Km     = lcoeff;             /* Loss coeff        */
 501    Link[Nlinks].Kb     = 0.0;
 502    Link[Nlinks].Kw     = 0.0;
 503    Link[Nlinks].Type   = type;               /* Valve type.       */
 504    Link[Nlinks].Stat   = status;             /* Valve status.     */
 505    Link[Nlinks].Rpt    = 0;                  /* Report flag.      */
 506    Valve[Nvalves].Link = Nlinks;             /* Link index.       */
 507    return(0);
 508 }                        /* end of valvedata */
 509 
 510 
 511 int  patterndata()
 512 /*
 513 **--------------------------------------------------------------
 514 **  Input:   none                                                ;輸入:無 
 515 **  Output:  returns error code                                  ;輸出:錯誤代碼
 516 **  Purpose: processes time pattern data                         ;做用:處理時間模式數據
 517 **  Format:                                                      ;格式:
 518 **     [PATTERNS]                                                這讓我回想起當時Hammer中導出的INP文件解算時只有前面幾個時段的數據,極可能的一個緣由就是EPANET對INP文件的規範是每行最多40項,而Hammer的Pattern格式長度過長致使的。
 519 **        id  mult1  mult2 .....                               
 520 **--------------------------------------------------------------
 521 */
 522 {
 523    int  i,n;                       /*n表示 當前行數據項個數*/
 524    double x;
 525    SFloatlist *f;                  //f:一個包含浮點數的單向鏈表                        
 526    STmplist   *p;                  //p:當前的用水模式
 527    n = Ntokens - 1;
 528    if (n < 1) return(201);            /* Too few values        當前行數據項個數過少*/
 529    if (                               /* Check for new pattern 查看當前行的ID是否存在於PrevPat鏈表中*/
 530           PrevPat != NULL &&          /*這裏的if語句的做用在於一個時間模式多是鏈接多行,那麼這樣就能提升效率*/
 531           strcmp(Tok[0],PrevPat->ID) == 0
 532       ) p = PrevPat;
 533    else p = findID(Tok[0],Patlist);
 534    if (p == NULL) return(205);
 535    for (i=1; i<=n; i++)               /* Add multipliers to list 添加用水模式係數,添加至鏈首*/
 536    {
 537        if (!getfloat(Tok[i],&x)) return(202);
 538        f = (SFloatlist *) malloc(sizeof(SFloatlist));
 539        if (f == NULL) return(101);
 540        f->value = x;
 541        f->next = p->x;               //將當前係數掛在該模式p的係數鏈首
 542        p->x = f;
 543    }
 544    Pattern[p->i].Length += n;         /* Save # multipliers for pattern 維護當前模式的長度*/
 545    PrevPat = p;                       /* Set previous pattern pointer 臨時的模式對象,因模式多是連着多行而提升效率*/
 546    return(0);
 547 }                        /* end of patterndata */
 548 
 549 
 550 int  curvedata()
 551 /*
 552 **------------------------------------------------------
 553 **  Input:   none                                       ;輸入:無
 554 **  Output:  returns error code                         ;輸出:錯誤代碼
 555 **  Purpose: processes curve data                       ;做用:處理曲線數據 
 556 **  Format:                                             ;格式: 
 557 **     [CURVES]                                        
 558 **      CurveID   x-value  y-value                    
 559 **------------------------------------------------------
 560 */
 561 {
 562    double      x,y;
 563    SFloatlist *fx, *fy;
 564    STmplist   *c;
 565 
 566    /* Check for valid curve ID */
 567    if (Ntokens < 3) return(201);
 568    if (
 569           PrevCurve != NULL &&
 570           strcmp(Tok[0],PrevCurve->ID) == 0
 571       ) c = PrevCurve;
 572    else c = findID(Tok[0],Curvelist);
 573    if (c == NULL) return(205);
 574 
 575    /* Check for valid data */
 576    if (!getfloat(Tok[1],&x)) return(202);
 577    if (!getfloat(Tok[2],&y)) return(202);
 578 
 579    /* Add new data point to curve's linked list */
 580    fx = (SFloatlist *) malloc(sizeof(SFloatlist));
 581    fy = (SFloatlist *) malloc(sizeof(SFloatlist));
 582    if (fx == NULL || fy == NULL) return(101);
 583    fx->value = x;
 584    fx->next = c->x;
 585    c->x = fx;
 586    fy->value = y;
 587    fy->next = c->y;
 588    c->y = fy;
 589    Curve[c->i].Npts++;
 590 
 591    /* Save the pointer to this curve */
 592    PrevCurve = c;
 593    return(0);
 594 }
 595 
 596 
 597 int  demanddata()
 598 /*
 599 **--------------------------------------------------------------
 600 **  Input:   none                                                ;輸入:無 
 601 **  Output:  returns error code                                  ;輸出:錯誤代碼
 602 **  Purpose: processes node demand data                          ;做用:定義鏈接節點的多模式需水,是對[JUNCTIONS]的補充。 
 603 **  Format:                                                      ;格式:
 604 **     [DEMANDS]                                               
 605 **        MULTIPLY  factor                                     
 606 **        node  base_demand  (pattern)                         
 607 **
 608 **  NOTE: Demands entered in this section replace those          ;注意:這部分的需水量將替換[JUNCTIONS]部分錄入的需水量
 609 **        entered in the [JUNCTIONS] section
 610 **--------------------------------------------------------------
 611 */
 612 {                                       //j:表示節點在Node中的索引值
 613    int  j,n,p = 0;                      //p:當前的用水模式在Pattern中的索引  /*n表示 當前行數據項個數*/
 614    double y;         
 615    Pdemand demand;
 616    STmplist *pat;
 617 
 618 /* Extract data from tokens 從當前行中提取需水量數據*/
 619    n = Ntokens;
 620    if (n < 2) return(201); 
 621    if (!getfloat(Tok[1],&y)) return(202);
 622 
 623 /* If MULTIPLY command, save multiplier */
 624    if (match(Tok[0],w_MULTIPLY))
 625    {
 626       if (y <= 0.0) return(202);
 627       else Dmult = y;
 628       return(0);
 629    }
 630 
 631 /* Otherwise find node (and pattern) being referenced 找到節點所引用的用水模式的索引值*/
 632    if ((j = findnode(Tok[0])) == 0) return(208);
 633    if (j > Njuncs) return(208);
 634    if (n >= 3)
 635    {
 636       pat = findID(Tok[2],Patlist);
 637       if (pat == NULL)  return(205);
 638       p = pat->i;
 639    }
 640 
 641 /* Replace any demand entered in [JUNCTIONS] section */
 642 /* (Such demand was temporarily stored in D[]) */
 643 
 644 /*** Updated 6/24/02 ***/
 645    demand = Node[j].D;
 646    if (demand && D[j] != MISSING)
 647    {
 648       demand->Base = y;
 649       demand->Pat  = p;
 650       D[j] = MISSING;//經過這個MISSING來作替換標記
 651    }
 652 /*** End of update ***/
 653 
 654 /* Otherwise add a new demand to this junction */
 655    else
 656    {
 657       demand = (struct Sdemand *) malloc(sizeof(struct Sdemand));
 658       if (demand == NULL) return(101);
 659       demand->Base = y;
 660       demand->Pat = p;
 661       demand->next = Node[j].D;
 662       Node[j].D = demand;
 663    }
 664    return(0);
 665 }                        /* end of demanddata */
 666 
 667 
 668 int  controldata()
 669 /*
 670 **--------------------------------------------------------------
 671 **  Input:   none                                                ;輸入:無
 672 **  Output:  returns error code                                  ;輸出:錯誤代碼
 673 **  Purpose: processes simple controls                           ;做用:處理簡單控制規則
 674 **  Formats:                                                     ;格式:
 675 **  [CONTROLS]                                                 
 676 **  LINK  linkID  setting IF NODE      nodeID {BELOW/ABOVE}  value 
 677 **  LINK  linkID  setting AT TIME      time  (units)               
 678 **  LINK  linkID  setting AT CLOCKTIME clocktime  (units)           
 679 **   (0)   (1)      (2)   (3) (4)       (5)     (6)          (7)
 680 其中: 
 681 linkID——管段ID標籤; 
 682 setting——OPEN或者CLOSED,水泵速度設置或者控制閥門設置 
 683 nodeID——節點ID標籤; 
 684 value ——鏈接節點壓力或者水池水位; 
 685 time——從模擬開始起算的時間,以小數或者小時:分鐘計; 
 686 clocktime——24小時的鐘表時間(小時:分鐘)。 
 687 備註: 
 688 a.  簡單控制將根據水池水位、節點壓強、進入模擬時間或者一日中的時間,改變管
 689 段狀態或者設置。 
 690 b.  對於用在指定管段狀態和設置的常規狀況,尤爲閥門控制,參見[STATUS] 節的
 691 備註。
 692 示例: 
 693 [CONTROLS] 
 694 ;若是Tank 23的水位超過20 ft ,關閉Link 
 695 LINK 12 CLOSED IF NODE 23 ABOVE 20 
 696  
 697 ;若是Node 130 的壓力低於30 psi,開啓Link 12 
 698 LINK 12 OPEN IF NODE 130 BELOW 30 
 699  
 700 ;在進入模擬16小時後水泵PUMP02的轉速比設置爲1.5 
 701 LINK PUMP02 1.5 AT TIME 16 
 702  
 703 ;整個模擬過程當中Lin 12在上午10時關閉,下午8時開啓 
 704 LINK 12 CLOSED AT CLOCKTIME 10 AM 
 705 LINK 12 OPEN AT CLOCKTIME 8 PM
 706 **--------------------------------------------------------------
 707 */
 708 {
 709    int   i = 0,                /* Node index             Node中的索引值*/
 710          k,                    /* Link index             Link中的索引值*/
 711          n;                    /* # data items           當前行數據項個數*/
 712    char  status = ACTIVE,      /* Link status            管段狀態*/
 713          type;                 /* Link or control type   管段類型*/
 714    double setting = MISSING,    /* Link setting           */
 715          time = 0.0,           /* Simulation time        從模擬開始起算的時間*/
 716          level = 0.0;          /* Pressure or tank level 水池水位或節點壓強*/
 717 
 718 /* Check for sufficient number of input tokens 檢查字段個數是否合法,不小於6個*/
 719    n = Ntokens;
 720    if (n < 6) return(201);
 721 
 722 /* Check that controlled link exists 判斷控制的管段是否存在*/
 723    k = findlink(Tok[1]);
 724    if (k == 0) return(204);
 725    type = Link[k].Type;
 726    if (type == CV) return(207);         /* Cannot control check valve. 不可以控制檢查閥*/
 727 
 728 /*** Updated 9/7/00 ***/
 729 /* Parse control setting into a status level or numerical setting. 獲取並設置控制管段的狀態*/
 730    if (match(Tok[2],w_OPEN))
 731    {
 732       status = OPEN;
 733       if (type == PUMP) setting = 1.0;
 734       if (type == GPV)  setting = Link[k].Kc;
 735    }
 736    else if (match(Tok[2],w_CLOSED))
 737    {
 738       status = CLOSED;
 739       if (type == PUMP) setting = 0.0;
 740       if (type == GPV)  setting = Link[k].Kc;
 741    }
 742    else if (type == GPV) return(206);
 743    else if (!getfloat(Tok[2],&setting)) return(202);
 744 
 745 /*** Updated 3/1/01 ***/
 746 /* Set status for pump in case speed setting was supplied 根據setting來設置水泵或者管段的status*/
 747 /* or for pipe if numerical setting was supplied */
 748 
 749    if (type == PUMP || type == PIPE)
 750    {
 751       if (setting != MISSING)
 752       {
 753          if (setting < 0.0)       return(202);
 754          else if (setting == 0.0) status = CLOSED;
 755          else                     status = OPEN;
 756       }
 757    }
 758 
 759 /* Determine type of control 獲取該條控制規則的類型*/
 760    if      (match(Tok[4],w_TIME))      type = TIMER;
 761    else if (match(Tok[4],w_CLOCKTIME)) type = TIMEOFDAY;
 762    else
 763    {//對節點或者水池的控制
 764       if (n < 8) return(201);
 765       if ((i = findnode(Tok[5])) == 0) return(203);
 766       if      (match(Tok[6],w_BELOW)) type = LOWLEVEL;
 767       else if (match(Tok[6],w_ABOVE)) type = HILEVEL;
 768       else return(201);
 769    }
 770 
 771 /* Parse control level or time 獲取控制的時間或者水位*/
 772    switch (type)
 773    {
 774       case TIMER:
 775       case TIMEOFDAY:
 776          if (n == 6) time = hour(Tok[5],"");
 777          if (n == 7) time = hour(Tok[5],Tok[6]);
 778          if (time < 0.0) return(201);
 779          break;
 780       case LOWLEVEL:
 781       case HILEVEL:   
 782          if (!getfloat(Tok[7],&level)) return(202);
 783          break;
 784    }
 785 
 786 /* Fill in fields of control data structure 將上述獲取到的值填充到控制規則線性鏈表中*/
 787    Ncontrols++;
 788    if (Ncontrols > MaxControls) return(200);
 789    Control[Ncontrols].Link     = k;
 790    Control[Ncontrols].Node     = i;
 791    Control[Ncontrols].Type     = type;
 792    Control[Ncontrols].Status   = status;
 793    Control[Ncontrols].Setting  = setting;
 794    Control[Ncontrols].Time     = (long)(3600.0*time);
 795    if (type == TIMEOFDAY)
 796       Control[Ncontrols].Time %= SECperDAY;
 797    Control[Ncontrols].Grade    = level;
 798    return(0);
 799 }                        /* end of controldata */
 800 
 801 
 802 int  sourcedata()
 803 /*
 804 **--------------------------------------------------------------
 805 **  Input:   none                                                ;輸入:無
 806 **  Output:  returns error code                                  ;輸出:錯誤代碼
 807 **  Purpose: processes water quality source data                 ;目的:定義水質源頭的位置。     
 808 **  Formats:                                                     ;格式:
 809 **     [SOURCE]                                                
 810 **        node  sourcetype  quality  (pattern start stop)
 811 **                                            
 812 格式: 
 813 每一水質源頭爲一輸入行,包括: 
 814 node  節點ID標籤 
 815 sourcetype  源頭類型(CONCEN, MASS, FLOWPACED 或SETPOINT )
 816 quality  基準源頭強度 
 817 pattern  時間模式ID(可選) 
 818   
 819 **  NOTE: units of mass-based source are mass/min  
 820 備註: 
 821 a.  MASS類型源頭的強度以質量流量每分鐘計。全部其它類型以濃度單位來計量源頭強度。 
 822 b.  源頭強度能夠指定時間模式,使其隨時間變化。 
 823 c.  CONCEN源頭爲: 
 824    表示節點的任何外部源頭進流濃度 
 825    僅僅在節點具備淨負需水量時使用(水從節點進入管網) 
 826    若是節點爲鏈接節點,報告濃度時混合了源流量和從管網其它部分的進流 
 827    若是節點爲水庫,報告的濃度爲源頭濃度 
 828    若是節點爲水池,報告的濃度爲水池的內部濃度 
 829    用於節點,表示了源水供應或者處理廠(例如,水庫或者節點具備負的需水量) 
 830    不可用於同時具備進流/出流的蓄水池。 
 831 d. MASS, FLOWPACED 或SETPOINT 源頭: 
 832    表示了加強源頭,這裏物質被直接注射到管網,不考慮節點的需水量怎樣 
 833    如下方式影響了離開節點到管網的其它部分的水: 
 834     - MASS 注入,增長了固定的質量流量到節點的進流 
 835     - FLOWPACED 注入,增長了固定濃度到節點的進流濃度 
 836     - SETPOINT 注入,固定了任何離開節點的濃度(只要進流帶來的濃度低於設置值) 
 837    鏈接節點或者水庫注入源頭報告的濃度,是在注入以後的濃度;報告具備註入源頭的水
 838 池的濃度,爲水池的內部濃度 
 839    適合於模擬示蹤劑或者消毒劑直接注入到管網,或者爲了模擬污染物的入侵。 
 840 e.對於模擬水齡或者源頭跟蹤,[SOURCES]節是不須要的。
 841 **--------------------------------------------------------------
 842 */
 843 {
 844    int   i,                  /* Token with quality value 水質值這列所在的當前行的數據項列表中的索引值*/
 845          j,                  /* Node index    Node中的索引值*/
 846          n,                  /* # data items  行的數據項數*/
 847          p = 0;              /* Time pattern  模式*/
 848    char  type = CONCEN;      /* Source type   源頭類型*/
 849    double c0 = 0;             /* Init. quality 初始水質*/
 850    STmplist *pat;
 851    Psource  source;
 852 
 853    n = Ntokens;
 854    if (n < 2) return(201);
 855    if ((j = findnode(Tok[0])) == 0) return(203);
 856    /* NOTE: Under old format, SourceType not supplied so let  若是是老版本那麼i=1,由於源頭類型不存在*/
 857    /*       i = index of token that contains quality value.   水質值這列所在的當前行的數據項列表中的索引值*/
 858    i = 2;
 859    if      (match(Tok[1],w_CONCEN))    type = CONCEN;
 860    else if (match(Tok[1],w_MASS))      type = MASS;
 861    else if (match(Tok[1],w_SETPOINT))  type = SETPOINT;
 862    else if (match(Tok[1],w_FLOWPACED)) type = FLOWPACED;
 863    else i = 1;
 864    if (!getfloat(Tok[i],&c0)) return(202);      /* Illegal WQ value 檢查水質數據類型*/
 865 
 866    if (n > i+1 && strlen(Tok[i+1]) > 0 && strcmp(Tok[i+1], "*") != 0 )         //(2.00.11 - LR)
 867    {
 868        pat = findID(Tok[i+1],Patlist);
 869        if (pat == NULL) return(205);            /* Illegal pattern. 找不到指定模式*/
 870        p = pat->i;                              //返回該模式在Pattern中的索引值
 871    }
 872 
 873    source = (struct Ssource *) malloc(sizeof(struct Ssource));
 874    if (source == NULL) return(101);
 875    source->C0 = c0;
 876    source->Pat = p;
 877    source->Type = type;
 878    Node[j].S = source;
 879    return(0);
 880 }                        /* end of sourcedata */
 881 
 882 
 883 int  emitterdata()
 884 /*
 885 **--------------------------------------------------------------
 886 **  Input:   none                                                ;輸入:無
 887 **  Output:  returns error code                                  ;輸出:錯誤代碼
 888 **  Purpose: processes junction emitter data                     ;目的:將模擬節點定義爲擴散器(噴嘴或者孔口)。 
 889 **  Formats:                                                     ;格式:
 890 **     [EMITTER]                                               
 891 **        node   K       
 892 備註: 
 893 a.  擴散器用於模擬經過噴水或者管道滲漏的流量。 
 894 b.  擴散器的出流等於流量係數與提高的鏈接節點壓力乘積。 
 895 c.  功率能夠利用[OPTIONS]節的EMITTER EXPONENT選項指定。缺省功率爲0.5 ,一般用於噴嘴。 
 896 d.  程序結果中報告的實際需水量,包括節點的常規需水量加上經過擴散器的流量。 
 897 e.  [EMITTERS] 節是可選的。 
 898 **--------------------------------------------------------------
 899 */
 900 {
 901    int   j,                  /* Node index    Node中的索引值*/
 902          n,                  /* # data items  行的數據項數*/
 903    double k;                  /* Flow coeff,   流量係數,在1米(1 psi )壓降下的流量單位。*/
 904 
 905    n = Ntokens;
 906    if (n < 2) return(201); 
 907    if ((j = findnode(Tok[0])) == 0) return(203);
 908    if (j > Njuncs) return(209);                 /* Not a junction.*/
 909    if (!getfloat(Tok[1],&k)) return(202);
 910    if (k < 0.0) return(202);
 911    Node[j].Ke = k;
 912    return(0);
 913 }
 914 
 915 
 916 int  qualdata()
 917 /*
 918 **--------------------------------------------------------------
 919 **  Input:   none                                                ;輸入:無
 920 **  Output:  returns error code                                  ;輸出:錯誤代碼                               
 921 **  Purpose: processes initial water quality data                ;目的:定義節點的初始水質。 
 922 **  Formats:
 923 **     [QUALITY]                                               
 924 **        node   initqual
 925 **        node1  node2    initqual
 926 每一節點爲一輸入行,包括: 
 927 node  節點ID標籤 
 928 initqual  初始水質
 929 
 930 備註: 
 931 a.  對於沒有列入的節點,水質假設爲零。 
 932 b.  水質表示了化學成分的濃度、水齡的小時或源頭跟蹤的百分比。 
 933 c.  [QUALITY]節是可選的。
 934 **--------------------------------------------------------------
 935 */
 936 {
 937    int   j,n;
 938    long  i,i0,i1;
 939    double c0;
 940 
 941    if (Nnodes == 0) return(208);        /* No nodes defined yet */
 942    n = Ntokens;
 943    if (n < 2) return(0);
 944    if (n == 2)                          /* Single node entered  單個節點*/
 945    {
 946       if ( (j = findnode(Tok[0])) == 0) return(0);
 947       if (!getfloat(Tok[1],&c0)) return(209);
 948       Node[j].C0 = c0;
 949    }
 950    else                                 /* Node range entered    批量節點*/
 951    {
 952       if (!getfloat(Tok[2],&c0)) return(209);
 953    
 954       /* If numerical range supplied, then use numerical comparison 這塊代碼有些奇怪,不過通常沒有這種輸入格式的*/
 955       if ((i0 = atol(Tok[0])) > 0 && (i1 = atol(Tok[1])) > 0)
 956       {
 957          for (j=1; j<=Nnodes; j++)
 958          {
 959             i = atol(Node[j].ID);
 960             if (i >= i0 && i <= i1) Node[j].C0 = c0;
 961          }
 962       }
 963       else
 964       {
 965          for (j=1; j<=Nnodes; j++)
 966             if ((strcmp(Tok[0],Node[j].ID) <= 0) &&
 967                 (strcmp(Tok[1],Node[j].ID) >= 0)
 968                ) Node[j].C0 = c0;
 969       }
 970    }
 971    return(0);
 972 }                        /* end of qualdata */
 973 
 974 
 975 int  reactdata()
 976 /*
 977 **--------------------------------------------------------------
 978 **  Input:   none                                                ;輸入:無
 979 **  Output:  returns error code                                  ;輸出:錯誤代碼                                
 980 **  Purpose: processes reaction coeff. data                      ;目的:定義對應於管網中與化學成分反應的參數。 
 981 **  Formats:                                                     ;格式:
 982 **     [REACTIONS]
 983 **        ORDER     {BULK/WALL/TANK} value                       
 984 **        GLOBAL    {BULK/WALL}      coeff                                                                  
 985 **        BULK      link1  (link2)   coeff                          
 986 **        WALL      link1  (link2)   coeff                          
 987 **        TANK      node1  (node2)   coeff                          
 988 **        LIMITING  POTENTIAL        value                          
 989 **        ROUGHNESS CORRELATION      value
 990 格式: 
 991 ORDER BULK/WALL/TANK value 
 992 GLOBAL BULK/WALL value 
 993 BULK/WALL/TANK  pipeID value 
 994 LIMITING POTENTIAL value 
 995 ROUGHNESS CORRELATION value 
 996 定義: 
 997 ORDER 用於設置分別發生在主流水體、管壁或者水池中的反應級數。管壁反應的數值必須
 998 爲0或者1。若是沒有提供,缺省反應級數爲1.0 。 
 999 GLOBAL用於設置全部主流水體反應係數(管道和水池)或者全部管壁係數的全局數值。缺
1000 省值爲零。 
1001 BULK, WALL 和TANK用於對指定管道和水池從新設置全局反應係數。 
1002 LIMITING POTENTIAL 指定了反應速率正比於當前濃度和一些限制值之間的差別。 
1003 ROUGHNESS CORRELATION將使全部缺省管壁反應係數,以如下方式,相關於管道粗糙系
1004 數: 
1005 水頭損失公式    粗糙相關性 
1006 Hazen-Williams F/C 
1007 Darcy-Weisbach F/log(e/D) 
1008 Chezy-Manning   F*n 
1009  105
1010 式中F——粗糙係數相關性; 
1011 C——Hazen-Williams C因子; 
1012 e——Darcy-Weisbach粗糙係數; 
1013 D——管道直徑; 
1014 n——Chezy-Manning 粗糙係數。 
1015 這種方式計算的缺省值可以經過利用WALL格式,對於任何使用特定數值管道重載。 
1016 備註: 
1017 a.  注意增加反應係數採用正值,衰減反應係數爲負值。 
1018 b.  全部反應係數的時間單位爲1/日。 
1019 c.  本節全部輸入爲可選的,反斜槓(/)以後的事項說明了容許選項。
1020 **--------------------------------------------------------------
1021 */
1022 {
1023    int   item,j,n;
1024    long  i,i1,i2;
1025    double y;
1026 
1027 /* Skip line if insufficient data */
1028    n = Ntokens;
1029    if (n < 3) return(0);
1030 
1031 /* Process input depending on keyword */
1032    if (match(Tok[0],w_ORDER))                    /* Reaction order */
1033    {
1034       if (!getfloat(Tok[n-1],&y)) return(213);
1035       if      (match(Tok[1],w_BULK)) BulkOrder = y;
1036       else if (match(Tok[1],w_TANK)) TankOrder = y;
1037       else if (match(Tok[1],w_WALL))
1038       {
1039          if (y == 0.0) WallOrder = 0.0;
1040          else if (y == 1.0) WallOrder = 1.0;
1041          else return(213);
1042       }
1043       else return(213);
1044       return(0);
1045    }
1046    if (match(Tok[0],w_ROUGHNESS))                /* Roughness factor */
1047    {
1048       if (!getfloat(Tok[n-1],&y)) return(213);
1049       Rfactor = y;
1050       return(0);
1051    }
1052    if (match(Tok[0],w_LIMITING))                 /* Limiting potential */
1053    {
1054       if (!getfloat(Tok[n-1],&y)) return(213);
1055       /*if (y < 0.0) return(213);*/
1056       Climit = y;
1057       return(0);
1058    }
1059    if (match(Tok[0],w_GLOBAL))                   /* Global rates */
1060    {
1061       if (!getfloat(Tok[n-1],&y)) return(213);
1062       if      (match(Tok[1],w_BULK)) Kbulk = y;
1063       else if (match(Tok[1],w_WALL)) Kwall = y;
1064       else return(201);
1065       return(0);
1066    }
1067    if      (match(Tok[0],w_BULK)) item = 1;      /* Individual rates */
1068    else if (match(Tok[0],w_WALL)) item = 2;
1069    else if (match(Tok[0],w_TANK)) item = 3;
1070    else return(201);
1071    strcpy(Tok[0],Tok[1]);                        /* Save id in Tok[0] */
1072    if (item == 3)                                /* Tank rates */
1073    {
1074       if (!getfloat(Tok[n-1],&y)) return(209);   /* Rate coeff. */
1075       if (n == 3)
1076       {
1077           if ( (j = findnode(Tok[1])) <= Njuncs) return(0);
1078           Tank[j-Njuncs].Kb = y;
1079       }
1080       else
1081       {
1082        /* If numerical range supplied, then use numerical comparison */
1083          if ((i1 = atol(Tok[1])) > 0 && (i2 = atol(Tok[2])) > 0)
1084          {
1085             for (j=Njuncs+1; j<=Nnodes; j++)
1086             {
1087                i = atol(Node[j].ID);
1088                if (i >= i1 && i <= i2) Tank[j-Njuncs].Kb = y;
1089             }
1090          }
1091          else for (j=Njuncs+1; j<=Nnodes; j++)
1092             if ((strcmp(Tok[1],Node[j].ID) <= 0) &&
1093                 (strcmp(Tok[2],Node[j].ID) >= 0)
1094                ) Tank[j-Njuncs].Kb = y;
1095       }
1096    }
1097    else                                          /* Link rates */
1098    {
1099       if (!getfloat(Tok[n-1],&y)) return(211);   /* Rate coeff. */
1100       if (Nlinks == 0) return(0);
1101       if (n == 3)                                /* Single link */
1102       {
1103          if ( (j = findlink(Tok[1])) == 0) return(0);
1104          if (item == 1) Link[j].Kb = y;
1105          else           Link[j].Kw = y;
1106       }
1107       else                                       /* Range of links */
1108       {
1109        /* If numerical range supplied, then use numerical comparison */
1110          if ((i1 = atol(Tok[1])) > 0 && (i2 = atol(Tok[2])) > 0)
1111          {
1112             for (j=1; j<=Nlinks; j++)
1113             {
1114                i = atol(Link[j].ID);
1115                if (i >= i1 && i <= i2)
1116                {
1117                   if (item == 1) Link[j].Kb = y;
1118                   else           Link[j].Kw = y;
1119                }
1120             }
1121          }
1122          else for (j=1; j<=Nlinks; j++)
1123             if ((strcmp(Tok[1],Link[j].ID) <= 0) &&
1124                 (strcmp(Tok[2],Link[j].ID) >= 0) )
1125             {
1126                if (item == 1) Link[j].Kb = y;
1127                else           Link[j].Kw = y;
1128             }
1129       }
1130    }
1131    return(0);
1132 }                        /* end of reactdata */
1133 
1134 
1135 int  mixingdata()
1136 /*
1137 **-------------------------------------------------------------
1138 **  Input:   none                                                ;輸入:無
1139 **  Output:  returns error code                                  ;輸出:錯誤代碼                                
1140 **  Purpose: processes tank mixing data                          ;目的:肯定控制蓄水池混合的模型。
1141 **  Format:                                                     
1142 **    [MIXING]                                                   
1143 **     TankID  MixModel  FractVolume
1144 格式: 
1145 一個水池佔一輸入行,包括: 
1146 z  水池ID標籤 
1147 z  混合模型(MIXED, 2COMP, FIFO 或LIFO) 
1148 z  室的容積(小數) 
1149 備註: 
1150 a.  混合模型包括: 
1151 z  徹底混合(MIXED ) 
1152 z  雙室混合(2COMP ) 
1153 z  先進先出(FIFO) 
1154 z  後進先出(LIFO) 
1155 b.  室容積參數僅僅用於雙室模型,表明了總水池容積貢獻於進水/出水室的部分。 
1156 c. [MIXING]節是可選的。不在本節描述的水池假設爲徹底混合。 
1157 **-------------------------------------------------------------
1158 */
1159 {
1160    int   i,j,n;
1161    double v;
1162 
1163    if (Nnodes == 0) return(208);        /* No nodes defined yet */
1164    n = Ntokens;
1165    if (n < 2) return(0);
1166    if ( (j = findnode(Tok[0])) <= Njuncs) return(0);
1167    if ( (i = findmatch(Tok[1],MixTxt)) < 0) return(201);
1168    v = 1.0;
1169    if ( (i == MIX2) &&
1170         (n == 3) &&
1171         (!getfloat(Tok[2],&v))          /* Get frac. vol. for 2COMP model */
1172       ) return(209);
1173    if (v == 0.0) v = 1.0;               /* v can't be zero */
1174    n = j - Njuncs;
1175    if (Tank[n].A == 0.0) return(0);     /* Tank is a reservoir */
1176    Tank[n].MixModel = (char)i;
1177    Tank[n].V1max = v;
1178    return(0);
1179 }
1180 
1181 
1182 int  statusdata()
1183 /*
1184 **--------------------------------------------------------------
1185 **  Input:   none                                                ;輸入:無
1186 **  Output:  returns error code                                  ;輸出:錯誤代碼                                
1187 **  Purpose: processes link initial status data                  ;目的:定義模擬開始時被選管段的初始狀態。       
1188 **  Formats:                                                     
1189 **    [STATUS]
1190 **       link   value
1191 **       link1  (link2)  value
1192 格式: 
1193 每一控制管段佔一輸入行,包括: 
1194 z  管段ID標籤 
1195 z  狀態或者設置 
1196 備註: 
1197 a.  該部分沒有列出的管段,缺省狀態爲OPEN(對於管道和水泵)或者ACTIVE(對於閥門)。 
1198 b.  狀態值能夠爲OPEN或者CLOSED。對於控制閥(例如PRV, FCV 等),意味着閥門是全開或
1199 者全閉,在其控制點不是活動的。 
1200 c.  設置數值能夠是水泵的轉速設置,或者閥門的開啓度設置。 
1201 d.  管道的初始狀態也能夠在[PIPES]節設置。 
1202 e.  止回閥不可以預先設置它們的狀態。 
1203 **--------------------------------------------------------------
1204 */
1205 {
1206    int   j,n;                        //j:Link中的索引值;n:行數據項個數
1207    long  i,i0,i1;
1208    double y = 0.0;
1209    char  status = ACTIVE;
1210 
1211    if (Nlinks == 0) return(210);
1212    n = Ntokens - 1;
1213    if (n < 1) return(201);
1214 
1215 /* Check for legal status setting 檢查狀態數據的合法性*/
1216    if      (match(Tok[n],w_OPEN))    status = OPEN;
1217    else if (match(Tok[n],w_CLOSED))  status = CLOSED;
1218    else if (!getfloat(Tok[n],&y))    return(211);
1219    if (y < 0.0)                      return(211);
1220 
1221 /* Single link ID supplied */
1222    if (n == 1)
1223    {
1224       if ( (j = findlink(Tok[0])) == 0) return(0);
1225       /* Cannot change status of a Check Valve */
1226       if (Link[j].Type == CV) return(211);
1227 
1228 /*** Updated 9/7/00 ***/      
1229       /* Cannot change setting for a GPV */
1230       if (Link[j].Type == GPV
1231       &&  status == ACTIVE)   return(211);
1232 
1233       changestatus(j,status,y);
1234    }
1235 
1236 /* Range of ID's supplied 對間與某2個ID之間的管段的狀態的批量設置*/
1237    else
1238    {
1239       /* Numerical range supplied */
1240       if ((i0 = atol(Tok[0])) > 0 && (i1 = atol(Tok[1])) > 0)
1241       {
1242          for (j=1; j<=Nlinks; j++)
1243          {
1244             i = atol(Link[j].ID);
1245             if (i >= i0 && i <= i1) changestatus(j,status,y);
1246          }
1247       }
1248       else
1249          for (j=1; j<=Nlinks; j++)
1250             if ( (strcmp(Tok[0],Link[j].ID) <= 0) &&
1251                  (strcmp(Tok[1],Link[j].ID) >= 0)
1252                ) changestatus(j,status,y);
1253    }
1254    return(0);
1255 }              /* end of statusdata */
1256 
1257 
1258 int  energydata()
1259 /*
1260 **--------------------------------------------------------------
1261 **  Input:   none                                                ;輸入:無
1262 **  Output:  returns error code                                  ;輸出:錯誤代碼                              
1263 **  Purpose: processes pump energy data                          ;目的:定義計算水泵提高能量和成本的參數。
1264 **  Formats:                                                     ;格式:
1265 **    [ENERGY]                                                   
1266 **       GLOBAL         {PRICE/PATTERN/EFFIC}  value                 
1267 **       PUMP   id      {PRICE/PATTERN/EFFIC}  value                 
1268 **       DEMAND CHARGE  value  
1269 格式: 
1270 GLOBAL PRICE/PATTERN/EFFIC value 
1271 PUMP  PumpID PRICE/PATTERN/EFFIC  value 
1272 DEMAND CHARGE value 
1273 備註: 
1274 a.  以關鍵詞GLOBAL爲開頭的行,用於設置全部水泵的能量價格、價格模式和水泵效
1275 率的全局缺省。 
1276 b.  以關鍵詞PUMP爲開頭的行,用於對特定水泵從新設置全局缺省。 
1277 c.  參數定義以下: 
1278 z  PRICE ——每千瓦時的平均成本, 
1279 z  PATTERN——描述能量價格怎樣變化的時間模式ID標籤, 
1280 z  EFFIC ——對於全局設置的單一百分比效率,或者指定水泵的效率曲線ID標
1281 籤, 
1282 z  DEMAND CHARGE ——模擬時段每最大kW用量增長的成本。 
1283 d.  缺省全局水泵效率爲75% ,缺省全局能量價格爲0。
1284 e.  本節的全部輸入是可選的。反斜槓(/)後的項說明容許選項。 
1285 示例: 
1286 [ENERGY] 
1287 GLOBAL PRICE 0.05 ;設置全局能量價格 
1288 GLOBAL PATTERN PAT1 ;和一日內時間模式 
1289 PUMP 23 PRICE 0.10 ; 重載Pump 23的價格 
1290 PUMP 23 EFFIC E23 ;將效率曲線賦給Pump 23 
1291 **--------------------------------------------------------------
1292 */
1293 {
1294    int j,k,n;
1295    double y;
1296    STmplist *t;
1297 
1298 /* Check for sufficient data */
1299    n = Ntokens;
1300    if (n < 3) return(201);
1301 
1302 /* Check first keyword */
1303    if (match(Tok[0],w_DMNDCHARGE))               /* Demand charge */
1304    {
1305       if (!getfloat(Tok[2], &y)) return(213);
1306       Dcost = y;
1307       return(0);
1308    }
1309    if (match(Tok[0],w_GLOBAL))                   /* Global parameter */
1310    {
1311       j = 0;
1312    }
1313    else if (match(Tok[0],w_PUMP))                /* Pump-specific parameter */
1314    {
1315       if (n < 4) return(201);
1316       k = findlink(Tok[1]);                      /* Check that pump exists */
1317       if (k == 0) return(216);
1318       if (Link[k].Type != PUMP) return(216);
1319       j = PUMPINDEX(k);
1320    }
1321    else return(201);
1322 
1323 /* Find type of energy parameter */      
1324    if (match(Tok[n-2],w_PRICE))                  /* Energy price */
1325    {
1326       if (!getfloat(Tok[n-1],&y))
1327       {
1328          if (j == 0) return(213);
1329          else return(217);
1330       }
1331       if (j == 0) Ecost = y;
1332       else Pump[j].Ecost = y;
1333       return(0);
1334    }    
1335    else if (match(Tok[n-2],w_PATTERN))           /* Price pattern */
1336    {
1337       t = findID(Tok[n-1],Patlist);              /* Check if pattern exists */
1338       if (t == NULL)
1339       {
1340          if (j == 0) return(213);
1341          else return(217);
1342       }
1343       if (j == 0) Epat = t->i;
1344       else Pump[j].Epat = t->i;
1345       return(0);
1346    }
1347    else if (match(Tok[n-2],w_EFFIC))             /* Pump efficiency */
1348    {
1349       if (j == 0)
1350       {
1351          if (!getfloat(Tok[n-1], &y)) return(213);
1352          if (y <= 0.0) return(213);
1353          Epump = y;
1354       }
1355       else
1356       {
1357          t = findID(Tok[n-1],Curvelist);         /* Check if curve exists */ 
1358          if (t == NULL) return(217);
1359          Pump[j].Ecurve = t->i;
1360       }
1361       return(0);
1362    }
1363    return(201);
1364 }
1365 
1366 
1367 int  reportdata()
1368 /*
1369 **--------------------------------------------------------------
1370 **  Input:   none                                                ;輸入:無
1371 **  Output:  returns error code                                  ;輸出:錯誤代碼                                 
1372 **  Purpose: processes report options data                       ;目的:描述模擬生成的輸出報表內容。 
1373 **  Formats:                                                     
1374 **    PAGE     linesperpage                                      
1375 **    STATUS   {NONE/YES/FULL}
1376 **    SUMMARY  {YES/NO}
1377 **    MESSAGES {YES/NO}
1378 **    ENERGY   {NO/YES}                                   
1379 **    NODES    {NONE/ALL}                                        
1380 **    NODES    node1  node2 ...                                  
1381 **    LINKS    {NONE/ALL}                                        
1382 **    LINKS    link1  link2 ...                                  
1383 **    FILE     filename
1384 **    variable {YES/NO}                                          
1385 **    variable {BELOW/ABOVE/PRECISION}  value 
1386 格式: 
1387 PAGESIZE value 
1388 FILE  filename 
1389 STATUS YES/NO/FULL 
1390 SUMMARY YES/NO 
1391 ENERGY YES/NO 
1392 NODES NONE/ALL/ node1 node2 ... 
1393 LINKS NONE/ALL/ link1 link2 ... 
1394 parameter  YES/NO 
1395 parameter  BELOW/ABOVE/PRECISION value 
1396 定義: 
1397 PAGESIZES設置了輸出報表中每一頁中的行數。缺省爲0,意味着事實上每一頁沒有行數限
1398 制。 
1399 對於將要寫入的輸出報告(在EPANETH的Windows版本中忽略),FILE提供了文件的名字。 
1400 STATUS肯定了應怎樣生成水力狀態報告。若是YES 被選擇,在模擬的每一時間步長中改變
1401 狀態的全部管網組件將輸出到報告。若是FULL被選擇,那麼也將包括每一水力分析的每一試算
1402 中的信息輸出到報告。詳細水平僅僅對於調試管網是有用的,這時水力不平衡。缺省爲NO。 
1403 SUMMARY肯定了管網組件數量的總結表,以及產生的關鍵分析選項。缺省爲YES 。 
1404 ENERGY肯定是否提供表格報告平均能量使用和每一臺水泵的成本。缺省爲NO。 
1405 NODES 肯定了哪些節點將被報告。能夠列出單個節點ID標籤,或者利用關鍵詞NONE或者
1406 ALL 。額外NODES 行可用於繼續該表。缺省爲NONE。 
1407 LINKS 肯定了哪些管段將被報告。能夠列出單個管段ID標籤,或者使用關鍵詞NONE或者
1408  106
1409 ALL 。額外LINKS 行可用於繼續該表。缺省爲NONE。 
1410 「參數」報告選項,用於肯定報告哪些量,多少小數位被顯示,哪一種類型的過濾用於限制輸
1411 出報告。能夠被報告的節點參數包括: 
1412 z  標高; 
1413 z  需水量; 
1414 z  水頭; 
1415 z  壓強; 
1416 z  水質。 
1417 管段參數包括: 
1418 z  長度; 
1419 z  直徑; 
1420 z  流量; 
1421 z  流速; 
1422 z  水頭損失; 
1423 z  位置(與狀態相同-開啓、活動、關閉); 
1424 z  設置(對應於管道的粗糙係數、水泵的轉速、閥門的壓力/流量設置); 
1425 z  反應(反應速率); 
1426 z  F-因子(摩擦因子)。 
1427 報告的缺省量對於節點的需水量、水頭、壓強和水質,以及管段的流量、流速和水頭損失。
1428 缺省精度爲兩個小數位。 
1429 備註: 
1430 a.  若是在本節沒有明確指出,全部選項假設爲它們的缺省數值。 
1431 b.  反斜槓(/)後的項爲可選項。 
1432 c.  缺省值對應於任何節點或者管段沒有報告,所以若是但願報告這些事項的結果,
1433 必須提供NODES 或者LINKS 選項。 
1434 d.  對於EPANETH的Windows版本,僅僅意識到的[REPORT] 選項爲STATUS。所 有 其
1435 它被忽略。 
1436 示例: 
1437 如下示例報告了節點N1, N2, N3 和N17 ,以及全部流速大於3.0 的管段。標準節點參數(需水
1438 量、水頭、壓強和水質)被報告,同時僅僅管段的流量、流速和F因子(摩擦因子)被報告。 
1439 [REPORT] 
1440 NODES N1 N2 N3 N17 
1441 LINKS ALL 
1442 FLOW YES 
1443 VELOCITY PRECISION 4 
1444 F-FACTOR PRECISION 4 
1445 VELOCITY ABOVE 3.0
1446 **--------------------------------------------------------------
1447 */
1448 {
1449    int    i,j,n;
1450    double  y;
1451 
1452    n = Ntokens - 1;
1453    if (n < 1) return(201);
1454 
1455 /* Value for page size */
1456    if (match(Tok[0],w_PAGE))
1457    {
1458       if (!getfloat(Tok[n],&y))   return(213);
1459       if (y < 0.0 || y > 255.0) return(213);
1460       PageSize = (int) y;
1461       return(0);
1462    }
1463 
1464 /* Request that status reports be written */
1465    if (match(Tok[0],w_STATUS))
1466    {
1467       if (match(Tok[n],w_NO))   Statflag = FALSE;
1468       if (match(Tok[n],w_YES))  Statflag = TRUE;
1469       if (match(Tok[n],w_FULL)) Statflag = FULL;
1470       return(0);
1471    }
1472 
1473 /* Request summary report */
1474    if (match(Tok[0],w_SUMMARY))
1475    {
1476       if (match(Tok[n],w_NO))  Summaryflag = FALSE;
1477       if (match(Tok[n],w_YES)) Summaryflag = TRUE;
1478       return(0);
1479    }
1480 
1481 /* Request error/warning message reporting */
1482    if (match(Tok[0],w_MESSAGES))
1483    {
1484       if (match(Tok[n],w_NO))  Messageflag = FALSE;
1485       if (match(Tok[n],w_YES)) Messageflag = TRUE;
1486       return(0);
1487    }
1488    
1489 
1490 /* Request an energy usage report */
1491    if (match(Tok[0],w_ENERGY))
1492    {
1493       if (match(Tok[n],w_NO))  Energyflag = FALSE;
1494       if (match(Tok[n],w_YES)) Energyflag = TRUE;
1495       return(0);
1496    }
1497 
1498 /* Particular reporting nodes specified */
1499    if (match(Tok[0],w_NODE))
1500    {
1501       if      (match(Tok[n],w_NONE)) Nodeflag = 0;  /* No nodes */
1502       else if (match(Tok[n],w_ALL))  Nodeflag = 1;  /* All nodes */
1503       else
1504       {
1505          if (Nnodes == 0) return(208);
1506          for (i=1; i<=n; i++)
1507          {
1508             if ( (j = findnode(Tok[i])) == 0) return(208);
1509             Node[j].Rpt = 1;
1510          }
1511          Nodeflag = 2;
1512       }
1513       return(0);
1514    }
1515 
1516 /* Particular reporting links specified */
1517    if (match(Tok[0],w_LINK))
1518    {
1519       if      (match(Tok[n],w_NONE)) Linkflag = 0;
1520       else if (match(Tok[n],w_ALL))  Linkflag = 1;
1521       else
1522       {
1523          if (Nlinks == 0) return(210);
1524          for (i=1; i<=n; i++)
1525          {
1526             if ( (j = findlink(Tok[i])) == 0) return(210);
1527             Link[j].Rpt = 1;
1528          }
1529          Linkflag = 2;
1530       }
1531       return(0);
1532    }
1533 
1534 /* Check if input is a reporting criterion. */
1535 
1536 /*** Special case needed to distinguish "HEAD" from "HEADLOSS" ***/            //(2.00.11 - LR)
1537    if (strcomp(Tok[0], w_HEADLOSS)) i = HEADLOSS;                              //(2.00.11 - LR)
1538    else i = findmatch(Tok[0],Fldname);                                         //(2.00.11 - LR)
1539    if (i >= 0)                                                                 //(2.00.11 - LR)
1540 /*****************************************************************/            //(2.00.11 - LR)
1541    {
1542       if (i > FRICTION) return(201);
1543       if (Ntokens == 1 || match(Tok[1],w_YES))
1544       {
1545          Field[i].Enabled = TRUE;
1546          return(0);
1547       }
1548       if (match(Tok[1],w_NO))
1549       {
1550          Field[i].Enabled = FALSE;
1551          return(0);
1552       }
1553       if (Ntokens < 3) return(201);
1554       if      (match(Tok[1],w_BELOW))  j = LOW;   /* Get relation operator */
1555       else if (match(Tok[1],w_ABOVE))  j = HI;    /* or precision keyword  */
1556       else if (match(Tok[1],w_PRECISION)) j = PREC;
1557       else return(201);
1558       if (!getfloat(Tok[2],&y)) return(201);
1559       if (j == PREC)
1560       {
1561          Field[i].Enabled = TRUE;
1562          Field[i].Precision = ROUND(y);
1563       }
1564       else Field[i].RptLim[j] = y;                /* Report limit value */
1565       return(0);
1566    }
1567 
1568 /* Name of external report file */
1569    if (match(Tok[0],w_FILE))
1570    {
1571       strncpy(Rpt2Fname,Tok[1],MAXFNAME);
1572       return(0);
1573    }
1574 
1575 /* If get to here then return error condition */
1576    return(201);
1577 }                        /* end of reportdata */
1578 
1579 
1580 int  timedata()
1581 /*
1582 **--------------------------------------------------------------
1583 **  Input:   none                                                ;輸入:無
1584 **  Output:  returns error code                                  ;輸出:錯誤代碼                                  
1585 **  Purpose: processes time options data                         ;目的:定義模擬中的各類事件時間步長參數。
1586 **  Formats:                                                     
1587 **    STATISTIC                  {NONE/AVERAGE/MIN/MAX/RANGE}                                          
1588 **    DURATION                   value   (units)                 
1589 **    HYDRAULIC TIMESTEP         value   (units)                 
1590 **    QUALITY TIMESTEP           value   (units)                 
1591 **    MINIMUM TRAVELTIME         value   (units)
1592 **    RULE TIMESTEP              value   (units)                 
1593 **    PATTERN TIMESTEP           value   (units)
1594 **    PATTERN START              value   (units)              
1595 **    REPORT TIMESTEP            value   (units)                 
1596 **    REPORT START               value   (units)                 
1597 **    START CLOCKTIME            value   (AM PM)
1598 定義: 
1599 DURATION 是模擬的歷時。設爲0來運行簡單的瞬時分析。缺省爲0。 
1600 HYDRAULIC TIMESTEP 定義了管網新的水力狀態計算頻率。若是它大於PATTERN或者
1601 REPORT時間步長,將自動下降。缺省爲1小時。 
1602 QUALITY TIMESTEP用於跟蹤水質經過管網變化的時間步長。缺省爲水力時間步長的1/10。
1603 RULE TIMESTEP 用於檢查水力時間步長之間,基於規則控制引發的系統狀態變化的時間步長。
1604 缺省爲1/10的水力時間步長。 
1605 PATTERN TIMESTEP是全部事件模式中時段之間的間隔。缺省爲1小時。 
1606 PATTERN START 是全部模式開始時的時間份量。例如,6小時的數值將開始模擬,在時段
1607 中的每一模式,對應於6小時。缺省爲0。 
1608 REPORT TIMESTEP 設置了輸出結果被報告的時間間隔。缺省爲1小時。 
1609 REPORT START是進入模擬的時間長度,此時輸出結果開始報告。缺省爲0。 
1610 START CLOCKTIME 是模擬開始的鐘表時間(例如3:00 PM)。缺省爲子夜12:00 AM 。 
1611 STATISTICS 肯定了在產生模擬結果的時間序列中,統計後處理的類型。AVERAGED 報告了
1612 時間平均結果集合,MINIMUM僅僅報告最小值,MAXIMUM爲最大值,以及RANGE 報告了最大值
1613 和最小值之間的差別。NONE報告了全部節點和管段量的完整時間序列,它爲缺省的。 
1614 備註: 
1615 a.  單位應爲SECONDS(SEC), MINUTES(MIN), HOURS 或DAYS。缺省爲小時。 
1616 b.  若是沒有提供計量單位,該時間數值可能輸入爲小數小時或者爲小時:分鐘。 
1617 c.  全部在[TIMES]節的輸入是可選的。在反斜槓(/)後的事項說明了可選狀況。
1618 **-------------------------------------------------------------
1619 */
1620 {
1621    int    n;
1622    long   t;
1623    double  y;
1624 
1625    n = Ntokens - 1;
1626    if (n < 1) return(201);
1627 
1628 /* Check if setting time statistic flag */
1629    if (match(Tok[0],w_STATISTIC))
1630    {
1631       if      (match(Tok[n],w_NONE))  Tstatflag = SERIES;
1632       else if (match(Tok[n],w_NO))    Tstatflag = SERIES;
1633       else if (match(Tok[n],w_AVG))   Tstatflag = AVG;
1634       else if (match(Tok[n],w_MIN))   Tstatflag = MIN;
1635       else if (match(Tok[n],w_MAX))   Tstatflag = MAX;
1636       else if (match(Tok[n],w_RANGE)) Tstatflag = RANGE;
1637       else return(201);
1638       return(0);
1639    }
1640 
1641 /* Convert text time value to numerical value in seconds 將文本時間值轉換爲數值時間值單位爲秒*/
1642 /* Examples:
1643 **    5           = 5 * 3600 sec
1644 **    5 MINUTES   = 5 * 60   sec
1645 **    13:50       = 13*3600 + 50*60 sec
1646 **    1:50 pm     = (12+1)*3600 + 50*60 sec
1647 */
1648      
1649    if (!getfloat(Tok[n],&y))
1650    {
1651       if ( (y = hour(Tok[n],"")) < 0.0)
1652       {
1653          if ( (y = hour(Tok[n-1],Tok[n])) < 0.0) return(213);
1654       }
1655    }
1656    t = (long)(3600.0*y);
1657 
1658 /* Process the value assigned to the matched parameter */
1659    if      (match(Tok[0],w_DURATION))  Dur = t;      /* Simulation duration */
1660    else if (match(Tok[0],w_HYDRAULIC)) Hstep = t;    /* Hydraulic time step */
1661    else if (match(Tok[0],w_QUALITY))   Qstep = t;    /* Quality time step   */
1662    else if (match(Tok[0],w_RULE))      Rulestep = t; /* Rule time step      */
1663    else if (match(Tok[0],w_MINIMUM))   return(0);    /* Not used anymore    */
1664    else if (match(Tok[0],w_PATTERN))
1665    {
1666       if (match(Tok[1],w_TIME))       Pstep = t;     /* Pattern time step   */
1667       else if (match(Tok[1],w_START)) Pstart = t;    /* Pattern start time  */
1668       else return(201);
1669    }
1670    else if (match(Tok[0],w_REPORT))
1671    {
1672       if      (match(Tok[1],w_TIME))  Rstep = t;     /* Reporting time step  */
1673       else if (match(Tok[1],w_START)) Rstart = t;    /* Reporting start time */
1674       else return(201);
1675    }                                                 /* Simulation start time*/
1676    else if (match(Tok[0],w_START))    Tstart = t % SECperDAY; 
1677    else return(201);
1678    return(0);
1679 }                        /* end of timedata */
1680 
1681 
1682 int  optiondata()
1683 /*
1684 **--------------------------------------------------------------
1685 **  Input:   none                                                ;輸入:無
1686 **  Output:  returns error code                                  ;輸出:錯誤代碼                                 
1687 **  Purpose: processes [OPTIONS] data                            ;目的:定義不一樣的模擬選項。 
1688 **--------------------------------------------------------------
1689 */
1690 {
1691    int i,n;
1692 
1693    n = Ntokens - 1;
1694    i = optionchoice(n);         /* Option is a named choice    */
1695    if (i >= 0) return(i);
1696    return(optionvalue(n));      /* Option is a numerical value */
1697 }                        /* end of optiondata */
1698 
1699 
1700 int  optionchoice(int n)
1701 /*
1702 **--------------------------------------------------------------
1703 **  Input:   n = index of last input token saved in Tok[]          
1704 **  Output:  returns error code or 0 if option belongs to        
1705 **           those listed below, or -1 otherwise                 
1706 **  Purpose: processes fixed choice [OPTIONS] data               
1707 **  Formats:                                                     
1708 **    UNITS               CFS/GPM/MGD/IMGD/AFD/LPS/LPM/MLD/CMH/CMD/SI
1709 **    PRESSURE            PSI/KPA/M                          
1710 **    HEADLOSS            H-W/D-W/C-M                        
1711 **    HYDRAULICS          USE/SAVE  filename                  
1712 **    QUALITY             NONE/AGE/TRACE/CHEMICAL  (TraceNode) 
1713 **    MAP                 filename                               
1714 **    VERIFY              filename                               
1715 **    UNBALANCED          STOP/CONTINUE {Niter}
1716 **    PATTERN             id
1717 **--------------------------------------------------------------
1718 */
1719 {
1720   /* Check if 1st token matches a parameter name and */
1721   /* process the input for the matched parameter     */
1722    if (n < 0) return(201);
1723    if (match(Tok[0],w_UNITS))  
1724    {
1725       if (n < 1) return(0);
1726       else if (match(Tok[1],w_CFS))  Flowflag = CFS;
1727       else if (match(Tok[1],w_GPM))  Flowflag = GPM;
1728       else if (match(Tok[1],w_AFD))  Flowflag = AFD;
1729       else if (match(Tok[1],w_MGD))  Flowflag = MGD;
1730       else if (match(Tok[1],w_IMGD)) Flowflag = IMGD;
1731       else if (match(Tok[1],w_LPS))  Flowflag = LPS;
1732       else if (match(Tok[1],w_LPM))  Flowflag = LPM;
1733       else if (match(Tok[1],w_CMH))  Flowflag = CMH;
1734       else if (match(Tok[1],w_CMD))  Flowflag = CMD;
1735       else if (match(Tok[1],w_MLD))  Flowflag = MLD;
1736       else if (match(Tok[1],w_SI))   Flowflag = LPS;
1737       else return(201);
1738    }
1739    else if (match(Tok[0],w_PRESSURE))
1740    {
1741       if (n < 1) return(0);
1742       else if (match(Tok[1],w_PSI))    Pressflag = PSI;
1743       else if (match(Tok[1],w_KPA))    Pressflag = KPA;
1744       else if (match(Tok[1],w_METERS)) Pressflag = METERS;
1745       else return(201);
1746    }
1747    else if (match(Tok[0],w_HEADLOSS))
1748    {
1749       if (n < 1) return(0);
1750       else if (match(Tok[1],w_HW)) Formflag = HW;
1751       else if (match(Tok[1],w_DW)) Formflag = DW;
1752       else if (match(Tok[1],w_CM)) Formflag = CM;
1753       else return(201);
1754    }
1755    else if (match(Tok[0],w_HYDRAULIC))
1756    {
1757       if (n < 2) return(0);
1758       else if (match(Tok[1],w_USE))  Hydflag = USE;
1759       else if (match(Tok[1],w_SAVE)) Hydflag = SAVE;
1760       else return(201);
1761       strncpy(HydFname,Tok[2],MAXFNAME);
1762    }
1763    else if (match(Tok[0],w_QUALITY))
1764    {
1765       if (n < 1) return(0);
1766       else if (match(Tok[1],w_NONE))  Qualflag = NONE;
1767       else if (match(Tok[1],w_CHEM))  Qualflag = CHEM;
1768       else if (match(Tok[1],w_AGE))   Qualflag = AGE;
1769       else if (match(Tok[1],w_TRACE)) Qualflag = TRACE;
1770       else
1771       {
1772          Qualflag = CHEM;
1773          strncpy(ChemName,Tok[1],MAXID);
1774          if (n >= 2) strncpy(ChemUnits,Tok[2],MAXID);
1775       }
1776       if (Qualflag == TRACE)                  /* Source tracing option */
1777       {
1778       /* Copy Trace Node ID to Tok[0] for error reporting */
1779          strcpy(Tok[0],"");
1780          if (n < 2) return(212);
1781          strcpy(Tok[0],Tok[2]);
1782          TraceNode = findnode(Tok[2]);
1783          if (TraceNode == 0) return(212);
1784          strncpy(ChemName,u_PERCENT,MAXID);
1785          strncpy(ChemUnits,Tok[2],MAXID);
1786       }
1787       if (Qualflag == AGE)
1788       {
1789          strncpy(ChemName,w_AGE,MAXID);
1790          strncpy(ChemUnits,u_HOURS,MAXID);
1791       }
1792    }
1793    else if (match(Tok[0],w_MAP))
1794    {
1795       if (n < 1) return(0);
1796       strncpy(MapFname,Tok[1],MAXFNAME);        /* Map file name */
1797    }
1798    else if (match(Tok[0],w_VERIFY))
1799    {
1800       /* Backward compatibility for verification file */
1801    }
1802    else if (match(Tok[0],w_UNBALANCED))         /* Unbalanced option */
1803    {
1804       if (n < 1) return(0);
1805       if (match(Tok[1],w_STOP)) ExtraIter = -1;
1806       else if (match(Tok[1],w_CONTINUE))
1807       {
1808          if (n >= 2) ExtraIter = atoi(Tok[2]);
1809          else ExtraIter = 0;
1810       }
1811       else return(201);
1812    }
1813    else if (match(Tok[0],w_PATTERN))            /* Pattern option */
1814    {
1815       if (n < 1) return(0);
1816       strncpy(DefPatID,Tok[1],MAXID);
1817    }
1818    else return(-1);
1819    return(0);
1820 }                        /* end of optionchoice */
1821 
1822 
1823 int  optionvalue(int n)
1824 /*
1825 **------------------------------------------------------------- 
1826 **  Input:   *line = line read from input file                   
1827 **  Output:  returns error code                                  
1828 **  Purpose: processes numerical value [OPTIONS] data            
1829 **  Formats:
1830 **    DEMAND MULTIPLIER   value
1831 **    EMITTER EXPONENT    value                                                     
1832 **    VISCOSITY           value                                  
1833 **    DIFFUSIVITY         value                                  
1834 **    SPECIFIC GRAVITY    value                                  
1835 **    TRIALS              value                                  
1836 **    ACCURACY            value                                  
1837 **    TOLERANCE           value                                  
1838 **    SEGMENTS            value  (not used)                                 
1839 **  ------ Undocumented Options -----                            
1840 **    HTOL                value                                  
1841 **    QTOL                value                                  
1842 **    RQTOL               value                                  
1843 **    CHECKFREQ           value                                  
1844 **    MAXCHECK            value
1845 **    DAMPLIMIT           value                                                //(2.00.12 - LR)                                  
1846 **--------------------------------------------------------------
1847 UNITS 設置了流量被表達的單位: 
1848     LPS ——升/秒 
1849     LPM ——升/分 
1850     MLD ——百萬升/日 
1851     CMH ——立方米/小時 
1852     CMG ——立方米/日 
1853     CFS ——立方英尺/秒 
1854     GPM ——加侖/分 
1855     MGD ——百萬加侖/日 
1856     IMGD——英制MGD 
1857     AFD ——英畝-英尺/日 
1858 若是流量單位爲升或者立方米,那麼公制單位也必須用於全部其它輸入量。對於CFS, GPM, 
1859 MGD, IMGD和AFD ,其它輸入量表達爲美製單位。(計量單位參見附錄A)。缺省流量單位爲GPM 。 
1860 HEADLOSS 選擇了用於計算經過管道水流的水頭損失公式。包括Hazen-Williams(H-W ),
1861 Darcy-Weisbach(D-W)或Chezy-Manning (C-M)公式。缺省爲H-W 。 
1862 HYDRAULICS 選項容許將當前水力結果SAVE(保存)到文件,或者USE (利用)之前保存的
1863 水力結果。當研究僅僅影響水質行爲的因子時,頗有用。 
1864 QUALITY選擇了執行水質分析的類型。選擇包括NONE(無), CHEMICAL(化學藥劑), AGE
1865 (水齡)和TRACE (跟蹤)。在CHEMI CAL 狀況中,化合物的實際名稱以後爲其濃度單位(例如
1866 CHLORINE mg/L )。若是TRACE 被選擇,必須跟蹤節點的ID標籤。缺省選項爲NONE(沒有水
1867 質分析)。 
1868 VISCOSITY是被模擬流體的運動粘度,相對於20攝氏度時的狀況(1.0 釐斯)。缺省值爲
1869 1.0 。 
1870 DIFFUSIVITY是化合物的分析擴散係數,相對於水中的氯狀況。缺省值爲1.0 。擴散係數
1871 僅僅適用於管壁反應中考慮質量轉換限制時。數值0將形成EPANETH忽略質量轉換限制。 
1872 SPECIFIC GRAVITY是被模擬流體密度與4攝氏度水的密度之比(無量綱)。 
1873 TRIALS是在每一模擬水力時間步長中,求解管網水力特性使用的最大試算次數。缺省爲40。 
1874 ACCURACY 指定了肯定什麼時候達到水力結果的收斂準則。當全部流量總和改變,來自原先求解
1875 除以全部管段的總流量低於該數值時,試算停止。缺省爲0.001 。 
1876 UNBALANCED 肯定了什麼時候進行,若是水力結果在指定的TRIAL 數值內不可以達到,對於水力
1877 時間步長來模擬。「STOP」將在該點終止整個分析。「CONTINUE 」將在公佈警告消息的狀況
1878 下繼續分析。「CONTINUE n 」將在另外「n」次試算中搜索結果,全部管線狀態保持它們的當
1879 前設置。模擬將在該點繼續,關於收斂是否達到,具備消息公佈。缺省選項爲「STOP」。 
1880 PATTERN提供了用於沒有指定需水量模式的全部節點缺省需水量模式的ID標籤。若是沒有
1881 這樣的模式在[PATTERNS] 節中存在,那麼經過缺省的模式,包含一個等於1.0 的單一乘子。如
1882 果沒有使用該選項,整體缺省需水量模式具備標籤「1」。 
1883 DEMAND MULTIPLIER用於調整全部鏈接節點的基本需水量數值,以及全部需水量的類型。
1884 例如,數值2爲兩倍的基準需水量,而數值0.5 將爲它們的一半。缺省值爲1.0 。 
1885 EMITTER EXPONENT指定了當計算擴散器的流量時,節點壓力上升的冪指數。缺省爲0.5 。 
1886 MAP 用於提供包含了管網節點座標的文件名稱,以便繪製管網地圖。對於任何水力或者水質
1887 計算這是無用的。 
1888 TOLERANCE是水質水平精度。對於全部水質分析(化合物、水齡(以小時度量),或者源
1889 頭跟蹤(以百分比度量)),缺省值爲0.01。 
1890 備註: 
1891 a.  若是在本節沒有明確指定,全部選項假設爲缺省數值。 
1892 b.  反斜槓(/)後的項說明爲容許選項。 
1893 */
1894 {
1895    int    nvalue = 1;   /* Index of token with numerical value */
1896    double  y;
1897 
1898 /* Check for obsolete SEGMENTS keyword */
1899    if (match(Tok[0],w_SEGMENTS)) return(0);
1900 
1901 /* Check for missing value (which is permissible) */
1902    if (match(Tok[0],w_SPECGRAV) || match(Tok[0],w_EMITTER)
1903    || match(Tok[0],w_DEMAND)) nvalue = 2;
1904    if (n < nvalue) return(0);
1905 
1906 /* Check for valid numerical input */
1907    if (!getfloat(Tok[nvalue],&y)) return(213);
1908 
1909 /* Check for WQ tolerance option (which can be 0) */
1910    if (match(Tok[0],w_TOLERANCE))
1911    {
1912       if (y < 0.0) return(213);
1913       Ctol = y;         /* Quality tolerance*/
1914       return(0);
1915    }
1916 
1917 /* Check for Diffusivity option */
1918    if (match(Tok[0],w_DIFFUSIVITY))
1919    {
1920       if (y < 0.0) return(213);
1921       Diffus = y;
1922       return(0);
1923    }
1924 
1925 /* Check for Damping Limit option */                                           //(2.00.12 - LR)
1926    if (match(Tok[0],w_DAMPLIMIT))
1927    {
1928       DampLimit = y;
1929       return(0);
1930    }
1931 
1932 /* All other options must be > 0 */
1933    if (y <= 0.0) return(213);
1934 
1935 /* Assign value to specified option */
1936    if      (match(Tok[0],w_VISCOSITY))   Viscos = y;       /* Viscosity */
1937    else if (match(Tok[0],w_SPECGRAV))    SpGrav = y;       /* Spec. gravity */
1938    else if (match(Tok[0],w_TRIALS))      MaxIter = (int)y; /* Max. trials */
1939    else if (match(Tok[0],w_ACCURACY))                      /* Accuracy */
1940    {
1941       y = MAX(y,1.e-5);                                  
1942       y = MIN(y,1.e-1);
1943       Hacc = y;
1944    }
1945    else if (match(Tok[0],w_HTOL))        Htol = y;
1946    else if (match(Tok[0],w_QTOL))        Qtol = y;
1947    else if (match(Tok[0],w_RQTOL))
1948    {
1949       if (y >= 1.0) return(213);
1950       RQtol = y;
1951    }
1952    else if (match(Tok[0],w_CHECKFREQ))   CheckFreq = (int)y;
1953    else if (match(Tok[0],w_MAXCHECK))    MaxCheck = (int)y;
1954    else if (match(Tok[0],w_EMITTER))     Qexp = 1.0/y;
1955    else if (match(Tok[0],w_DEMAND))      Dmult = y;
1956    else return(201);
1957    return(0);
1958 }                        /* end of optionvalue */
1959 
1960 
1961 int  getpumpcurve(int n)
1962 /*
1963 **--------------------------------------------------------
1964 **  Input:   n = number of parameters for pump curve
1965 **  Output:  returns error code
1966 **  Purpose: processes pump curve data for Version 1.1-
1967 **           style input data
1968 **  Notes:
1969 **    1. Called by pumpdata() in INPUT3.C
1970 **    2. Current link index & pump index of pump being
1971 **       processed is found in global variables Nlinks
1972 **       and Npumps, respectively
1973 **    3. Curve data read from input line is found in
1974 **       global variables X[0],...X[n-1]
1975 **---------------------------------------------------------
1976 */
1977 {
1978    double a,b,c,h0,h1,h2,q1,q2;
1979 
1980    if (n == 1)                /* Const. HP curve       */
1981    {
1982       if (X[0] <= 0.0) return(202);
1983       Pump[Npumps].Ptype = CONST_HP;
1984       Link[Nlinks].Km = X[0];
1985    }
1986    else
1987    {
1988       if (n == 2)             /* Generic power curve   */
1989       {
1990          q1 = X[1];
1991          h1 = X[0];
1992          h0 = 1.33334*h1;
1993          q2 = 2.0*q1;
1994          h2 = 0.0;
1995       }
1996       else if (n >= 5)        /* 3-pt. power curve     */
1997       {
1998          h0 = X[0];
1999          h1 = X[1];
2000          q1 = X[2];
2001          h2 = X[3];
2002          q2 = X[4];
2003       }
2004       else return(202);
2005       Pump[Npumps].Ptype = POWER_FUNC;
2006       if (!powercurve(h0,h1,h2,q1,q2,&a,&b,&c)) return(206);
2007       Pump[Npumps].H0 = -a;
2008       Pump[Npumps].R  = -b;
2009       Pump[Npumps].N  = c;
2010       Pump[Npumps].Q0 = q1;
2011       Pump[Npumps].Qmax  = pow((-a/b),(1.0/c));
2012       Pump[Npumps].Hmax  = h0;
2013    }
2014    return(0);
2015 }
2016 
2017 
2018 int  powercurve(double h0, double h1, double h2, double q1,
2019                 double q2, double *a, double *b, double *c)
2020 /*
2021 **---------------------------------------------------------
2022 **  Input:   h0 = shutoff head                            輸入:h0 =最大水頭
2023 **           h1 = design head                                    h1 =設計水頭 
2024 **           h2 = head at max. flow                              h2 =最大流量時的水頭
2025 **           q1 = design flow                                    q1 =設計流量
2026 **           q2 = max. flow                                      q2 =最大流量
2027 **  Output:  *a, *b, *c = pump curve coeffs. (H = a-bQ^c),輸出:返回水泵揚程-流量公式中的3參數
2028 **           Returns 1 if sucessful, 0 otherwise.
2029 **  Purpose: computes coeffs. for pump curve              目的:計算水泵曲線的方程係數
2030 **----------------------------------------------------------
2031 */
2032 {
2033     double h4,h5;
2034     if (
2035           h0      < TINY ||
2036           h0 - h1 < TINY ||
2037           h1 - h2 < TINY ||
2038           q1      < TINY ||
2039           q2 - q1 < TINY
2040                            ) return(0);
2041     *a = h0;
2042     h4 = h0 - h1;
2043     h5 = h0 - h2;
2044     *c = log(h5/h4)/log(q2/q1);
2045     if (*c <= 0.0 || *c > 20.0) return(0);
2046     *b = -h4/pow(q1,*c);
2047 
2048     /*** Updated 6/24/02 ***/
2049     if (*b >= 0.0) return(0);
2050 
2051     return(1);
2052 }
2053 
2054 
2055 int  valvecheck(int type, int j1, int j2)
2056 /*
2057 **--------------------------------------------------------------
2058 **  Input:   type = valve type 閥門類型                                  
2059 **           j1   = index of upstream node   上游節點索引值                    
2060 **           j2   = index of downstream node 下游節點索引值                   
2061 **  Output:  returns 1 for legal connection, 0 otherwise   返回1爲合法閥門狀況      
2062 **  Purpose: checks for legal connections between PRVs & PSVs    做用:檢查多個閥門之間共享節點等非法狀況
2063 **--------------------------------------------------------------
2064 */
2065 {
2066    int  k, vk, vj1, vj2, vtype;
2067 
2068    /* Examine each existing valve */
2069    for (k=1; k<=Nvalves; k++)
2070    {
2071       vk = Valve[k].Link;
2072       vj1 = Link[vk].N1;
2073       vj2 = Link[vk].N2;
2074       vtype = Link[vk].Type;
2075 
2076       /* Cannot have two PRVs sharing downstream nodes or in series */
2077       if (vtype == PRV && type == PRV)
2078       {
2079          if (vj2 == j2 ||
2080              vj2 == j1 ||
2081              vj1 == j2   ) return(0);
2082       }
2083 
2084       /* Cannot have two PSVs sharing upstream nodes or in series */
2085       if (vtype == PSV && type == PSV)
2086       {
2087          if (vj1 == j1 ||
2088              vj1 == j2 ||
2089              vj2 == j1   ) return(0);
2090       }
2091 
2092       /* Cannot have PSV connected to downstream node of PRV */
2093       if (vtype == PSV && type == PRV && vj1 == j2) return(0);
2094       if (vtype == PRV && type == PSV && vj2 == j1) return(0);
2095 
2096 /*** Updated 3/1/01 ***/
2097       /* Cannot have PSV connected to downstream node of FCV */
2098       /* nor have PRV connected to upstream node of FCV */
2099       if (vtype == FCV && type == PSV && vj2 == j1) return(0);
2100       if (vtype == FCV && type == PRV && vj1 == j2) return(0);
2101 
2102 /*** Updated 4/14/05 ***/
2103       if (vtype == PSV && type == FCV && vj1 == j2) return (0);
2104       if (vtype == PRV && type == FCV && vj2 == j1) return (0);
2105    }
2106    return(1);
2107 }                   /* End of valvecheck */
2108 
2109 
2110 void  changestatus(int j, char status, double y)
2111 /*
2112 **--------------------------------------------------------------
2113 **  Input:   j      = link index                                   
2114 **           status = status setting (OPEN, CLOSED)             //這裏就闡釋了status與setting的關係                
2115 **           y      = numerical setting (pump speed, valve
2116 **                    setting)
2117 **  Output:  none
2118 **  Purpose: changes status or setting of a link
2119 **
2120 **  NOTE: If status = ACTIVE, then a numerical setting (y) was  //若是status = ACTIVE,那麼一個數值設定y將提供用於表示水泵的轉速,或者閥門的開度等
2121 **        supplied. If status = OPEN/CLOSED, then numerical
2122 **        setting is 0.
2123 **--------------------------------------------------------------
2124 */
2125 {
2126    if (Link[j].Type == PIPE || Link[j].Type == GPV)
2127    {
2128       if (status != ACTIVE) Link[j].Stat = status;
2129    }
2130    else if (Link[j].Type == PUMP)
2131    {
2132       if (status == ACTIVE)
2133       {
2134          Link[j].Kc = y;
2135          status = OPEN;
2136          if (y == 0.0) status = CLOSED;
2137       }
2138       else if (status == OPEN) Link[j].Kc = 1.0;
2139       Link[j].Stat = status;
2140    }
2141    else if (Link[j].Type >= PRV)
2142    {
2143       Link[j].Kc = y;
2144       Link[j].Stat = status;
2145       if (status != ACTIVE) Link[j].Kc = MISSING;
2146    }
2147 }                        /* end of changestatus */
2148 
2149 /********************** END OF INPUT3.C ************************/
相關文章
相關標籤/搜索