using IStation.Epanet.Enums;
using IStation.Epanet.Network.Structures;
using System.Diagnostics;
namespace IStation.Epanet.Network
{
///Units report properties & conversion support class
public class FieldsMap
{
///Report fields properties.
private readonly Dictionary _fields = new Dictionary();
///Fields units values.
private readonly Dictionary _units = new Dictionary();
///Init fields default configuration
public FieldsMap()
{
try
{
foreach (FieldType type in Enum.GetValues(typeof(FieldType)))
_fields[type] = new Field(type);
GetField(FieldType.FRICTION).Precision = 3;
for (var i = FieldType.DEMAND; i <= FieldType.QUALITY; i++)
GetField(i).Enabled = true;
for (var i = FieldType.FLOW; i <= FieldType.HEADLOSS; i++)
GetField(i).Enabled = true;
}
catch (EnException e)
{
Debug.Print(e.ToString());
}
}
///Get report field properties from type.
/// Field type.
/// Report field.
///
/// Throws
/// If specified type not found.
///
public Field GetField(FieldType fieldType)
{
if (!_fields.TryGetValue(fieldType, out Field value))
throw new EnException(ErrorCode.Err201, fieldType.ParseStr());
return value;
}
///Get conversion value from field type.
/// Field type.
/// Conversion units value (from user units to system units).
///
/// Throws If specified type not found.
///
public double GetUnits(FieldType fieldType)
{
if (!_units.TryGetValue(fieldType, out double value))
throw new EnException(ErrorCode.Err201, fieldType.ParseStr());
return value;
}
///Update fields and units, after loading the INP.
public void Prepare(
UnitsType targetUnits,
FlowUnitsType flowFlag,
PressUnitsType pressFlag,
QualType qualFlag,
string chemUnits,
double spGrav,
TimeSpan hstep)
{
double dcf,
ccf,
qcf,
hcf,
pcf,
wcf;
if (targetUnits == UnitsType.SI)
{
GetField(FieldType.DEMAND).Units = flowFlag.ToString();
GetField(FieldType.ELEV).Units = Keywords.u_METERS;
GetField(FieldType.HEAD).Units = Keywords.u_METERS;
GetField(FieldType.PRESSURE).Units = pressFlag == PressUnitsType.METERS
? Keywords.u_METERS
: Keywords.u_KPA;
GetField(FieldType.LENGTH).Units = Keywords.u_METERS;
GetField(FieldType.DIAM).Units = Keywords.u_MMETERS;
GetField(FieldType.FLOW).Units = flowFlag.ToString();
GetField(FieldType.VELOCITY).Units = Keywords.u_MperSEC;
GetField(FieldType.HEADLOSS).Units = "m" + Keywords.u_per1000M;
GetField(FieldType.FRICTION).Units = "";
GetField(FieldType.POWER).Units = Keywords.u_KW;
dcf = 1000.0 * Constants.MperFT;
qcf = Constants.LPSperCFS;
switch (flowFlag)
{
case FlowUnitsType.Lpm:
qcf = Constants.LPMperCFS;
break;
case FlowUnitsType.Mld:
qcf = Constants.MLDperCFS;
break;
case FlowUnitsType.Cmh:
qcf = Constants.CMHperCFS;
break;
case FlowUnitsType.Cmd:
qcf = Constants.CMDperCFS;
break;
}
hcf = Constants.MperFT;
if (pressFlag == PressUnitsType.METERS) pcf = Constants.MperFT * spGrav;
else pcf = Constants.KPAperPSI * Constants.PSIperFT * spGrav;
wcf = Constants.KWperHP;
}
else
{
GetField(FieldType.DEMAND).Units = flowFlag.ToString();
GetField(FieldType.ELEV).Units = Keywords.u_FEET;
GetField(FieldType.HEAD).Units = Keywords.u_FEET;
GetField(FieldType.PRESSURE).Units = Keywords.u_PSI;
GetField(FieldType.LENGTH).Units = Keywords.u_FEET;
GetField(FieldType.DIAM).Units = Keywords.u_INCHES;
GetField(FieldType.FLOW).Units = flowFlag.ToString();
GetField(FieldType.VELOCITY).Units = Keywords.u_FTperSEC;
GetField(FieldType.HEADLOSS).Units = "ft" + Keywords.u_per1000FT;
GetField(FieldType.FRICTION).Units = "";
GetField(FieldType.POWER).Units = Keywords.u_HP;
dcf = 12.0;
qcf = 1.0;
switch (flowFlag)
{
case FlowUnitsType.Gpm:
qcf = Constants.GPMperCFS;
break;
case FlowUnitsType.Mgd:
qcf = Constants.MGDperCFS;
break;
case FlowUnitsType.Imgd:
qcf = Constants.IMGDperCFS;
break;
case FlowUnitsType.Afd:
qcf = Constants.AFDperCFS;
break;
}
hcf = 1.0;
pcf = Constants.PSIperFT * spGrav;
wcf = 1.0;
}
GetField(FieldType.QUALITY).Units = "";
ccf = 1.0;
switch (qualFlag)
{
case QualType.Chem:
ccf = 1.0 / Constants.LperFT3;
GetField(FieldType.QUALITY).Units = chemUnits;
GetField(FieldType.REACTRATE).Units = chemUnits + Keywords.t_PERDAY;
break;
case QualType.Age:
GetField(FieldType.QUALITY).Units = Keywords.u_HOURS;
break;
case QualType.Trace:
GetField(FieldType.QUALITY).Units = Keywords.u_PERCENT;
break;
}
SetUnits(FieldType.DEMAND, qcf);
SetUnits(FieldType.ELEV, hcf);
SetUnits(FieldType.HEAD, hcf);
SetUnits(FieldType.PRESSURE, pcf);
SetUnits(FieldType.QUALITY, ccf);
SetUnits(FieldType.LENGTH, hcf);
SetUnits(FieldType.DIAM, dcf);
SetUnits(FieldType.FLOW, qcf);
SetUnits(FieldType.VELOCITY, hcf);
SetUnits(FieldType.HEADLOSS, hcf);
SetUnits(FieldType.LINKQUAL, ccf);
SetUnits(FieldType.REACTRATE, ccf);
SetUnits(FieldType.FRICTION, 1.0);
SetUnits(FieldType.POWER, wcf);
SetUnits(FieldType.VOLUME, hcf * hcf * hcf);
if (hstep.TotalSeconds < 1800)
{
SetUnits(FieldType.TIME, 1.0 / 60.0);
GetField(FieldType.TIME).Units = Keywords.u_MINUTES;
}
else
{
SetUnits(FieldType.TIME, 1.0 / 3600.0);
GetField(FieldType.TIME).Units = Keywords.u_HOURS;
}
}
/// Revert system units to user units.
/// Field type.
/// Value to be converted.
/// Value in user units.
public double RevertUnit(FieldType fieldType, double value)
{
return fieldType == (FieldType)(-1)
? value
: value * GetUnits(fieldType);
}
public double ConvertUnitToSystem(FieldType fieldType, double value)
{
return value / GetUnits(fieldType);
}
///Set conversion value from field type.
/// Field type.
/// Field value.
private void SetUnits(FieldType fieldType, double value)
{
_units[fieldType] = value;
}
}
}