/* * 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.msx; import java.io.BufferedReader; import java.io.IOException; import java.util.logging.Logger; import org.addition.epanet.msx.EnumTypes.*; import org.addition.epanet.msx.Structures.MathExpr; import org.addition.epanet.msx.Structures.Source; public class InpReader { Logger log; private static final int MAXERRS = 100; // Max. input errors reported private Network MSX; private ENToolkit2 epanet; private Project project; public void loadDependencies(EpanetMSX epa) { this.MSX = epa.getNetwork(); this.epanet = epa.getENToolkit(); this.project = epa.getProject(); } // Error codes (401 - 409) private enum InpErrorCodes { INP_ERR_FIRST (400), ERR_LINE_LENGTH (401), ERR_ITEMS (402), ERR_KEYWORD (403), ERR_NUMBER (404), ERR_NAME (405), ERR_RESERVED_NAME (406), ERR_DUP_NAME (407), ERR_DUP_EXPR (408), ERR_MATH_EXPR (409), INP_ERR_LAST (410); public final int id; InpErrorCodes(int val){this.id = val;} }; // Respective error messages. private static String [] InpErrorTxt = {"", "Error 401 (too many characters)", "Error 402 (too few input items)", "Error 403 (invalid keyword)", "Error 404 (invalid numeric value)", "Error 405 (reference to undefined object)", "Error 406 (illegal use of a reserved name)", "Error 407 (name already used by another object)", "Error 408 (species already assigned an expression)", "Error 409 (illegal math expression)"}; // Reads multi-species input file to determine number of system objects. int countMsxObjects(BufferedReader reader) { String line; // line from input data file SectionType sect = null; // input data sections int errcode = 0; // error code int errsum = 0; // number of errors found long lineCount = 0; //MSX.Msg+=MSX.MsxFile.getFilename(); //epanet.ENwriteline(MSX.Msg); //epanet.ENwriteline(""); //BufferedReader reader = (BufferedReader)MSX.MsxFile.getFileIO(); for(;;) { try{ line = reader.readLine(); } catch(IOException e){ break; } if(line == null) break; errcode = 0; line = line.trim(); lineCount++; int comentPosition = line.indexOf(';'); if(comentPosition!=-1) line = line.substring(0,comentPosition); if (line.length() == 0) continue; String[] tok = line.split("[ \t]+"); if ( tok.length == 0 || tok[0].length() >0 && tok[0].charAt(0) == ';' ) continue; int [] sect_temp = new int[1]; if ( getNewSection(tok[0], Constants.MsxSectWords, sect_temp) !=0 ){ sect = SectionType.values()[sect_temp[0]]; continue; } if ( sect == SectionType.s_SPECIES ) errcode = addSpecies(tok); if ( sect == SectionType.s_COEFF ) errcode = addCoeff(tok); if ( sect == SectionType.s_TERM ) errcode = addTerm(tok); if ( sect == SectionType.s_PATTERN ) errcode = addPattern(tok); if ( errcode!=0 ) { writeInpErrMsg(errcode, Constants.MsxSectWords[sect.id], line,(int) lineCount); errsum++; if (errsum >= MAXERRS ) break; } } //return error code if ( errsum > 0 ) return ErrorCodeType.ERR_MSX_INPUT.id; return errcode; } // Queries EPANET database to determine number of network objects. int countNetObjects() { MSX.Nobjects[ObjectTypes.NODE.id] = epanet.ENgetcount(ENToolkit2.EN_NODECOUNT); MSX.Nobjects[ObjectTypes.TANK.id] = epanet.ENgetcount(ENToolkit2.EN_TANKCOUNT); MSX.Nobjects[ObjectTypes.LINK.id] = epanet.ENgetcount(ENToolkit2.EN_LINKCOUNT); return 0; } // retrieves required input data from the EPANET project data. int readNetData() { int i, k, n, t = 0; int n1 = 0, n2 = 0; float diam = 0.0f, len = 0.0f, v0 = 0.0f, xmix = 0.0f, vmix = 0.0f; float roughness = 0.0f; // Get flow units & time parameters MSX.Flowflag = FlowUnitsType.values()[epanet.ENgetflowunits()]; if ( MSX.Flowflag.ordinal() >= FlowUnitsType.LPS.ordinal())//EN_LPS ) MSX.Unitsflag = UnitSystemType.SI; else MSX.Unitsflag = UnitSystemType.US; MSX.Dur = epanet.ENgettimeparam(ENToolkit2.EN_DURATION); MSX.Qstep = epanet.ENgettimeparam(ENToolkit2.EN_QUALSTEP); MSX.Rstep = epanet.ENgettimeparam(ENToolkit2.EN_REPORTSTEP); MSX.Rstart = epanet.ENgettimeparam(ENToolkit2.EN_REPORTSTART); MSX.Pstep = epanet.ENgettimeparam(ENToolkit2.EN_PATTERNSTEP); MSX.Pstart = epanet.ENgettimeparam(ENToolkit2.EN_PATTERNSTART); MSX.Statflag = TstatType.values()[(int)epanet.ENgettimeparam(ENToolkit2.EN_STATISTIC)]; // Read tank/reservoir data n = MSX.Nobjects[ObjectTypes.NODE.id] - MSX.Nobjects[ObjectTypes.TANK.id]; for (i=1; i<=MSX.Nobjects[ObjectTypes.NODE.id]; i++) { k = i - n; if ( k > 0 ) { try{ t = epanet.ENgetnodetype(i); v0 = epanet.ENgetnodevalue(i, ENToolkit2.EN_INITVOLUME); xmix = epanet.ENgetnodevalue(i, ENToolkit2.EN_MIXMODEL); vmix = epanet.ENgetnodevalue(i, ENToolkit2.EN_MIXZONEVOL); } catch(Exception e){return Integer.parseInt(e.getMessage());} MSX.Node[i].setTank(k); MSX.Tank[k].setNode(i); if ( t == ENToolkit2.EN_RESERVOIR ) MSX.Tank[k].setA( 0.0 ); else MSX.Tank[k].setA( 1.0 ); MSX.Tank[k].setV0(v0); MSX.Tank[k].setMixModel((int)xmix); MSX.Tank[k].setvMix(vmix); } } // Read link data for (i=1; i<=MSX.Nobjects[ObjectTypes.LINK.id]; i++) { int [] n_temp; try { n_temp = epanet.ENgetlinknodes(i); } catch (Exception e) {return Integer.parseInt(e.getMessage());} n1 = n_temp[0]; n2 = n_temp[1]; try{ diam = epanet.ENgetlinkvalue(i, ENToolkit2.EN_DIAMETER); len = epanet.ENgetlinkvalue(i, ENToolkit2.EN_LENGTH); roughness = epanet.ENgetlinkvalue(i, ENToolkit2.EN_ROUGHNESS); } catch(Exception e){return Integer.parseInt(e.getMessage());} MSX.Link[i].setN1(n1); MSX.Link[i].setN2(n2); MSX.Link[i].setDiam(diam); MSX.Link[i].setLen(len); MSX.Link[i].setRoughness(roughness); } return 0; } // Reads multi-species data from the EPANET-MSX input file. int readMsxData(BufferedReader rin) { String line; // line from input data file int sect = -1; // input data sections int errsum = 0; // number of errors found int inperr = 0; // input error code int lineCount = 0; // line count // rewind //MSX.MsxFile.close(); //MSX.MsxFile.openAsTextReader(); //BufferedReader rin = (BufferedReader)MSX.MsxFile.getFileIO(); for(;;){ try { line = rin.readLine(); } catch (IOException e) { break; } if(line==null) break; lineCount++; line = line.trim(); int comentPosition = line.indexOf(';'); if(comentPosition!=-1) line = line.substring(0,comentPosition); if (line.length() == 0) continue; String[] tok = line.split("[ \t]+"); if ( tok.length == 0) continue; if ( getLineLength(line) >= Constants.MAXLINE ) { inperr = InpErrorCodes.ERR_LINE_LENGTH.id; writeInpErrMsg(inperr, Constants.MsxSectWords[sect], line, lineCount); errsum++; } int [] sect_tmp = new int[1]; if ( getNewSection(tok[0], Constants.MsxSectWords,sect_tmp) !=0){ sect = sect_tmp[0]; continue; } inperr = parseLine(SectionType.values()[sect], line, tok); if ( inperr > 0 ) { errsum++; writeInpErrMsg(inperr, Constants.MsxSectWords[sect], line, lineCount); } // Stop if reach end of file or max. error count if (errsum >= MAXERRS) break; } if (errsum > 0) return 200; return 0; } // reads multi-species data from the EPANET-MSX input file. public String MSXinp_getSpeciesUnits(int m) { String units = MSX.Species[m].getUnits(); units+= "/"; if ( MSX.Species[m].getType() == SpeciesType.BULK ) units += "L"; else units += Constants.AreaUnitsWords[MSX.AreaUnits.id]; return units; } // determines number of characters of data in a line of input. int getLineLength(String line) { int index = line.indexOf(';'); if(index!=-1){ return line.substring(0,index).length(); } return line.length(); } // checks if a line begins a new section in the input file. int getNewSection(String tok, String [] sectWords, int [] sect) { int newsect; if(tok.length()==0) return 0; // --- check if line begins with a new section heading if ( tok.charAt(0) == '[' ) { // --- look for section heading in list of section keywords newsect = Utilities.MSXutils_findmatch(tok, sectWords); if ( newsect >= 0 ) sect[0] = newsect; else sect[0] = -1; return 1; } return 0; } // adds a species ID name to the project. int addSpecies(String []Tok) { int errcode = 0; if ( Tok.length < 2 ) return InpErrorCodes.ERR_ITEMS.id; errcode = checkID(Tok[1]); if ( errcode!=0 ) return errcode; if ( project.MSXproj_addObject(ObjectTypes.SPECIES, Tok[1], MSX.Nobjects[ObjectTypes.SPECIES.id]+1) < 0 ) errcode = 101; else MSX.Nobjects[ObjectTypes.SPECIES.id]++; return errcode; } // adds a coefficient ID name to the project. int addCoeff(String [] Tok) { ObjectTypes k; int errcode = 0; // determine the type of coeff. if ( Tok.length < 2 ) return InpErrorCodes.ERR_ITEMS.id; if (Utilities.MSXutils_match(Tok[0], "PARAM")) k = ObjectTypes.PARAMETER; else if (Utilities.MSXutils_match(Tok[0], "CONST")) k = ObjectTypes.CONSTANT; else return InpErrorCodes.ERR_KEYWORD.id; // check for valid id name errcode = checkID(Tok[1]); if ( errcode !=0) return errcode; if ( project.MSXproj_addObject(k, Tok[1], MSX.Nobjects[k.id] + 1) < 0 ) errcode = 101; else MSX.Nobjects[k.id]++; return errcode; } // adds an intermediate expression term ID name to the project. int addTerm(String [] id) { int errcode = checkID(id[0]); if ( errcode == 0 ) { if ( project.MSXproj_addObject(ObjectTypes.TERM, id[0], MSX.Nobjects[ObjectTypes.TERM.id]+1) < 0 ) errcode = 101; else MSX.Nobjects[ObjectTypes.TERM.id]++; } return errcode; } // adds a time pattern ID name to the project. int addPattern(String [] tok) { int errcode = 0; // A time pattern can span several lines if ( project.MSXproj_findObject( ObjectTypes.PATTERN, tok[0]) <= 0 ) { if ( project.MSXproj_addObject(ObjectTypes.PATTERN, tok[0], MSX.Nobjects[ObjectTypes.PATTERN.id]+1) < 0 ) errcode = 101; else MSX.Nobjects[ObjectTypes.PATTERN.id]++; } return errcode; } // checks that an object's name is unique int checkID(String id) { // Check that id name is not a reserved word int i = 1; //while (HydVarWords[i] != NULL) for(String word : Constants.HydVarWords) { if (Utilities.MSXutils_strcomp(id, word)) return InpErrorCodes.ERR_RESERVED_NAME.id; i++; } // Check that id name not used before if ( project.MSXproj_findObject(ObjectTypes.SPECIES, id) > 0 || project.MSXproj_findObject(ObjectTypes.TERM, id) > 0 || project.MSXproj_findObject(ObjectTypes.PARAMETER, id) > 0 || project.MSXproj_findObject(ObjectTypes.CONSTANT, id) > 0 ) return InpErrorCodes.ERR_DUP_NAME.id; return 0; } // parses the contents of a line of input data. int parseLine(SectionType sect, String line, String [] Tok) { switch(sect) { case s_TITLE: MSX.Title = line; break; case s_OPTION: return parseOption(Tok); case s_SPECIES: return parseSpecies(Tok); case s_COEFF: return parseCoeff(Tok); case s_TERM: return parseTerm(Tok); case s_PIPE: return parseExpression(ObjectTypes.LINK, Tok); case s_TANK: return parseExpression(ObjectTypes.TANK, Tok); case s_SOURCE: return parseSource(Tok); case s_QUALITY: return parseQuality(Tok); case s_PARAMETER: return parseParameter(Tok); case s_PATTERN: return parsePattern(Tok); case s_REPORT: return parseReport(Tok); } return 0; } // parses an input line containing a project option. int parseOption(String [] Tok) { int k; // Determine which option is being read if ( Tok.length < 2 ) return 0; k = Utilities.MSXutils_findmatch(Tok[0], Constants.OptionTypeWords); if ( k < 0 ) return InpErrorCodes.ERR_KEYWORD.id; // Parse the value for the given option switch ( OptionType.values()[k] ) { case AREA_UNITS_OPTION: k = Utilities.MSXutils_findmatch(Tok[1], Constants.AreaUnitsWords); if ( k < 0 ) return InpErrorCodes.ERR_KEYWORD.id; MSX.AreaUnits = AreaUnitsType.values()[k]; break; case RATE_UNITS_OPTION: k = Utilities.MSXutils_findmatch(Tok[1], Constants.TimeUnitsWords); if ( k < 0 ) return InpErrorCodes.ERR_KEYWORD.id; MSX.RateUnits = RateUnitsType.values()[k]; break; case SOLVER_OPTION: k = Utilities.MSXutils_findmatch(Tok[1], Constants.SolverTypeWords); if ( k < 0 ) return InpErrorCodes.ERR_KEYWORD.id; MSX.Solver = SolverType.values()[k]; break; case COUPLING_OPTION: k = Utilities.MSXutils_findmatch(Tok[1], Constants.CouplingWords); if ( k < 0 ) return InpErrorCodes.ERR_KEYWORD.id; MSX.Coupling = CouplingType.values()[k]; break; case TIMESTEP_OPTION: k = Integer.parseInt(Tok[1]); if ( k <= 0 ) return InpErrorCodes.ERR_NUMBER.id; MSX.Qstep = k; break; case RTOL_OPTION: { double [] tmp = new double[1]; if ( !Utilities.MSXutils_getDouble(Tok[1], tmp) ) return InpErrorCodes.ERR_NUMBER.id; MSX.DefRtol = tmp[0]; break; } case ATOL_OPTION: { double [] tmp = new double[1]; if ( !Utilities.MSXutils_getDouble(Tok[1], tmp) ) return InpErrorCodes.ERR_NUMBER.id; MSX.DefAtol = tmp[0]; } break; } return 0; } // Parses an input line containing a species variable. int parseSpecies(String [] Tok) { int i; // Get secies index if ( Tok.length < 3 ) return InpErrorCodes.ERR_ITEMS.id; i = project.MSXproj_findObject(ObjectTypes.SPECIES, Tok[1]); if ( i <= 0 ) return InpErrorCodes.ERR_NAME.id; // Get pointer to Species name MSX.Species[i].setId(project.MSXproj_findID(ObjectTypes.SPECIES, Tok[1])); // Get species type if ( Utilities.MSXutils_match(Tok[0], "BULK") ) MSX.Species[i].setType(SpeciesType.BULK); else if ( Utilities.MSXutils_match(Tok[0], "WALL") ) MSX.Species[i].setType(SpeciesType.WALL); else return InpErrorCodes.ERR_KEYWORD.id; // Get Species units MSX.Species[i].setUnits(Tok[2]); // Get Species error tolerance MSX.Species[i].setaTol(0.0); MSX.Species[i].setrTol(0.0); if ( Tok.length >= 4) { double [] tmp= new double[1]; if ( !Utilities.MSXutils_getDouble(Tok[3], tmp))//&MSX.Species[i].aTol) ) MSX.Species[i].setaTol (tmp[0]); return InpErrorCodes.ERR_NUMBER.id; } if ( Tok.length >= 5) { double [] tmp= new double[1]; if ( !Utilities.MSXutils_getDouble(Tok[4], tmp))//&MSX.Species[i].rTol) ) MSX.Species[i].setrTol(tmp[0]); return InpErrorCodes.ERR_NUMBER.id; } return 0; } // parses an input line containing a coefficient definition. int parseCoeff(String [] Tok) { int i, j; double [] x = new double[1]; // Check if variable is a Parameter if ( Tok.length < 2 ) return 0; if ( Utilities.MSXutils_match(Tok[0], "PARAM") ) { // Get Parameter's index i = project.MSXproj_findObject(ObjectTypes.PARAMETER, Tok[1]); if ( i <= 0 ) return InpErrorCodes.ERR_NAME.id; // Get Parameter's value MSX.Param[i].setId(project.MSXproj_findID(ObjectTypes.PARAMETER, Tok[1])); if ( Tok.length >= 3 ) { if (Utilities.MSXutils_getDouble(Tok[2], x)) return InpErrorCodes.ERR_NUMBER.id; MSX.Param[i].setValue(x[0]); for (j=1; j<=MSX.Nobjects[ObjectTypes.LINK.id]; j++) MSX.Link[j].getParam()[i] = x[0]; for (j=1; j<=MSX.Nobjects[ObjectTypes.TANK.id]; j++) MSX.Tank[j].getParam()[i] = x[0]; } return 0; } // Check if variable is a Constant else if ( Utilities.MSXutils_match(Tok[0], "CONST") ) { // Get Constant's index i = project.MSXproj_findObject(ObjectTypes.CONSTANT, Tok[1]); if ( i <= 0 ) return InpErrorCodes.ERR_NAME.id; // Get constant's value MSX.Const[i].setId(project.MSXproj_findID(ObjectTypes.CONSTANT, Tok[1])); MSX.Const[i].setValue(0.0); if ( Tok.length >= 3 ) { double [] tmp = new double[1]; if ( !Utilities.MSXutils_getDouble(Tok[2], tmp))//&MSX.Const[i].value) ) return InpErrorCodes.ERR_NUMBER.id; MSX.Const[i].setValue(tmp[0]); } return 0; } else return InpErrorCodes.ERR_KEYWORD.id; } //============================================================================= // parses an input line containing an intermediate expression term . int parseTerm(String [] Tok) { int i, j; String s = ""; MathExpr expr; // --- get term's name if ( Tok.length < 2 ) return 0; i = project.MSXproj_findObject(ObjectTypes.TERM, Tok[0]); // --- reconstruct the expression string from its tokens for (j=1; j<Tok.length; j++) s+= Tok[j]; // --- convert expression into a postfix stack of op codes //expr = mathexpr_create(s, getVariableCode); expr = MathExpr.create(s, new VariableInterface(){ public double getValue(int id) {return 0;} public int getIndex(String id) {return getVariableCode(id);} }); if ( expr == null ) return InpErrorCodes.ERR_MATH_EXPR.id; // --- assign the expression to a Term object MSX.Term[i].setExpr(expr); return 0; } //============================================================================= // parses an input line containing a math expression. int parseExpression(ObjectTypes classType,String []Tok) { int i, j, k; String s = ""; MathExpr expr; // --- determine expression type if ( Tok.length < 3 ) return InpErrorCodes.ERR_ITEMS.id; k = Utilities.MSXutils_findmatch(Tok[0], Constants.ExprTypeWords); if ( k < 0 ) return InpErrorCodes.ERR_KEYWORD.id; // --- determine species associated with expression i = project.MSXproj_findObject(ObjectTypes.SPECIES, Tok[1]); if ( i < 1 ) return InpErrorCodes.ERR_NAME.id; // --- check that species does not already have an expression if ( classType == ObjectTypes.LINK ) { if ( MSX.Species[i].getPipeExprType() != ExpressionType.NO_EXPR ) return InpErrorCodes.ERR_DUP_EXPR.id; } if ( classType == ObjectTypes.TANK ) { if ( MSX.Species[i].getTankExprType() != ExpressionType.NO_EXPR ) return InpErrorCodes.ERR_DUP_EXPR.id; } // --- reconstruct the expression string from its tokens for (j=2; j<Tok.length; j++) s+= Tok[j]; // --- convert expression into a postfix stack of op codes //expr = mathexpr_create(s, getVariableCode); expr = MathExpr.create(s, new VariableInterface(){ public double getValue(int id) {return 0;} public int getIndex(String id) {return getVariableCode(id);} });//createMathExpr() if ( expr == null ) return InpErrorCodes.ERR_MATH_EXPR.id; // --- assign the expression to the species switch (classType) { case LINK: MSX.Species[i].setPipeExpr(expr); MSX.Species[i].setPipeExprType(ExpressionType.values()[k]); break; case TANK: MSX.Species[i].setTankExpr(expr); MSX.Species[i].setTankExprType(ExpressionType.values()[k]); break; } return 0; } //============================================================================= // parses an input line containing initial species concentrations. int parseQuality(String [] Tok) { int err, i, j, k, m; double [] x = new double[1]; // --- determine if quality value is global or object-specific if ( Tok.length < 3 ) return InpErrorCodes.ERR_ITEMS.id; if ( Utilities.MSXutils_match(Tok[0], "GLOBAL") ) i = 1; else if ( Utilities.MSXutils_match(Tok[0], "NODE") ) i = 2; else if ( Utilities.MSXutils_match(Tok[0], "LINK") ) i = 3; else return InpErrorCodes.ERR_KEYWORD.id; // --- find species index k = 1; if ( i >= 2 ) k = 2; m = project.MSXproj_findObject(ObjectTypes.SPECIES, Tok[k]); if ( m <= 0 ) return InpErrorCodes.ERR_NAME.id; // --- get quality value if ( i >= 2 && Tok.length < 4 ) return InpErrorCodes.ERR_ITEMS.id; k = 2; if ( i >= 2 ) k = 3; if ( !Utilities.MSXutils_getDouble(Tok[k], x) ) return InpErrorCodes.ERR_NUMBER.id; // --- for global specification, set initial quality either for // all nodes or links depending on type of species if ( i == 1) { MSX.C0[m] = x[0]; if ( MSX.Species[m].getType() == SpeciesType.BULK ) { for (j=1; j<=MSX.Nobjects[ObjectTypes.NODE.id]; j++) MSX.Node[j].getC0()[m] = x[0]; } for (j=1; j<=MSX.Nobjects[ObjectTypes.LINK.id]; j++) MSX.Link[j].getC0()[m] = x[0]; } // --- for a specific node, get its index & set its initial quality else if ( i == 2 ) { int [] tmp = new int[1]; err = epanet.ENgetnodeindex(Tok[1], tmp); j = tmp[0]; if ( err!=0 ) return InpErrorCodes.ERR_NAME.id; if ( MSX.Species[m].getType() == SpeciesType.BULK ) MSX.Node[j].getC0()[m] = x[0]; } // --- for a specific link, get its index & set its initial quality else if ( i == 3 ) { int [] tmp = new int[1]; err = epanet.ENgetlinkindex(Tok[1], tmp); j = tmp[0]; if ( err!=0 ) return InpErrorCodes.ERR_NAME.id; MSX.Link[j].getC0()[m] = x[0]; } return 0; } //============================================================================= // parses an input line containing a parameter data. int parseParameter(String [] Tok) { int err, i, j; double x; // --- get parameter name if ( Tok.length < 4 ) return 0; i = project.MSXproj_findObject(ObjectTypes.PARAMETER, Tok[2]); // --- get parameter value double [] x_tmp = new double[1]; if ( !Utilities.MSXutils_getDouble(Tok[3], x_tmp) ) return InpErrorCodes.ERR_NUMBER.id; x = x_tmp[0]; // --- for pipe parameter, get pipe index and update parameter's value if ( Utilities.MSXutils_match(Tok[0], "PIPE") ) { int [] j_tmp = new int [1]; err = epanet.ENgetlinkindex(Tok[1], j_tmp); j = j_tmp[0]; if ( err != 0) return InpErrorCodes.ERR_NAME.id; MSX.Link[j].getParam()[i] = x; } // --- for tank parameter, get tank index and update parameter's value else if ( Utilities.MSXutils_match(Tok[0], "TANK") ) { int [] j_temp = new int [1]; err = epanet.ENgetnodeindex(Tok[1], j_temp); j = j_temp[0]; if ( err!=0 ) return InpErrorCodes.ERR_NAME.id; j = MSX.Node[j].getTank(); if ( j > 0 ) MSX.Tank[j].getParam()[i] = x; } else return InpErrorCodes.ERR_KEYWORD.id; return 0; } //============================================================================= // parses an input line containing a source input data. int parseSource(String [] Tok) { int err, i, j, k, m; double x; Source source = null; // --- get source type if ( Tok.length < 4 ) return InpErrorCodes.ERR_ITEMS.id; k = Utilities.MSXutils_findmatch(Tok[0], Constants.SourceTypeWords); if ( k < 0 ) return InpErrorCodes.ERR_KEYWORD.id; // --- get node index int [] j_tmp = new int[1]; err = epanet.ENgetnodeindex(Tok[1], j_tmp); j = j_tmp[0]; if ( err != 0) return InpErrorCodes.ERR_NAME.id; // --- get species index m = project.MSXproj_findObject(ObjectTypes.SPECIES, Tok[2]); if ( m <= 0 ) return InpErrorCodes.ERR_NAME.id; // --- check that species is a BULK species if ( MSX.Species[m].getType() != SpeciesType.BULK ) return 0; // --- get base strength double [] x_tmp = new double[1]; if ( !Utilities.MSXutils_getDouble(Tok[3], x_tmp) ) return InpErrorCodes.ERR_NUMBER.id; x = x_tmp[0]; // --- get time pattern if present i = 0; if ( Tok.length >= 5 ) { i = project.MSXproj_findObject(ObjectTypes.PATTERN, Tok[4]); if ( i <= 0 ) return InpErrorCodes.ERR_NAME.id; } // --- check if a source for this species already exists /*source = MSX.Node[j].sources; while ( source ) { if ( source->species == m ) break; source = source->next; }*/ for(Source src : MSX.Node[j].getSources()) { if ( src.getSpecies() == m ){ source = src; break; } } // --- otherwise create a new source object if ( source == null ) { source = new Source();//(struct Ssource *) malloc(sizeof(struct Ssource)); //if ( source == NULL ) return 101; //source->next = MSX.Node[j].sources; //MSX.Node[j].sources = source; MSX.Node[j].getSources().add(0,source); } // --- save source's properties source.setType(SourceType.values()[k]); source.setSpecies(m); source.setC0(x); source.setPattern(i); return 0; } //============================================================================= // parses an input line containing a time pattern data. int parsePattern(String [] Tok) { int i; double [] x = new double[1]; //List<Double> listItem = new ArrayList<Double>(); //SnumList *listItem; // --- get time pattern index if ( Tok.length < 2 ) return InpErrorCodes.ERR_ITEMS.id; i = project.MSXproj_findObject(ObjectTypes.PATTERN, Tok[0]); if ( i <= 0 ) return InpErrorCodes.ERR_NAME.id; MSX.Pattern[i].setId(project.MSXproj_findID(ObjectTypes.PATTERN, Tok[0])); // --- begin reading pattern multipliers //k = 1; //while ( k < Tok.length ) for(int k = 1;k< Tok.length;k++)//String token : Tok) { if ( !Utilities.MSXutils_getDouble(Tok[k], x) ) return InpErrorCodes.ERR_NUMBER.id; MSX.Pattern[i].getMultipliers().add(x[0]); /*listItem = (SnumList *) malloc(sizeof(SnumList)); if ( listItem == NULL ) return 101; listItem->value = x; listItem->next = NULL; if ( MSX.Pattern[i].first == NULL ) { MSX.Pattern[i].current = listItem; MSX.Pattern[i].first = listItem; } else { MSX.Pattern[i].current->next = listItem; MSX.Pattern[i].current = listItem; } */ // k++; } return 0; } int parseReport(String [] Tok) { int i, j, k, err; // Get keyword if ( Tok.length < 2 ) return 0; k = Utilities.MSXutils_findmatch(Tok[0], Constants.ReportWords); if ( k < 0 ) return InpErrorCodes.ERR_KEYWORD.id; switch(k) { // Keyword is NODE; parse ID names of reported nodes case 0: if ( Utilities.MSXutils_strcomp(Tok[1], Constants.ALL) ) { for (j=1; j<=MSX.Nobjects[ObjectTypes.NODE.id]; j++) MSX.Node[j].setRpt(true); } else if ( Utilities.MSXutils_strcomp(Tok[1], Constants.NONE) ) { for (j=1; j<=MSX.Nobjects[ObjectTypes.NODE.id]; j++) MSX.Node[j].setRpt(false); } else for (i=1; i<Tok.length; i++) { int [] j_tmp = new int [1]; err = epanet.ENgetnodeindex(Tok[i], j_tmp); j = j_tmp[0]; if ( err != 0) return InpErrorCodes.ERR_NAME.id; MSX.Node[j].setRpt(true); } break; // Keyword is LINK: parse ID names of reported links case 1: if ( Utilities.MSXutils_strcomp(Tok[1], Constants.ALL) ) { for (j=1; j<=MSX.Nobjects[ObjectTypes.LINK.id]; j++) MSX.Link[j].setRpt(true); } else if ( Utilities.MSXutils_strcomp(Tok[1], Constants.NONE) ) { for (j=1; j<=MSX.Nobjects[ObjectTypes.LINK.id]; j++) MSX.Link[j].setRpt(false); } else for (i=1; i<Tok.length; i++) { int j_temp [] = new int [1]; err = epanet.ENgetlinkindex(Tok[i], j_temp); j = j_temp[0]; if ( err != 0) return InpErrorCodes.ERR_NAME.id; MSX.Link[j].setRpt(true); } break; // Keyword is SPECIES; get YES/NO & precision case 2: j = project.MSXproj_findObject(ObjectTypes.SPECIES, Tok[1]); if ( j <= 0 ) return InpErrorCodes.ERR_NAME.id; if ( Tok.length >= 3 ) { if ( Utilities.MSXutils_strcomp(Tok[2], Constants.YES) ) MSX.Species[j].setRpt((char)1); else if ( Utilities.MSXutils_strcomp(Tok[2], Constants.NO) ) MSX.Species[j].setRpt((char)0); else return InpErrorCodes.ERR_KEYWORD.id; } if ( Tok.length >= 4 ) { int [] precision_tmp = new int[1]; if ( !Utilities.MSXutils_getInt(Tok[3], precision_tmp) ); MSX.Species[j].setPrecision(precision_tmp[0]); return InpErrorCodes.ERR_NUMBER.id; } break; // Keyword is FILE: get name of report file case 3: MSX.rptFilename = Tok[1] ; break; // Keyword is PAGESIZE; case 4: int [] pagesize_tmp = new int[1]; if ( !Utilities.MSXutils_getInt(Tok[1], pagesize_tmp) ) return InpErrorCodes.ERR_NUMBER.id; MSX.PageSize = pagesize_tmp[0]; break; } return 0; } //============================================================================= // Finds the index assigned to a species, intermediate term, parameter, or constant that appears in a math expression. int getVariableCode(String id) { int j = project.MSXproj_findObject(ObjectTypes.SPECIES, id); if ( j >= 1 ) return j; j = project.MSXproj_findObject(ObjectTypes.TERM, id); if ( j >= 1 ) return MSX.Nobjects[ObjectTypes.SPECIES.id] + j; j = project.MSXproj_findObject(ObjectTypes.PARAMETER, id); if ( j >= 1 ) return MSX.Nobjects[ObjectTypes.SPECIES.id] + MSX.Nobjects[ObjectTypes.TERM.id] + j; j = project.MSXproj_findObject(ObjectTypes.CONSTANT, id); if ( j >= 1 ) return MSX.Nobjects[ObjectTypes.SPECIES.id] + MSX.Nobjects[ObjectTypes.TERM.id] + MSX.Nobjects[ObjectTypes.PARAMETER.id] + j; j = Utilities.MSXutils_findmatch(id, Constants.HydVarWords); if ( j >= 1 ) return MSX.Nobjects[ObjectTypes.SPECIES.id] + MSX.Nobjects[ObjectTypes.TERM.id] + MSX.Nobjects[ObjectTypes.PARAMETER.id] + MSX.Nobjects[ObjectTypes.CONSTANT.id] + j; return -1; } //============================================================================= // Scans a string for tokens, saving pointers to them //in shared variable Tok[]. //int getTokens(String s) //{ // int len, m, n; // String c; // // // --- begin with no tokens // // for (n = 0; n < MAXTOKS; n++) Tok[n] = NULL; // n = 0; // // // --- truncate s at start of comment // // c = strchr(s,';'); // if (c) *c = '\0'; // len = strlen(s); // // // --- scan s for tokens until nothing left // // while (len > 0 && n < MAXTOKS) // { // m = strcspn(s,SEPSTR); // find token length // if (m == 0) s++; // no token found // else // { // if (*s == '"') // token begins with quote // { // s++; // start token after quote // len--; // reduce length of s // m = strcspn(s,"\"\n"); // find end quote or new line // } // s[m] = '\0'; // null-terminate the token // Tok[n] = s; // save pointer to token // n++; // update token count // s += m+1; // begin next token // } // len -= m+1; // update length of s // } // return(n); //} //============================================================================= void writeInpErrMsg(int errcode, String sect, String line, int lineCount) { String msg; if ( errcode >= InpErrorCodes.INP_ERR_LAST.id || errcode <= InpErrorCodes.INP_ERR_FIRST.id ) { System.out.println(String.format("Error Code = %d", errcode)); } else { System.out.println(String.format("%s at line %d of %s] section:", InpErrorTxt[errcode-InpErrorCodes.INP_ERR_FIRST.id], lineCount, sect)); } //epanet.ENwriteline(""); //epanet.ENwriteline(msg); //epanet.ENwriteline(line); } }