/*
* 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 org.addition.epanet.msx.EnumTypes.*;
import java.io.*;
public class Output {
public void loadDependencies(EpanetMSX epa) {
this.MSX = epa.getNetwork();
quality = epa.getQuality();
}
Network MSX; // MSX project data
long ResultsOffset; // Offset byte where results begin
long NodeBytesPerPeriod; // Bytes per time period used by all nodes
static long LinkBytesPerPeriod; // Bytes per time period used by all links
private Quality quality;
DataOutputStream outStream;
// opens an MSX binary output file.
int MSXout_open(File output) throws IOException {
// Close output file if already opened
//MSX.OutFile.close();
//
//// Try to open the file
//if(!MSX.OutFile.openAsBinaryWritter())
// return ErrorCodeType.ERR_OPEN_OUT_FILE.id;
//
//
//// open a scratch output file for statistics
//if ( MSX.Statflag == TstatType.SERIES ) //MSX.TmpOutFile.file = MSX.OutFile.file;
// MSX.TmpOutFile = MSX.OutFile;
//else
//if ( !MSX.TmpOutFile.openAsBinaryWritter())
// return ErrorCodeType.ERR_OPEN_OUT_FILE.id;
outStream = new DataOutputStream(new FileOutputStream(output));
// write initial results to file
MSX.Nperiods = 0;
MSXout_saveInitialResults(output);
return 0;
}
void writeString(DataOutputStream stream,String str, int size )
{
char[] buff = null;
if(str!=null)
buff = str.toCharArray();
for(int i = 0;i<size;i++)
{
try {
if(buff!=null && i<buff.length)
stream.writeByte(buff[i]);
else
stream.writeByte('\0');
} catch (IOException e) {
return;
}
}
}
// Saves general information to beginning of MSX binary output file.
int MSXout_saveInitialResults(File output) throws IOException {
//MSX.OutFile.close();
//MSX.OutFile.openAsBinaryWritter(); // rewind
//DataOutputStream dout = (DataOutputStream)MSX.OutFile.getFileIO();
//try {
// outStream.writeInt(Constants.MAGICNUMBER); //Magic number
// outStream.writeInt(Constants.VERSION); //Version number
// outStream.writeInt(MSX.Nobjects[ObjectTypes.NODE.id]); //Number of nodes
// outStream.writeInt(MSX.Nobjects[ObjectTypes.LINK.id]); //Number of links
// outStream.writeInt(MSX.Nobjects[ObjectTypes.SPECIES.id]);//Number of species
// outStream.writeInt((int)MSX.Rstep); //Reporting step size
//
// for (int m=1; m<=MSX.Nobjects[ObjectTypes.SPECIES.id]; m++){
// int n = MSX.Species[m].getId().length();
// outStream.writeInt(n); //Length of species ID
// writeString(outStream,MSX.Species[m].getId(),n); //Species ID string
// }
//
// for (int m=1; m<=MSX.Nobjects[ObjectTypes.SPECIES.id]; m++){
// writeString(outStream,MSX.Species[m].getUnits(),Constants.MAXUNITS); //Species mass units
// }
//
//} catch (IOException e) {
// return 0;
//}
//outStream.close();
ResultsOffset = 0;// output.length();
outStream = new DataOutputStream(new FileOutputStream(output,true));
NodeBytesPerPeriod = MSX.Nobjects[ObjectTypes.NODE.id]*MSX.Nobjects[ObjectTypes.SPECIES.id]*4;
LinkBytesPerPeriod = MSX.Nobjects[ObjectTypes.LINK.id]*MSX.Nobjects[ObjectTypes.SPECIES.id]*4;
return 0;
}
// Saves computed species concentrations for each node and link at the
// current time period to the temporary MSX binary output file (which
// will be the same as the permanent MSX binary file if time series
// values were specified as the reported statistic, which is the
// default case).
int MSXout_saveResults()
{
int m, j;
double x;
//DataOutputStream dout = (DataOutputStream)MSX.TmpOutFile.getFileIO();
for (m=1; m<=MSX.Nobjects[ObjectTypes.SPECIES.id]; m++)
{
for (j=1; j<=MSX.Nobjects[ObjectTypes.NODE.id]; j++)
{
x = quality.MSXqual_getNodeQual(j, m);
//if(j==462){
// System.out.println("462 : " + x);
//}
//if(j==79){
// System.out.println("79 : " + x);
//}
try {
outStream.writeFloat((float)x);//fwrite(&x, sizeof(REAL4), 1, MSX.TmpOutFile.file);
} catch (IOException e) {}
}
}
for (m=1; m<=MSX.Nobjects[ObjectTypes.SPECIES.id]; m++)
{
for (j=1; j<=MSX.Nobjects[ObjectTypes.LINK.id]; j++)
{
x = quality.MSXqual_getLinkQual(j, m);
try{
outStream.writeFloat((float)x);//fwrite(&x, sizeof(REAL4), 1, MSX.TmpOutFile.file);
}
catch (IOException e){}
}
}
return 0;
}
// Saves any statistical results plus the following information to the end
// of the MSX binary output file:
// - byte offset into file where WQ results for each time period begins,
// - total number of time periods written to the file,
// - any error code generated by the analysis (0 if there were no errors),
// - the Magic Number to indicate that the file is complete.
int MSXout_saveFinalResults()
{
int n;
int magic = Constants.MAGICNUMBER;
int err = 0;
// Save statistical results to the file
//if ( MSX.Statflag != TstatType.SERIES )
// err = saveStatResults(out);
if ( err > 0 )
return err;
// Write closing records to the file
try{
n = (int)ResultsOffset;
outStream.writeInt(n);
n = (int)MSX.Nperiods;
outStream.writeInt(n);
n = MSX.ErrCode;
outStream.writeInt(n);
outStream.writeInt(magic);
}
catch (IOException e){}
return 0;
}
// retrieves a result for a specific node from the MSX binary output file.
public float MSXout_getNodeQual(RandomAccessFile raf,int k, int j, int m)
{
float c=0.0f;
long bp = ResultsOffset + k * (NodeBytesPerPeriod + LinkBytesPerPeriod);
bp += ((m-1)*MSX.Nobjects[ObjectTypes.NODE.id] + (j-1)) * 4;
try {
raf.seek(bp);
c = raf.readFloat();
} catch (IOException e) {}
return c;
}
// retrieves a result for a specific link from the MSX binary output file.
public float MSXout_getLinkQual(RandomAccessFile raf,int k, int j, int m)
{
float c=0.0f;
long bp = ResultsOffset + ((k+1)*NodeBytesPerPeriod) + (k*LinkBytesPerPeriod);
bp += ((m-1)*MSX.Nobjects[ObjectTypes.LINK.id] + (j-1)) * 4;
try {
raf.seek(bp);
c = raf.readFloat();
} catch (IOException e) {}
return c;
}
// Saves time statistic results (average, min., max., or range) for each
// node and link to the permanent binary output file.
//int saveStatResults(RandomAccessFile raf,DataOutputStream dout)
//{
// int m, err = 0;
// float [] x;
// double[] stats1;
// double[] stats2;
//
// // Create arrays used to store statistics results
//
// if ( MSX.Nperiods <= 0 ) return err;
// m = Math.max(MSX.Nobjects[ObjectTypes.NODE.id], MSX.Nobjects[ObjectTypes.LINK.id]);
// x = new float[m+1];
// stats1 = new double[m+1];
// stats2 = new double[m+1];
//
// // Get desired statistic for each node & link and save to binary file
//
// //if ( x && stats1 && stats2 )
// {
// for (m = 1; m <= MSX.Nobjects[ObjectTypes.SPECIES.id]; m++ )
// {
// getStatResults(raf,ObjectTypes.NODE, m, stats1, stats2, x);
// //fwrite(x+1, sizeof(REAL4), MSX.Nobjects[ObjectTypes.NODE.id], MSX.OutFile.file);
// for(int ij = 0;ij<MSX.Nobjects[ObjectTypes.NODE.id];ij++)
// try {
// dout.writeFloat(x[ij+1]);
// } catch (IOException e) {
//
// }
//
// }
// for (m = 1; m <= MSX.Nobjects[ObjectTypes.SPECIES.id]; m++)
// {
// getStatResults(raf,ObjectTypes.LINK, m, stats1, stats2, x);
// //fwrite(x+1, sizeof(REAL4), MSX.Nobjects[ObjectTypes.LINK.id], MSX.OutFile.file);
// for(int ij = 0;ij<MSX.Nobjects[ObjectTypes.LINK.id];ij++)
// try {
// dout.writeFloat(x[ij+1]);
// } catch (IOException e) {
//
// }
// }
// MSX.Nperiods = 1;
// }
//
// return err;
//}
// Reads all results for a given type of object from the temporary
// binary output file and computes the required statistic (average,
// min., max., or range) for each object.
//void getStatResults(RandomAccessFile raf,ObjectTypes objType, int m, double [] stats1, double [] stats2,
// float [] x)
//{
// int j, k;
// int n = MSX.Nobjects[objType.id];
// long bp;
//
// // Initialize work arrays
// for (j = 1; j <= n; j++)
// {
// stats1[j] = 0.0;
// stats2[j] = 0.0;
// }
//
// // For all time periods
// byte [] readBuff = new byte[n*4];
// ByteBuffer buffWrapper = ByteBuffer.wrap(readBuff);
// for (k = 0; k < MSX.Nperiods; k++)
// {
//
// // position file at start of time period
// bp = k*(NodeBytesPerPeriod + LinkBytesPerPeriod);
// if ( objType == ObjectTypes.NODE )
// {
// bp += (m-1) * MSX.Nobjects[ObjectTypes.NODE.id] * 4;
// }
// if ( objType == ObjectTypes.LINK)
// {
// bp += NodeBytesPerPeriod +
// (m-1) * MSX.Nobjects[ObjectTypes.LINK.id] * 4;
// }
//
// // read concentrations and update stats for all objects
// try{
// raf.seek(bp);
// raf.read(readBuff);
//
// for(int i = 0;i<n;i++)
// x[i+1] = buffWrapper.getFloat(i<<2);
// }
// catch(IOException e){
// continue;
// }
//
//
// if (MSX.Statflag == TstatType.AVGERAGE){
// for (j = 1; j <= n; j++) stats1[j] += x[j];
// }
// else
// for (j = 1; j <= n; j++)
// {
// stats1[j] = Math.min(stats1[j], x[j]);
// stats2[j] = Math.max(stats2[j], x[j]);
// }
// }
//
// // Place final stat value for each object in x
// if (MSX.Statflag == TstatType.AVGERAGE){
// for ( j = 1; j <= n; j++) stats1[j] /= (double)MSX.Nperiods;
// }
//
// if (MSX.Statflag == TstatType.RANGE){
// for ( j = 1; j <= n; j++)
// stats1[j] = Math.abs(stats2[j] - stats1[j]);
// }
//
// if(MSX.Statflag == TstatType.MAXIMUM){
// for ( j = 1; j <= MSX.Nobjects[ObjectTypes.NODE.id]; j++) stats1[j] = stats2[j];
// }
//
// for (j = 1; j <= n; j++)
// x[j] = (float)stats1[j];
//}
}