@@ -12,14 +12,35 @@ class cal_Bernabeu(object):
12
12
13
13
This class reads input datasets, calculates its parameters.
14
14
"""
15
- def __init__ (self , CM , Hs50 , D50 , Tp50 , doc , hr , HTL = 0 ):
16
- self .CM = CM
15
+ def __init__ (self , HTL , Hs50 , Tp50 , D50 , CM , hr , doc ):
16
+
17
+ # --- Input data validation ---
18
+ gamma_break = CM / Hs50
19
+ if not (0.5 <= gamma_break <= 1.5 ):
20
+ raise ValueError (
21
+ f"CM should be between 0.7 and 1.5 times Hs50 "
22
+ f"(CM/Hs50 given = { gamma_break :.2f} )"
23
+ )
24
+ if not (- 17.0 <= HTL <= 17.0 ):
25
+ raise ValueError (f"HTL must be between -17 and 17 m (given { HTL } )" )
26
+ if not (0.1 <= Hs50 <= 4 ):
27
+ raise ValueError (f"Hs50 must be between 0.1 and and be 2x smaller than CM (given { Hs50 } )" )
28
+ if not (4.0 <= Tp50 <= 20.0 ):
29
+ raise ValueError (f"Tp50 must be between 1 and 25 s (given { Tp50 } )" )
30
+ if not (0.06 <= D50 <= 4.0 ):
31
+ raise ValueError (f"D50 must be between 0.06 and 4.0 mm (given { D50 } )" )
32
+ if not (HTL < doc <= HTL + 20.0 ):
33
+ raise ValueError (f"doc must be between HTL and CM/2 (given doc={ doc } , HTL={ HTL } and CM/2={ CM / 2 } )" )
34
+ if not (HTL < hr < CM / 2 ):
35
+ raise ValueError (f"hr must satisfy HTL-0.5 < hr < CM/2 (given hr={ hr } , HTL={ HTL } , CM/2={ CM / 2 } )" )
36
+
37
+ self .HTL = HTL
17
38
self .Hs50 = Hs50
18
- self .D50 = D50
19
39
self .Tp50 = Tp50
20
- self .doc = doc
21
- self .HTL = HTL
40
+ self .D50 = D50
41
+ self .CM = CM
22
42
self .hr = hr
43
+ self .doc = doc
23
44
24
45
# observed data placeholders
25
46
self .x_raw = None
@@ -45,7 +66,8 @@ def __init__(self, CM, Hs50, D50, Tp50, doc, hr, HTL=0):
45
66
def params (self ):
46
67
ws = wMOORE (self .D50 / 1000 )
47
68
gamma = self .Hs50 / (ws * self .Tp50 )
48
- self .Ar = 0.21 - 0.02 * gamma
69
+ A_raw = 0.21 - 0.02 * gamma
70
+ self .A = max (A_raw , 1e-3 )
49
71
self .B = 0.89 * np .exp (- 1.24 * gamma )
50
72
self .C = 0.06 + 0.04 * gamma
51
73
self .D = 0.22 * np .exp (- 0.83 * gamma )
@@ -55,9 +77,9 @@ def def_hvec(self):
55
77
56
78
def def_xo (self ):
57
79
self .xo = (
58
- (self .hr + self .CM ) / self .Ar
80
+ (self .hr + self .CM ) / self .A
59
81
)** 1.5 - (self .hr / self .C )** 1.5 + (
60
- self .B / (self .Ar ** 1.5 )
82
+ self .B / (self .A ** 1.5 )
61
83
) * (self .hr + self .CM )** 3 - (
62
84
self .D / (self .C ** 1.5 )
63
85
) * self .hr ** 3
@@ -71,10 +93,10 @@ def run(self):
71
93
self .def_xo ()
72
94
# raw computation
73
95
x_raw , x1_raw , x2_raw , h2 = Bernabeu (
74
- self .Ar , self .B , self .C , self .D ,
96
+ self .A , self .B , self .C , self .D ,
75
97
self .CM , self .h , self .xo
76
98
)
77
- y2_raw = self .h + self .HTL
99
+ # y2_raw = self.h + self.HTL
78
100
79
101
self .x_full = x_raw + self .x_drift
80
102
self .y_full = self .h + self .HTL
@@ -191,20 +213,23 @@ def resid(log_params):
191
213
return np .concatenate ([res1 , res2 ])
192
214
193
215
x0 = np .array ([
194
- np .log (self .Ar ), np .log (self .B ),
216
+ np .log (self .A ), np .log (self .B ),
195
217
np .log (self .C ), np .log (self .D ),
196
218
self .hr
197
219
])
198
- lb = [np .log (1e-3 )]* 4 + [0.0 ]
199
- ub = [np .log (10.0 )]* 4 + [self .h .max ()]
220
+ lb = [np .log (1e-4 )]* 4 + [0.0 ]
221
+ ub = [np .log (100.0 )]* 4 + [self .h .max ()]
222
+
223
+ x0 = np .maximum (x0 , lb )
224
+ x0 = np .minimum (x0 , ub )
200
225
201
226
res = least_squares (
202
227
resid , x0 , bounds = (lb , ub ),
203
228
loss = 'huber' , f_scale = 0.1 ,
204
229
xtol = 1e-8 , ftol = 1e-8 , max_nfev = 2000
205
230
)
206
231
207
- self .Ar , self .B , self .C , self .D = np .exp (res .x [:4 ])
232
+ self .A , self .B , self .C , self .D = np .exp (res .x [:4 ])
208
233
self .hr = res .x [4 ]
209
234
self .def_hvec ()
210
235
return self .run ()
0 commit comments