• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

WDN.cpp

Go to the documentation of this file.
00001 #include "WDN.h"
00002 
00003 //------------------------------------------------------------------------------
00004 // Struct DiameterTable
00005 //-------------------------------------------------
00006 
00007 int DiameterTable::lookupDiameterCode(float diameterSize)
00008 {
00009   int num = this->size();
00010   for (int i = 0; i < num; i++)
00011   {
00012     if (diameterSize == this->at(i).size)
00013       return i;
00014   }
00015   
00016   return -1;
00017 }
00018 
00019 //------------------------------------------------------------------------------
00020 // Class WDN
00021 //-------------------------------------------------
00022 // Public Members
00023 void WDN::getNadirIdeal(vector<double>& nadir, vector<double>& ideal, int numVar)
00024 {
00025   nadir.resize(3);
00026   ideal.resize(3);
00027 
00028   int* xnom = new int[numVar];
00029   for (int i = 0; i < numVar; i++)
00030     xnom[i] = 0;          
00031   vector<float> flow(2*network.m, 1);
00032 
00033   ideal[0] = isParallelExp() ? 0 : f1(NULL, xnom);
00034   ideal[1] = 1;
00035   ideal[2] = f3(flow);
00036 
00037   for (int i = 0; i < numVar; i++)
00038     xnom[i] = diameterTable.size() - 1;   
00039 
00040   nadir[0] = f1(NULL, xnom);
00041   nadir[1] = 0;
00042   nadir[2] = 1;
00043 
00044   delete [] xnom;
00045 }
00046 
00047 //------------------------------------------------------------------------------
00048 // Class WDN
00049 //-------------------------------------------------
00050 // Protected Members
00051 
00052 /* Initialize EPANET simulator */
00053 void WDN::initialize(string simInputFileName, string simOutputFileName) 
00054 {
00055 #ifdef DEBUG
00056   cout << "WDN::initialize()" << endl;
00057 #endif
00058 
00059   /* Input to EPANET simulator the diameters of the new pipes, 
00060    * and existing pipes (ico parallel expansion problem)
00061    */
00062   char temp[LEN], temp2[LEN], temp3[] = "";
00063   int errorCode = ENopen(strcpy(temp, simInputFileName.c_str()), strcpy(temp2, simOutputFileName.c_str()), temp3);
00064   if (errorCode != 0)
00065   {
00066     cerr << "WDN: EPANET simulator returned error code " << errorCode << " while trying to initialize! Exiting." << endl;
00067     exit(1);
00068   }
00069 
00070   /* Read in diameter table */  
00071   ifstream infile(simInputFileName.c_str());
00072   char line[LEN], * pNext;
00073   Diameter newDiameter;
00074   Pipe newPipe;
00075 
00076   skipLinesUntil(infile, HEADER_DIAMETERS);
00077   infile.getline(line, LEN); // Skip row with column heads
00078   do
00079   {
00080     infile.getline(line, LEN);
00081     newDiameter.size = (float) strtod(line, &pNext);
00082     newDiameter.price = (float) strtod(pNext, NULL);
00083     diameterTable.push_back(newDiameter); 
00084   } 
00085   while (diameterTable.back().size != 0.0);
00086 
00087   diameterTable.pop_back(); // Remove entry originating from empty line
00088 
00089   /* Read in miscellaneous settings */
00090   skipLinesUntil(infile, HEADER_MISC);
00091   pressureZero = (float) strtod(getValue(infile), NULL);
00092   pressureReq = (float) strtod(getValue(infile), NULL);
00093   convDiamSize = (float) strtod(getValue(infile), NULL);
00094   parallelExp = (atoi(getValue(infile)) == 1) ? true : false; 
00095 
00096   infile.close();
00097 
00098   /* Retrieve network parameters */ 
00099   ENgetcount(EN_LINKCOUNT, &network.m);
00100   ENgetcount(EN_NODECOUNT, &network.n);
00101   ENgetcount(EN_TANKCOUNT, &network.r);
00102   network.n -= network.r;
00103   
00104   if (parallelExp)
00105   {
00106     /* Adjust number of pipes to omit the existing pipes */
00107     network.m /= 2;
00108 
00109     /* Add zero diameter to diameter table */
00110     newDiameter.size = 0;
00111     newDiameter.price = 0;
00112     diameterTable.insert(diameterTable.begin(), 1, newDiameter); // Insert at postion 0
00113   }
00114 
00115   /* Retrieve new pipe definitions */
00116   for (int i = 0; i < network.m; i++)
00117   {    
00118     ENgetlinkvalue(i+1, EN_LENGTH, &newPipe.length);
00119     ENgetlinkvalue(i+1, EN_ROUGHNESS, &newPipe.roughness);
00120     ENgetlinknodes(i+1, &newPipe.beginNode, &newPipe.endNode);
00121     newPipe.beginNode--;
00122     newPipe.endNode--;
00123     network.pipe.push_back(newPipe);
00124   }
00125   
00126   /* Retrieve existing pipe definitions */
00127   if (parallelExp)
00128   {
00129     for (int i = 0; i < network.m; i++)
00130     {    
00131       ENgetlinkvalue(i+1+network.m, EN_LENGTH, &newPipe.length);
00132       ENgetlinkvalue(i+1+network.m, EN_ROUGHNESS, &newPipe.roughness);
00133       ENgetlinknodes(i+1+network.m, &newPipe.beginNode, &newPipe.endNode);
00134       newPipe.beginNode--;
00135       newPipe.endNode--;
00136       network.existPipe.push_back(newPipe);
00137     }
00138   }
00139   
00140   /* Retrieve nodal elevations and demands */
00141   network.elevation.resize(network.n);
00142   network.Q.resize(network.n);
00143   for (int j = 0; j < network.n; j++)
00144   {
00145     ENgetnodevalue(j+1, EN_ELEVATION, &network.elevation[j]);
00146     ENgetnodevalue(j+1, EN_BASEDEMAND, &network.Q[j]);
00147   }
00148 
00149   /* Initialize EPANET simulator */ 
00150   ENopenH();
00151 
00152   F.resize(3, 0);
00153 }
00154 
00155 void WDN::simulate(Individual* I, int* xnom, int numVar, double* noise)
00156 {
00157 #ifdef DEBUG
00158   cout << "WDN::simulate()" << endl;
00159 #endif
00160 
00161   if (numVar < network.m && !(numVar == network.m / 2 && parallelExp))   
00162   {           
00163     cerr << "WDN: number of decision variables, numVar = " << numVar <<  ", is less than the number of pipes in the network, m = " << network.m 
00164          << "! Exiting." << endl;
00165     close();
00166     exit(1);
00167   }
00168 
00169   long t, tStep;
00170   F.assign(3, 0);
00171 
00172   /* Input environmental noise to EPANET simulator */
00173   if (noise != NULL)
00174   {
00175     for (int j = 0; j < network.n; j++)
00176       ENsetnodevalue(j+1, EN_BASEDEMAND, network.Q[j] + (noise[j] * cvDemand * network.Q[j]));
00177     
00178     float a, b;  
00179     for (int i = 0; i < network.m; i++)
00180     {
00181       a = network.pipe[i].roughness - (cvRoughness * network.pipe[i].roughness);
00182       b = network.pipe[i].roughness + (cvRoughness * network.pipe[i].roughness);
00183       ENsetlinkvalue(i+1, EN_ROUGHNESS, a + (noise[i+network.n] * (b-a)));  
00184     }
00185   }
00186   
00187   /* Input to EPANET simulator the diameters for the new pipes, contained in the individual */
00188   for (int i = 0; i < network.m; i++)
00189   {
00190     if (diameterTable[((I != NULL) ? I->D[i] : xnom[i])].size > 0.0)
00191     {
00192       ENsetlinkvalue(i+1, EN_INITSTATUS, 1);   
00193       ENsetlinkvalue(i+1, EN_DIAMETER, (diameterTable[((I != NULL) ? I->D[i] : xnom[i])].size) * convDiamSize);
00194     }
00195     else
00196       ENsetlinkvalue(i+1, EN_INITSTATUS, 0);
00197   }
00198 
00199   /* Run EPANET simulator */ 
00200   ENinitH(0);
00201   do
00202   {
00203     ENrunH(&t);
00204     ENnextH(&tStep);
00205   } 
00206   while (tStep > 0);
00207  
00208   /* Retrieve flows in pipes from EPANET */
00209   vector<float> flow((parallelExp) ? network.m * 2 : network.m, 0);
00210   for (int i = 0; i < network.m; i++)
00211     ENgetlinkvalue(i+1, EN_FLOW, &flow[i]);
00212 
00213   if (parallelExp)
00214   {
00215     for (int i = 0; i < network.m; i++)
00216       ENgetlinkvalue(i+1+network.m, EN_FLOW, &flow[i]);
00217   }
00218 
00219   /* Retrieve nodal pressures from EPANET */
00220   vector<float> pressure(network.n, 0);
00221   for (int j = 0; j < network.n; j++)
00222   {
00223     ENgetnodevalue(j+1, EN_HEAD, &pressure[j]);
00224     pressure[j] -= network.elevation[j];
00225   }
00226 
00227   /* Calculate objective values */ 
00228   F[0] = f1(I, xnom);
00229   F[1] = f2(pressure);
00230   F[2] = f3(flow);
00231 
00232   if (I != NULL)
00233     I->F = F;
00234 }
00235 
00236 /* f1: Investment Cost -> min */
00237 double WDN::f1(Individual* I, int* xnom)
00238 {
00239 #ifdef DEBUG
00240   cout << "WDN::f1()" << endl;
00241 #endif
00242 
00243   double sum = 0;
00244 
00245   for (int i = 0; i < network.m; i++)
00246     sum += diameterTable[((I != NULL) ? I->D[i] : xnom[i])].price * network.pipe[i].length;
00247   
00248   return sum;
00249 }
00250 
00251 /* f2: Weighted Demand Supply Ratio -> MAX */
00252 double WDN::f2(vector<float>& pressure)
00253 {
00254 #ifdef DEBUG
00255   cout << "WDN::f2()" << endl;
00256 #endif
00257 
00258   vector<double> frac_met(network.n, 0);
00259   double weightedSum = 0, 
00260          totalQ      = 0;
00261     
00262   /* Determine Q_met_j's */
00263   for (int j = 0; j < network.n; j++)
00264   {
00265     if (pressure[j] < pressureZero)
00266       frac_met[j] = 0;
00267     else if (pressure[j] > pressureReq)
00268       frac_met[j] = 1;
00269     else // pressureZero <= pressure[j] <= pressureReq
00270       frac_met[j] = sqrt((pressure[j] - pressureZero) / (pressureReq - pressureZero));
00271   }
00272   
00273   for (int j = 0; j < network.n; j++)
00274   {
00275     weightedSum += frac_met[j] * network.Q[j];
00276     totalQ += network.Q[j];
00277   }
00278   
00279   return (weightedSum / totalQ);
00280 }       
00281 
00282 /* f3: System Entropy -> MAX */
00283 double WDN::f3(vector<float>& flow)
00284 {
00285 #ifdef DEBUG
00286   cout << "WDN::f3()" << endl;
00287 #endif
00288 
00289   vector<double> in(network.n, 0),
00290                  s(network.n, 0);
00291   double IN = 0, 
00292          S  = 0;
00293          
00294   /* Determine in_j's and calculate IN */     
00295   for (int j = 0; j < network.n; j++)
00296   {  
00297     /* New pipes */  
00298     for (int i = 0; i < network.m; i++)
00299     {      
00300       if ((flow[i] > 0 && j == network.pipe[i].endNode) ||
00301           (flow[i] < 0 && j == network.pipe[i].beginNode))
00302         in[j] += fabs(flow[i]);
00303     }
00304 
00305     /* Existing pipes */
00306     if (parallelExp)
00307     {
00308       for (int i = 0; i < network.m; i++)
00309       {      
00310         if ((flow[i+network.m] > 0 && j == network.existPipe[i].endNode) ||
00311             (flow[i+network.m] < 0 && j == network.existPipe[i].beginNode))
00312           in[j] += fabs(flow[i+network.m]);
00313       }
00314     }
00315 
00316     IN += in[j];
00317   }
00318   
00319   /* Calculate s_j's and S */
00320   for (int j = 0; j < network.n; j++)
00321   {
00322     /* New pipes */  
00323     for (int i = 0; i < network.m; i++)
00324     {
00325       if ((flow[i] > 0 && j == network.pipe[i].endNode) ||
00326           (flow[i] < 0 && j == network.pipe[i].beginNode))
00327         s[j] -= (fabs(flow[i]) / in[j]) * log(fabs(flow[i]) / in[j]); 
00328     }
00329 
00330     /* Existing pipes */
00331     if (parallelExp)
00332     {
00333       for (int i = 0; i < network.m; i++)
00334       {
00335         if ((flow[i+network.m] > 0 && j == network.existPipe[i].endNode) ||
00336             (flow[i+network.m] < 0 && j == network.existPipe[i].beginNode))
00337           s[j] -= (fabs(flow[i+network.m]) / in[j]) * log(fabs(flow[i+network.m]) / in[j]); 
00338       }
00339     }
00340 
00341     S += (in[j] / IN) * (s[j] - log(in[j] / IN));
00342   }
00343   
00344   /* Return the exponential value of S */ 
00345   return exp(S);
00346 }       
00347 
00348 /* Shutdown EPANET simulator */
00349 void WDN::close()
00350 {
00351 #ifdef DEBUG
00352   cout << "WDN::close()" << endl;
00353 #endif
00354 
00355   ENcloseH();
00356   ENclose();
00357 }
00358 

Generated on Tue Oct 4 2011 16:25:19 for WDN by  doxygen 1.7.2