WNTR icon indicating copy to clipboard operation
WNTR copied to clipboard

Wrong conversion for General Purpose Valve Curves

Open angusmcb opened this issue 1 year ago • 5 comments

Summary I believe that General Purpose Valves curves are being converted using the wrong unit: 'headloss' rather than 'hydraulichead'.

(Headloss is always 1/1000 wheras hydraulic head is metres/feet).

https://github.com/USEPA/WNTR/blob/c41b5e42a59e8ab291a0734f0934a7c52a3c65da/wntr/epanet/io.py#L848C21-L848C76

angusmcb avatar Apr 09 '25 09:04 angusmcb

EPANET documentation defines GPV curves as "flow - head loss relationship", https://epanet22.readthedocs.io/en/latest/3_network_model.html. Can you provide an example using WNTR of the incorrect conversion?

kaklise avatar Apr 21 '25 17:04 kaklise

Sorry I didn't see your reply !

This is correct, but the WNTR HydParam.HeadLoss is actually 'unit headloss ' measured in metres/1000metres or feet/1000feet. The headloss referred to in the docs is units of head (i.e. metres / feet). This is represented in wntr as HydParam.HydraulicHead

See also the UI in EPANET which specifies the units of headloss as feet. Image

There is actually a related problem with the link results, where pipes headloss is in units of metres/1000 metres, whilst within the same dataframe valves and pumps are in units of metres. Whilst this could be considered correct behaviour it is extremely confusing. (I could open an new issue for this if appropriate - the solution isn't obvious !).

angusmcb avatar May 23 '25 20:05 angusmcb

As an example:

The below .inp file will have a leadloss curve of flow: 1 lps headloss: 1 metres when opened in epanet.

When opened with wntr it will give the following

wn.curves['1'] <Curve: '1', curve_type='HEADLOSS', points=[(0.001, 0.001)]>

flow is correctly converted to 0.001 m3/s, but headloss is not 1 metre

[TITLE]


[JUNCTIONS]
;ID              	Elev        	Demand      	Pattern         
 2               	0           	0           	                	;
 3               	0           	0           	                	;

[RESERVOIRS]
;ID              	Head        	Pattern         

[TANKS]
;ID              	Elevation   	InitLevel   	MinLevel    	MaxLevel    	Diameter    	MinVol      	VolCurve        	Overflow

[PIPES]
;ID              	Node1           	Node2           	Length      	Diameter    	Roughness   	MinorLoss   	Status

[PUMPS]
;ID              	Node1           	Node2           	Parameters

[VALVES]
;ID              	Node1           	Node2           	Diameter    	Type	Setting     	MinorLoss   
 1               	2               	3               	12          	GPV 	1           	0           	;

[TAGS]

[DEMANDS]
;Junction        	Demand      	Pattern         	Category

[STATUS]
;ID              	Status/Setting

[PATTERNS]
;ID              	Multipliers
;


[CURVES]
;ID              	X-Value     	Y-Value
;HEADLOSS: 
 1               	1           	1           

[CONTROLS]

[RULES]

[ENERGY]
 Global Efficiency  	75
 Global Price       	0
 Demand Charge      	0

[EMITTERS]
;Junction        	Coefficient

[QUALITY]
;Node            	InitQual

[SOURCES]
;Node            	Type        	Quality     	Pattern

[REACTIONS]
;Type     	Pipe/Tank       	Coefficient


[REACTIONS]
 Order Bulk            	1
 Order Tank            	1
 Order Wall            	1
 Global Bulk           	0
 Global Wall           	0
 Limiting Potential    	0
 Roughness Correlation 	0

[MIXING]
;Tank            	Model

[TIMES]
 Duration           	0
 Hydraulic Timestep 	1:00
 Quality Timestep   	0:05
 Pattern Timestep   	1:00
 Pattern Start      	0:00
 Report Timestep    	1:00
 Report Start       	0:00
 Start ClockTime    	12 am
 Statistic          	None

[REPORT]
 Status             	No
 Summary            	No
 Page               	0

[OPTIONS]
 Units              	LPS
 Headloss           	H-W
 Specific Gravity   	1
 Viscosity          	1
 Trials             	40
 Accuracy           	0.001
 CHECKFREQ          	2
 MAXCHECK           	10
 DAMPLIMIT          	0
 Unbalanced         	Continue 10
 Pattern            	1
 Demand Multiplier  	1.0
 Emitter Exponent   	0.5
 Quality            	None mg/L
 Diffusivity        	1
 Tolerance          	0.01

[COORDINATES]
;Node            	X-Coord           	Y-Coord
2               	1645.710          	8875.740          
3               	6216.716          	8816.568          

[VERTICES]
;Link            	X-Coord           	Y-Coord

[LABELS]
;X-Coord             Y-Coord             Label & Anchor Node

[BACKDROP]
  DIMENSIONS  	0.000             	0.000             	10000.000         	10000.000         
 UNITS          	None
 FILE           	
 OFFSET         	0.00            	0.00            

[END]

angusmcb avatar May 23 '25 20:05 angusmcb

Headloss in WNTR is unitless (meters/meter) in SI units. The documentation needs to be updated in https://usepa.github.io/WNTR/units.html.

Headloss first gets converted using HydParam.HydraulicHead (length unit), then using HydParam.HeadLoss (to divide out or multiply by 1000). See the following:

https://github.com/USEPA/WNTR/blob/8a61184a69efbbdc07756bcc083f10b4255bdaf3/wntr/epanet/util.py#L582C1-L591C67

https://github.com/USEPA/WNTR/blob/8a61184a69efbbdc07756bcc083f10b4255bdaf3/wntr/epanet/util.py#L679C4-L689C1

You can also use the following code to test this out.

from wntr.epanet.util import to_si, from_si, HydParam

flow_units = 'LPS'
inp_file_value = 1 # m/1000m

SI_value = to_si(flow_units, inp_file_value, HydParam.HeadLoss) # unitless
convert_back = from_si(flow_units, SI_value, HydParam.HeadLoss) # m/1000m

print(inp_file_value, SI_value, convert_back)

Does that resolve the issue?

kaklise avatar May 24 '25 00:05 kaklise

I think the HydParam.HeadLoss is only for simulation results for pipes. I would refer to this as 'unit headloss'

For valves and pumps it doesn't make sense as they don't have any length. I think this is why the documentation says that metres is used (HydParam.HydraulicHead). This is what epanet does.

angusmcb avatar May 25 '25 14:05 angusmcb