-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpuvq.m
259 lines (232 loc) · 7.33 KB
/
puvq.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
function ws =puvq(p, u, v, depth, zp, zuv, fs, nfft, rho, lf_cutoff, hf_cutoff, window )
% PUVQ - Determine wave heights from p, u, v velocity data
% [ws]=puvq (p, u, v, depth, zp, zuv, fs, [nfft], [rho], [lf_cutoff], [hf_cutoff], [window],)
%
% Input:
% p pressure (dbar)
% u u velocities (m/s)
% v v velocities (m/s)
% depth Average water depth (m, positive number)
% zp Height of pressure sensor off bottom (m, postive number)
% zuv Height of veloctity sensor off bottom (m, positve number)
% fs Sampling freqency (Hz)
% nfft Length of data to window and process [optional; default=512]
% rho Water density [optional; default = 1025]
% window Data window for spectral calc [optional; default=hanning(nfft)]
% lf_cutoff Low-frequency cutoff for wave motions (default = 1/50 s)
% hf_cutoff High-frequency cutoff for wave motions (default = 1/5 s)
%
% Returns:
% structure ws
% ws.Hrmsp = Hrms (=Hmo) from pressure
% ws.Hrmsu = Hrms from u,v
% ws.ubr = Representative orbital velocity amplitude in freq. band
% ( lf_cutoff <= f <= hf_cutoff ) (m/s)
% ws.omegar = Representative orbital velocity (radian frequency)
% ws.Tr = Representative orbital velocity period (s)
% ws.Tpp = Peak period from pressure (s)
% ws.Tpu = Peak period from velocity (s)
% ws.phir = Representative orbital velocity direction (angles from
% x-axis, positive ccw)
% ws.azr = Represntative orb. velocity direction (deg; geographic
% azimuth; ambiguous =/- 180 degrees)
% ws.ublo = ubr in freq. band (f <= lf_cutoff) (m/s)
% ws.ubhi = ubr in freq. band (f >= hf_cutoff) (m/s)
% ws.ubig = ubr in infragravity freq. band (lf_cutoff f <= 1/20) (m/s)
% Chris Sherwood, USGS
% Laura Landerman - correct calc. of phir and azr, June 24, 2003
% Chris Sherwood - change calc. of wave contributions, May 22, 2004
% Chris Sherwood - calc. params using only ff:lf to avoid divide by zero
% msg. June 2, 2006
% Chris Sherwood - switch to Soulsby method (qkhfs) for wavenumber July 2007
% Chris Sherwood - add freq. range to computation of omegar July 2007
% - embed qkhfs instead of qkhf
% - add window arguement to function statement
% Chris Sherwood - Dec 2008 - revisit direction per J. Lacy suggestions
% Chris Sherwood - Feb 2008 - add Tpp and Tpu
% Patrick Dickhudt - Nov. 2009 - make Tpp and Tpu nan if any Snp/Snu are
% nan or all are zero - otherwise Tpp/Tpu is max period in window
g = 9.81;
if(exist('rho')~=1),rho = 1025;,end
if(exist('nfft')~=1),nfft = 512;,end
if(exist('window')~=1),window = hanning(nfft);,end
if(exist('lf_cutoff')~=1),lf_cutoff=1/50;,end
if(exist('hf_cutoff')~=1),hf_cutoff=1/5;,end
noverlap=nfft/2;
p = detrend(p);
u = detrend(u);
v = detrend(v);
% compute wave height from velocities
% Determine velocity spectra for u and v
[Gpp, f] = p_welch( rho*g*p,nfft, fs, window, noverlap );
df = f(3)-f(2);
[Guu, f] = p_welch( u, nfft, fs, window, noverlap);
[Gvv, f] = p_welch( v, nfft, fs, window, noverlap);
% These pairs of time-domain and spectral stats
% should be very close to equal:
% varp = var(rho*g*p)
% varP = sum( Gpp*df )
% varu = var(u)
% varU = sum( Guu*df )
% varv = var(v)
% varV = sum( Gvv*df )
% rmsV = sqrt(varV)
% rmsv = sqrt(mean( v.^2))
% ubr1 = sqrt(2.*(varu+varv))
% ubr2 = sqrt(2*(varU+varV))
% determine wave number
omega = 2*pi .* f;
k = qkhfs(omega, depth) ./ depth;
%compute linear wave transfer function
kh = k*depth;
kzp = k*zp;
kzuv = k*zuv;
omega = omega(:);
nf = length(omega);
Hp = ones(nf,1);
Huv = ones(nf,1);
% change wavenumber at 0 Hz to 1 to avoid divide by zero
i = 1:nf;
if(omega(1)==NaN | omega(1)<=0),
i = 2:nf;
Hp(1)=1;
Huv(1)=1;
end
Hp(i,1) = rho*g .* ( cosh(kzp(i,1)) ./ cosh(kh(i,1)) );
Huv(i,1) = omega(i,1) .* ( cosh(kzuv(i,1)) ./ sinh(kh(i,1)) );
% create cut off freqency, so noise is not magnified
ff = min(find(f>=lf_cutoff));
lf = max(find(f<=hf_cutoff));
% combine horizontal velocity spectra
Guv = Guu + Gvv;
% Determine wave height for velocity spectra
Snp = Gpp(ff:lf) ./ (Hp(ff:lf).^2);
Snu = Guv(ff:lf) ./ (Huv(ff:lf).^2);
fclip = f(ff:lf);
% Determine rms wave height (mult by another sqrt(2) for Hs)
% Thornton and Guza say Hrms = sqrt(8 mo)
Hrmsu = 2*sqrt( 2*sum( Snu*df ) );
Hrmsp = 2*sqrt( 2*sum( Snp*df ) );
% These are representative orbital velocities for w-c cacluations,
% according to Madsen (1994) Coastal Engineering 1994, Proc., 24th
% Intl. Conf., Coastal Eng. Res. Council / ASCE. pp.384-398.
% (esp. p. 395)
ubr = sqrt( 2*sum(Guv(ff:lf)*df));
ubr_check = sqrt(2*var(u)+2*var(v));
omegar = sum( omega(ff:lf).* Guv(ff:lf)*df )./ ...
sum( Guv(ff:lf)*df );
Tr = 2*pi/omegar;
% peak frequencies
if any(isnan(Snp)) || ~any(Snp)
Tpp = nan;
else
[emax,jpeak]=max(Snp);
Tpp = 1/fclip(jpeak);
end
if any(isnan(Snu)) || ~any(Snu)
Tpu = nan;
else
[emax,jpeak]=max(Snu);
Tpu = 1/fclip(jpeak);
end
% phi is angle wrt to x axis; this assumes Guu is in x direction
% phir = atan2( sum(Guu(ff:lf)*df), sum(Gvv(ff:lf)*df) );
% this is the line changed on 6/24/03 - I still think it is wrong (CRS)
% phir = atan2( sum(Gvv(ff:lf)*df), sum(Guu(ff:lf)*df) );
% This is Jessie's replacement for direction
% 12/08 Jessie notes that Madsen uses velocity and suggests
% 12/08 Jessie notes that Madsen uses velocity
%Suu = sqrt(Guu);
%Svv = sqrt(Gvv);
%Suv = sqrt(Guv);
% but I think eqn. 24 is based on u^2, so following is ok:
rr = corrcoef(u,v);
ortest = sign(rr(2,1));
phir = atan2( ortest*sum(Gvv(ff:lf)*df), sum(Guu(ff:lf)*df) );
% convert to degrees; convert to geographic azimuth (0-360, 0=north)
azr = 90-(180/pi).*phir;
% Freq. bands for variance contribs
ig = max( find( f <= 0.05 ));
% low freq, infragravity, high-freq
if(1<ff),
ublo = sqrt(2*sum(Guv(1:ff)*df));
else
ublo = 0;
end
if(ig>ff),
ubig = sqrt(2*sum(Guv(1:ff)*df));
else
ubig = 0;
end
if(lf < nfft ),
ubhi = sqrt(2*sum(Guv(lf:end)*df));
else
ubhi = 0;
end
% stick results in structure
ws.Hrmsp = Hrmsp;
ws.Hrmsu = Hrmsu;
ws.ubr = ubr;
ws.ubr_check = ubr_check;
ws.omegar = omegar;
ws.Tr = Tr;
ws.Tpp = Tpp;
ws.Tpu = Tpu;
ws.phir = phir;
ws.azr = azr;
ws.ublo = ublo;
ws.ubhi = ubhi;
ws.ubig = ubig;
if(0),
figure(1), clf
subplot(311)
plot(u)
subplot(312)
plot(v)
subplot(313)
plot(p)
figure(2)
clf
subplot(121)
plot(f(ff:lf),Hp)
ylabel('Hp')
subplot(122)
plot(f(ff:lf),Huv)
ylabel('Huv')
figure(3)
clf
plot(f(ff:lf),Snp,'-b')
hold on
plot(f(ff:lf),Snu,'-r')
end
function kh = qkhfs( w, h )
% QKHFS - Quick iterative calculation of kh in dispersion relationship
% kh = qkhf( w, h )
%
% Input:
% w Angular wave frequency = 2*pi/T where T = wave period [1/s]
% h Water depth [m]
% Returns:
% kh = wavenumber * depth [ ]
%
% Either w or h can be a vector, but not both.
% Hard-wired for MKS units.
% Orbital velocities from kh are accurate to 3e-12 !
%
% RL Soulsby (2006) "Simplified calculation of wave orbital velocities"
% HR Wallingford Report TR 155, February 2006
% Eqns. 12a - 14
% csherwood@usgs.gov
% Sept 10, 2006
g = 9.81;
x = w.^2*h./g;
y = sqrt(x) .* (x<1) + x.* (x>=1);
%this appalling bit of code is about 25% faster than a for loop
t = tanh( y );
y = y-( (y.*t -x)./(t+y.*(1-t.^2)));
t = tanh( y );
y = y-( (y.*t -x)./(t+y.*(1-t.^2)));
t = tanh( y );
y = y-( (y.*t -x)./(t+y.*(1-t.^2)));
kh=y;
return;