Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions moorpy/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -671,14 +671,16 @@ def getLineProps(dnommm, material, lineProps=None, source=None, name="", rho=102
# Shorthand for the sub-dictionary of properties for the material in question
mat = lineProps[material]

# convert nominal diameter from mm to m (needed for the range checks below)
d = dnommm*0.001

# Check valid diameter ranges
if mat['d_max'] >= 0 and d > mat['d_max']: # if a max value is given and the diameter is greater than the max
raise Exception(f"Input diameter {d} m is greater than the max valid value of {mat['d_max']} m for {material}.")
if mat['d_min'] >= 0 and d < mat['d_min']: # if a min value is given and the diameter is less than the min
raise Exception(f"Input diameter {d} m is less than the min valid value of {mat['d_min']} m for {material}.")

# calculate the relevant properties for this specific line type
d = dnommm*0.001 # convert nominal diameter from mm to m
mass = mat['mass_d2']*d**2

MBL = mat[ 'MBL_0'] + mat[ 'MBL_d']*d + mat[ 'MBL_d2']*d**2 + mat[ 'MBL_d3']*d**3
Expand Down Expand Up @@ -841,7 +843,7 @@ def loadLineProps(source):
output[mat]['cost_EA' ] = getFromDict(props, 'cost_EA' , default=0.0)
output[mat]['cost_MBL' ] = getFromDict(props, 'cost_MBL' , default=0.0)
output[mat]['d_min' ] = getFromDict(props, 'd_min' , default=-1.0) # -1 to disable checking
output[mat]['d_max' ] = getFromDict(props, 'd_dmax' , default=-1.0) # -1 to disable checking
output[mat]['d_max' ] = getFromDict(props, 'd_max' , default=-1.0) # -1 to disable checking

return output

Expand Down
34 changes: 31 additions & 3 deletions tests/test_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,37 @@

def test_line_stiffness():
'''Checks stiffness of mooring lines.'''





def test_getLineProps_diameter_limits():
'''getLineProps must apply the d_min / d_max range checks correctly.

Regression test for two bugs in the diameter validation:
1. ``d`` (the diameter in metres) was referenced in the range checks
before it was assigned, so any material with ``d_min >= 0`` or
``d_max >= 0`` raised ``UnboundLocalError`` instead of the intended
range Exception.
2. ``loadLineProps`` read ``d_max`` from the key ``'d_dmax'`` (a typo),
so a user-specified ``d_max`` was silently dropped to the -1
"disabled" default and the upper-bound check never fired.
'''
base = {'mass_d2': 100.0, 'MBL_0': 0.0, 'MBL_d': 1e6}

# within the valid range -> succeeds and returns a line type dict
src = {'lineProps': {'rope': {**base, 'd_min': 0.01, 'd_max': 0.20}}}
lt = getLineProps(50.0, 'rope', source=src) # 50 mm = 0.05 m, in range
assert isinstance(lt, dict) and lt['material'] == 'rope'

# below d_min -> the intended Exception (not UnboundLocalError)
with pytest.raises(Exception, match='less than the min'):
getLineProps(5.0, 'rope', source=src) # 5 mm = 0.005 m < 0.01

# above d_max -> the intended Exception; this only works if the d_max
# typo is fixed (otherwise d_max stays -1 and the check is disabled)
with pytest.raises(Exception, match='greater than the max'):
getLineProps(300.0, 'rope', source=src) # 300 mm = 0.3 m > 0.20


if __name__ == '__main__':

import moorpy as mp
Expand Down
Loading