5757 W3 = dict (m = 3.0 , loga = 10.493 ),
5858)
5959
60- def dnv_in_air (name ):
60+ def units2nref (units ):
61+ if not isinstance (units , str ):
62+ raise ValueError (f"Units input must be a string. Instead got, { units } " )
63+ if not (units .find ("N" ) >= 0 or units .find ("Pa" ) >= 0 ):
64+ raise ValueError (f"Units input must be in SI units of Newtons or Newton-meters or Pascals. Instead got, { units } " )
65+
66+ # Get multiplier to convert from MPa or MN or MNm to x
67+ pfx = units [0 ]
68+ if pfx == 'k' :
69+ nref = 1e3
70+ elif pfx == 'M' :
71+ nref = 1
72+ elif pfx in ['N' ,'P' ]:
73+ nref = 1e6
74+ else :
75+ raise ValueError (f"Unrecognized units string. Expected something like kN or MPa. Instead got, { units } " )
76+
77+ return nref
78+
79+ def dnv_in_air (name , units ):
6180 """Returns a DNV endurance curve (SN curve)
6281
6382 This method returns an endurance curve in air according to
@@ -67,6 +86,9 @@ def dnv_in_air(name):
6786 ---------
6887 name : str
6988 Name of the endurance curve.
89+ units : str
90+ Units for the stresses that are used for fatigue damage calculation (or forces for damage-equivalent loads).
91+ Must be SI units of Newtons or Pascals. Examples are 'kPa' or 'MNm'.
7092
7193 Returns
7294 -------
@@ -81,7 +103,8 @@ def dnv_in_air(name):
81103 """
82104
83105 data = curves_in_air [name ]
84- curve = fatpack .BiLinearEnduranceCurve (1e6 ) # 1e6 for MPa to Pa
106+ nref = units2nref (units )
107+ curve = fatpack .BiLinearEnduranceCurve (nref ) # 1e6 for MPa to Pa
85108 curve .Nc = 10 ** data ["loga1" ]
86109 curve .Nd = data ["Nd" ]
87110 curve .m1 = data ["m1" ]
@@ -90,7 +113,7 @@ def dnv_in_air(name):
90113 return curve
91114
92115
93- def dnv_in_seawater_cathodic (name ):
116+ def dnv_in_seawater_cathodic (name , units ):
94117 """Returns a DNV endurance curve (SN curve)
95118
96119 This method returns an endurance curve in seawater with
@@ -100,6 +123,9 @@ def dnv_in_seawater_cathodic(name):
100123 ---------
101124 name : str
102125 Name of the endurance curve.
126+ units : str
127+ Units for the stresses that are used for fatigue damage calculation (or forces for damage-equivalent loads).
128+ Must be SI units of Newtons or Pascals. Examples are 'kPa' or 'MNm'.
103129
104130 Returns
105131 -------
@@ -113,7 +139,8 @@ def dnv_in_seawater_cathodic(name):
113139
114140 """
115141 data = curves_in_seawater_with_cathodic_protection [name ]
116- curve = fatpack .BiLinearEnduranceCurve (1e6 ) # 1e6 for MPa to Pa
142+ nref = units2nref (units )
143+ curve = fatpack .BiLinearEnduranceCurve (nref ) # 1e6 for MPa to Pa
117144 curve .Nc = 10 ** data ["loga1" ]
118145 curve .Nd = data ["Nd" ]
119146 curve .m1 = data ["m1" ]
@@ -122,7 +149,7 @@ def dnv_in_seawater_cathodic(name):
122149 curve .reference = ref
123150 return curve
124151
125- def dnv_in_seawater (name ):
152+ def dnv_in_seawater (name , units ):
126153 """Returns a DNV endurance curve (SN curve)
127154
128155 This method returns an endurance curve in seawater for
@@ -132,6 +159,9 @@ def dnv_in_seawater(name):
132159 ---------
133160 name : str
134161 Name of the endurance curve.
162+ units : str
163+ Units for the stresses that are used for fatigue damage calculation (or forces for damage-equivalent loads).
164+ Must be SI units of Newtons or Pascals. Examples are 'kPa' or 'MNm'.
135165
136166 Returns
137167 -------
@@ -145,7 +175,8 @@ def dnv_in_seawater(name):
145175
146176 """
147177 data = curves_in_seawater_for_free_corrosion [name ]
148- curve = fatpack .LinearEnduranceCurve (1e6 ) # 1e6 for MPa to Pa
178+ nref = units2nref (units )
179+ curve = fatpack .LinearEnduranceCurve (nref ) # 1e6 for MPa to Pa
149180 curve .Nc = 10 ** data ["loga" ]
150181 curve .m = data ["m" ]
151182 ref = curves_in_seawater_for_free_corrosion ["reference" ]
@@ -164,13 +195,16 @@ def __init__(self, **kwargs):
164195 1. Specify a curve from DNV-RP-C203, Fatigue in Offshore Steel Structures.
165196 Input keywords are "dnv_type" = (one of) ['air', 'seawater', 'cathodic'] and
166197 "dnv_name" = (one of) [B1, B2, C, C1, C2, D, E, G F1, F3, G, W1, W2, W3]
198+ Units must be specified with the "units" input string for consistency.
167199
168200 2. Specify the slope of the S-N curve and a point on the curve.
169201 Required keywords are "slope", "Nc" and "Sc". Assumes a linear S-N curve.
202+ Units are left to the user but must be consistent for all inputs.
170203
171204 3. Specify the slope and the S-intercept point assuming a perflectly linear S-N curve
172205 (which might not be the actual ultimate failure stress of the material.
173206 Required keywords are "slope" and "S_intercept".
207+ Units are left to the user but must be consistent for all inputs.
174208
175209 Parameters
176210 ----------
@@ -184,6 +218,9 @@ def __init__(self, **kwargs):
184218 dnv_name : string (optional)
185219 Grade of metal and hot spot exposure to use: [B1, B2, C, C1, C2, D, E, G F1, F3, G, W1, W2, W3]. Must also specify "dnv_type"
186220 From DNV-RP-C203, Fatigue of Metal Structures, - Edition October 2024
221+ units : string (optional)
222+ Units for the stresses that are used for fatigue damage calculation (or forces for damage-equivalent loads).
223+ Must be SI units of Newtons or Pascals. Examples are 'kPa' or 'MNm'.
187224 slope : float (optional)
188225 Wohler exponent in the traditional SN-curve of S = A * N ^ -(1/m). Must either specify Sc-Nc or S_intercept.
189226 Sc : float (optional)
@@ -205,6 +242,7 @@ def __init__(self, **kwargs):
205242 self .load2stress = kwargs .get ("load2stress" , 1.0 )
206243 dnv_name = kwargs .get ("dnv_name" , "" ).upper ()
207244 dnv_type = kwargs .get ("dnv_type" , "" ).lower ()
245+ units = kwargs .get ("units" , "N" )
208246 slope = np .abs ( kwargs .get ("slope" , 4.0 ) )
209247 Sc = kwargs .get ("Sc" , None )
210248 Nc = kwargs .get ("Nc" , None )
@@ -217,19 +255,19 @@ def __init__(self, **kwargs):
217255 self .goodman = kwargs .get ("goodman" , self .goodman )
218256
219257 for k in kwargs :
220- if k not in ["load2stress" , "dnv_name" , "dnv_type" ,
258+ if k not in ["load2stress" , "dnv_name" , "dnv_type" , "units" ,
221259 "slope" , "Sc" , "Nc" , "ultimate_stress" ,
222260 "S_intercept" , "rainflow_bins" , "bins" ,
223261 "goodman_correction" , "goodman" ]:
224262 print (f"Unknown keyword argument, { k } " )
225263
226264 if dnv_name is not None and len (dnv_name ) > 0 :
227265 if dnv_type .find ("cath" ) >= 0 :
228- self .curve = dnv_in_seawater_cathodic (dnv_name )
266+ self .curve = dnv_in_seawater_cathodic (dnv_name , units )
229267 elif dnv_type .find ("sea" ) >= 0 :
230- self .curve = dnv_in_seawater (dnv_name )
268+ self .curve = dnv_in_seawater (dnv_name , units )
231269 elif dnv_type .find ("air" ) >= 0 :
232- self .curve = dnv_in_air (dnv_name )
270+ self .curve = dnv_in_air (dnv_name , units )
233271 else :
234272 raise ValueError (f'Unknown DNV RP-C203 curve type, { dnv_type } . Expected [air, seawater, or cathodic]' )
235273
@@ -316,6 +354,9 @@ def get_rainflow_counts(self, chan, bins, S_ult=None, goodman=False):
316354
317355 if S_ult == 0.0 :
318356 raise ValueError ('Must specify an ultimate_stress to use Goodman correction' )
357+
358+ if np .any (Mrf > S_ult ):
359+ print ("Warning: Mean stress in Goodman correction is greater than ultimate stress. Will likely lean to innacurate DEL and Damage calculations." )
319360
320361 ranges = fatpack .find_goodman_equivalent_stress (ranges , Mrf , S_ult )
321362
@@ -375,6 +416,7 @@ def compute_del(self, chan, elapsed_time, **kwargs):
375416 slope = self .curve .m1 if hasattr (self .curve , 'm1' ) else self .curve .m
376417 DELs = Frf ** slope * Nrf / elapsed_time
377418 DEL = DELs .sum () ** (1.0 / slope )
419+
378420 # With fatpack do:
379421 #curve = fatpack.LinearEnduranceCurve(1.)
380422 #curve.m = slope
0 commit comments