/*
* Copyright (C) 2012 Addition, Lda. (addition at addition dot pt)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package org.addition.epanet;
import org.addition.epanet.hydraulic.HydraulicSim;
import org.addition.epanet.hydraulic.io.AwareStep;
import org.addition.epanet.hydraulic.io.HydraulicReader;
import org.addition.epanet.network.FieldsMap;
import org.addition.epanet.network.Network;
import org.addition.epanet.network.PropertiesMap;
import org.addition.epanet.network.io.input.InputParser;
import org.addition.epanet.network.structures.Demand;
import org.addition.epanet.network.structures.Link;
import org.addition.epanet.network.structures.Node;
import org.addition.epanet.quality.QualitySim;
import org.addition.epanet.util.ENException;
import org.addition.epanet.util.Utilities;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
public class EPATool {
public static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");
public static void consoleLog(String msg) {
System.out.println(msg + " " + TIME_FORMAT.format(new Date(System.currentTimeMillis())));
}
public static String convertToScientifcNotation(Double value, double max_threshold, double min_threshold, int decimal) {
if (value == null)
return null;
if (value != 0.0 && (Math.abs(value) > max_threshold || Math.abs(value) < min_threshold))
return String.format("%." + decimal + "e", value);
return String.format("%." + decimal + "f", value);
}
static enum NodeVariableType {
ELEVATION("ELEVATION", FieldsMap.Type.ELEV),
PRESSURE("PRESSURE", FieldsMap.Type.PRESSURE),
HEAD("HEAD", FieldsMap.Type.HEAD),
QUALITY("QUALITY", FieldsMap.Type.QUALITY),
INITQUALITY("INITQUALITY", FieldsMap.Type.QUALITY),
BASEDEMAND("BASEDEMAND", FieldsMap.Type.DEMAND),
DEMAND("DEMAND", FieldsMap.Type.DEMAND);
public final String name;
public final FieldsMap.Type type;
NodeVariableType(String name, FieldsMap.Type type) {
this.name = name;
this.type = type;
}
public double getValue(FieldsMap fmap, AwareStep step, Node node, int index) throws ENException {
switch (this) {
case BASEDEMAND: {
double dsum = 0;
for (Demand demand : node.getDemand()) {
dsum += demand.getBase();
}
return fmap.revertUnit(type, dsum);
}
case ELEVATION:
return fmap.revertUnit(type, node.getElevation());
case DEMAND:
return step != null ? step.getNodeDemand(index, node, fmap) : 0;
case HEAD:
return step != null ? step.getNodeHead(index, node, fmap) : 0;
case INITQUALITY: {
double dsum = 0;
for (double v : node.getC0()) {
dsum += v;
}
return dsum != 0 ? fmap.revertUnit(type, dsum / node.getC0().length) : fmap.revertUnit(type, dsum);
}
case PRESSURE:
return step != null ? step.getNodePressure(index, node, fmap) : 0;
case QUALITY:
return step != null ? step.getNodeQuality(index) : 0;
default:
return 0.0;
}
}
}
static enum LinkVariableType {
LENGHT("LENGHT", FieldsMap.Type.LENGTH),
DIAMETER("DIAMETER", FieldsMap.Type.DIAM),
ROUGHNESS("ROUGHNESS", null),
FLOW("FLOW", FieldsMap.Type.FLOW),
VELOCITY("VELOCITY", FieldsMap.Type.VELOCITY),
UNITHEADLOSS("UNITHEADLOSS", FieldsMap.Type.HEADLOSS),
FRICTIONFACTOR("FRICTIONFACTOR", FieldsMap.Type.FRICTION),
QUALITY("QUALITY", FieldsMap.Type.QUALITY);
public final String name;
public final FieldsMap.Type type;
LinkVariableType(String name, FieldsMap.Type type) {
this.name = name;
this.type = type;
}
public double getValue(PropertiesMap.FormType formType, FieldsMap fmap, AwareStep step, Link link, int index) throws ENException {
switch (this) {
case LENGHT:
return fmap.revertUnit(type, link.getLenght());
case DIAMETER:
return fmap.revertUnit(type, link.getDiameter());
case ROUGHNESS:
if (link.getType() == Link.LinkType.PIPE && formType == PropertiesMap.FormType.DW)
return fmap.revertUnit(FieldsMap.Type.DIAM, link.getRoughness());
else
return link.getRoughness();
case FLOW:
return step != null ? Math.abs(step.getLinkFlow(index, link, fmap)) : 0;
case VELOCITY:
return step != null ? Math.abs(step.getLinkVelocity(index, link, fmap)) : 0;
case UNITHEADLOSS:
return step != null ? step.getLinkHeadLoss(index, link, fmap) : 0;
case FRICTIONFACTOR:
return step != null ? step.getLinkFriction(index, link, fmap) : 0;
case QUALITY:
return step != null ? fmap.revertUnit(type, step.getLinkAvrQuality(index)) : 0;
default:
return 0.0;
}
}
}
public static void main(String[] args) {
Logger log = Logger.getLogger(EPATool.class.toString());
log.setUseParentHandlers(false);
File hydFile = null;
File qualFile = null;
Network net = new Network();
PropertiesMap pMap = null;
List<NodeVariableType> nodesVariables = new ArrayList<NodeVariableType>();
List<LinkVariableType> linksVariables = new ArrayList<LinkVariableType>();
File inFile = null;
List<Long> targetTimes = new ArrayList<Long>();
List<String> targetNodes = new ArrayList<String>();
List<String> targetLinks = new ArrayList<String>();
int parseMode = 0;
for (int i = 0; i < args.length; i++) {
if (args[i].endsWith(".inp")) {
parseMode = 0;
inFile = new File(args[i]);
if (!inFile.exists()) {
consoleLog("END_RUN_ERR");
System.out.println("File not found !");
return;
}
continue;
} else if (args[i].equals("-T")) {
parseMode = 1;
continue;
} else if (args[i].equals("-N")) {
parseMode = 2;
continue;
} else if (args[i].equals("-L")) {
parseMode = 3;
continue;
}
if (parseMode == 1) {
targetTimes.add((long) (Utilities.getHour(args[i], "") * 3600));
} else if (parseMode == 2) {
targetNodes.add(args[i]);
} else if (parseMode == 3) {
targetLinks.add(args[i]);
}
}
try {
InputParser parserINP = InputParser.create(Network.FileType.INP_FILE, log);
parserINP.parse(net, inFile);
pMap = net.getPropertiesMap();
if (targetTimes.size() > 0) {
for (Long time : targetTimes) {
String epanetTime = Utilities.getClockTime(time);
if (time < pMap.getRstart())
throw new Exception("Target time \"" + epanetTime + "\" smaller than simulation start time");
if (time > pMap.getDuration())
throw new Exception("Target time \"" + epanetTime + "\" bigger than simulation duration");
if ((time - pMap.getRstart()) % pMap.getRstep() != 0)
throw new Exception("Target time \"" + epanetTime + "\" not found");
}
}
for (String nodeName : targetNodes) {
if (net.getNode(nodeName) == null)
throw new Exception("Node \"" + nodeName + "\" not found");
}
for (String linkName : targetLinks) {
if (net.getLink(linkName) == null)
throw new Exception("Link \"" + linkName + "\" not found");
}
nodesVariables.add(NodeVariableType.ELEVATION);
nodesVariables.add(NodeVariableType.BASEDEMAND);
if (!pMap.getQualflag().equals(PropertiesMap.QualType.NONE))
nodesVariables.add(NodeVariableType.INITQUALITY);
nodesVariables.add(NodeVariableType.PRESSURE);
nodesVariables.add(NodeVariableType.HEAD);
nodesVariables.add(NodeVariableType.DEMAND);
if (!pMap.getQualflag().equals(PropertiesMap.QualType.NONE)) nodesVariables.add(NodeVariableType.QUALITY);
linksVariables.add(LinkVariableType.LENGHT);
linksVariables.add(LinkVariableType.DIAMETER);
linksVariables.add(LinkVariableType.ROUGHNESS);
linksVariables.add(LinkVariableType.FLOW);
linksVariables.add(LinkVariableType.VELOCITY);
linksVariables.add(LinkVariableType.UNITHEADLOSS);
linksVariables.add(LinkVariableType.FRICTIONFACTOR);
if (!pMap.getQualflag().equals(PropertiesMap.QualType.NONE)) linksVariables.add(LinkVariableType.QUALITY);
hydFile = File.createTempFile("hydSim", "bin");
consoleLog("START_RUNNING");
HydraulicSim hydSim = new HydraulicSim(net, log);
hydSim.simulate(hydFile);
if (!net.getPropertiesMap().getQualflag().equals(PropertiesMap.QualType.NONE)) {
qualFile = File.createTempFile("qualSim", "bin");
QualitySim q = new QualitySim(net, log);
q.simulate(hydFile, qualFile);
}
HydraulicReader hydReader = new HydraulicReader(new RandomAccessFile(hydFile, "r"));
BufferedWriter nodesTextWriter = null;
BufferedWriter linksTextWriter = null;
File nodesOutputFile = null;
File linksOutputFile = null;
if (targetNodes.size() == 0 && targetLinks.size() == 0 || targetNodes.size() > 0) {
nodesOutputFile = new File(inFile.getAbsolutePath() + ".nodes.out");
nodesTextWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(nodesOutputFile), "UTF-8"));
nodesTextWriter.write("\t");
for (NodeVariableType nodeVar : nodesVariables) {
nodesTextWriter.write("\t");
nodesTextWriter.write(nodeVar.name);
}
nodesTextWriter.write("\n\t");
for (NodeVariableType nodeVar : nodesVariables) {
nodesTextWriter.write("\t");
nodesTextWriter.write(net.getFieldsMap().getField(nodeVar.type).getUnits());
}
nodesTextWriter.write("\n");
}
if (targetNodes.size() == 0 && targetLinks.size() == 0 || targetLinks.size() > 0) {
linksOutputFile = new File(inFile.getAbsolutePath() + ".links.out");
linksTextWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(linksOutputFile), "UTF-8"));
linksTextWriter.write("\t");
for (LinkVariableType linkVar : linksVariables) {
linksTextWriter.write("\t");
linksTextWriter.write(linkVar.name);
}
linksTextWriter.write("\n\t");
for (LinkVariableType linkVar : linksVariables) {
linksTextWriter.write("\t");
if (linkVar.type == null) {
continue;
}
linksTextWriter.write(net.getFieldsMap().getField(linkVar.type).getUnits());
}
linksTextWriter.write("\n");
}
for (long time = pMap.getRstart(); time <= pMap.getDuration(); time += pMap.getRstep()) {
AwareStep step = hydReader.getStep((int) time);
int i = 0;
if (targetTimes.size() > 0 && !targetTimes.contains(time))
continue;
if (nodesTextWriter != null) {
for (Node node : net.getNodes()) {
if (targetNodes.size() > 0 && !targetNodes.contains(node.getId()))
continue;
nodesTextWriter.write(node.getId());
nodesTextWriter.write("\t");
nodesTextWriter.write(Utilities.getClockTime(time));
for (NodeVariableType nodeVar : nodesVariables) {
nodesTextWriter.write("\t");
Double val = nodeVar.getValue(net.getFieldsMap(), step, node, i);
nodesTextWriter.write(convertToScientifcNotation(val, 1000, 0.01, 2));
}
nodesTextWriter.write("\n");
i++;
}
}
i = 0;
if (linksTextWriter != null) {
for (Link link : net.getLinks()) {
if (targetLinks.size() > 0 && !targetLinks.contains(link.getId()))
continue;
linksTextWriter.write(link.getId());
linksTextWriter.write("\t");
linksTextWriter.write(Utilities.getClockTime(time));
for (LinkVariableType linkVar : linksVariables) {
linksTextWriter.write("\t");
Double val = linkVar.getValue(net.getPropertiesMap().getFormflag(), net.getFieldsMap(), step, link, i);
linksTextWriter.write(convertToScientifcNotation(val, 1000, 0.01, 2));
}
linksTextWriter.write("\n");
i++;
}
}
}
if (nodesTextWriter != null) {
nodesTextWriter.close();
consoleLog("NODES FILE \"" + nodesOutputFile.getAbsolutePath() + "\"");
}
if (linksTextWriter != null) {
linksTextWriter.close();
consoleLog("LINKS FILES \"" + nodesOutputFile.getAbsolutePath() + "\"");
}
consoleLog("END_RUN_OK");
} catch (ENException e) {
consoleLog("END_RUN_ERR");
e.printStackTrace();
} catch (IOException e) {
consoleLog("END_RUN_ERR");
e.printStackTrace();
} catch (Exception e) {
consoleLog("END_RUN_ERR");
e.printStackTrace();
}
if (hydFile != null)
hydFile.delete();
if (qualFile != null)
qualFile.delete();
}
}