目录

Matlab波浪数值模拟

写在前面:最近几天新冠病毒疫情还未平息,在家帮女票研究波浪模型的时候探索了一下用Matlab进行波浪数值模拟的简单方法,在这里写一个简单教程,因为我在网上也没有找到写的比较完整的波浪模拟代码,所以来这里占个坑,希望对大家有所帮助。

理论依据

详情参考这两篇论文:

[1] 刘素美. 波浪数值模拟[J]. 科技与创新, 2018(13):132-133.

[2] 赵珂,李茂华,郑建丽,田冠楠. 基于波浪谱的三维随机波浪数值模拟及仿真[J]. 舰船科学技术, 2014,36(02):37-39.

简单来说就是,波浪的模拟,可以由不同方向角、不同频率的很多个波,用随机的初始相位初始化后叠加得到。显然,组成波浪的波的频率个数越多、方向角个数越多,能够形成的波就更复杂(直观上也更真实)。

先给出波面模型的公式(根据文献[1]) $$ z = \eta(x, y, t)=\sum_{i=1}^{M} \sum_{j=1}^{N} \zeta_{i j} \cos [{k}_{i}\left(x \cos \alpha_{d j}+y \sin \alpha_{d j}\right)-\omega_{di}t+\beta_{ij} $$ 其中$\zeta_{ij},k_{i},\alpha_{dj},\omega_{di},\beta_{ij}$分别为波浪的波幅、波数、方向角、频率和相位角。且$k_{i} = \omega_{di}^{2}/g$。

可以看出,其中$x,y,t$是需要输入的参数,即坐标位置和时间,$z$就是波面高度,由于波的形成需要如上的这些参数。其中方向角和频率是需要进行划分的,其余的参数全都可以由不同的方向角和频率计算得到,下面讲波浪参数的确定。

方向角划分和选取

对传播方向角$\alpha$进行划分时,设方向角的变化范围为主波向$\alpha_{main}$两侧$[-\pi/2,\pi/2]$的范围,将此区域$N$等分,每一份的宽度为$d\alpha=\pi/N$(论文这里写的有误,请大家注意),选取每段的中心值作为方向角$\alpha_{dj}$。

频率的划分和选取

论文中给定了频率选取区间的计算方式,这里不做描述,直接关注频率的划分公式

$$\omega_{i}=\left[\frac{3.11}{H_{1 / 3}^{2} \ln (M+2 / i)}\right]^{1 / 4}$$

$$\omega_{di}=\frac{\omega_{i+1}+\omega_{i}}{2}$$

这里采用等分能量法分割频率,将频率划分为$M$个等能量的区间,$\omega_{i}$是各区间的分界频率,$\omega_{di}$是各频率区间的中心值作为选取的频率。

备注:原文中第一个公式中是$M/i$,因为i的取值只能是从1~M-1,所以只能产生M-2个区间,这里坐了一下修改,保证M的个数与选取的频率个数相同

利用三维随机波浪谱确定波幅$\zeta_{ij}$

标准波浪谱为PM谱

$$S_{PM}(\omega)=\frac{0.78}{\omega^{5}}exp[-\frac{3.11}{\omega^{4}H_{1/3}^{2}}]$$

其中$H_{1/3}=0.0214v^{2}$为有义波高,$v$是海面风速,会影响波浪高度。由于PM 谱描述的是能量随频率的变化,而对于三维随机波浪,其能量分布与频率和方向角都有关,并且认为频率和方向角的影响相互独立,则引入只与方向角$\alpha$有关的方向扩展谱函数$D_{f}(\alpha)$

$$D_{f}(\alpha)=\frac{2}{\pi} \cos ^{2} \alpha,\left(-\frac{\pi}{2} \leqslant \alpha \leqslant \frac{\pi}{2}\right)$$

最终得到三位随机波浪的方向波谱:

$$S_{3D}(\omega,\alpha)=S_{PM}(\omega)D_{f}(alpha)$$

将划分好的频率和方向角代入下式,即可得到每个单元组成波的波幅$\zeta_{ij}$

$$\zeta_{ij}=\sqrt{2S(\omega,\alpha)d{\omega}d{\alpha}}$$

备注:论文这里公式有误,我已经做了修改

随机初始相位$\beta_{ij}$的生成

文中写的是线性乘同余法,其实用简单的$0-2\pi$的均匀分布随机采样就可以。

基本实现的静态波浪生成代码

 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
n = 64;
map = zeros(n,n);
M = 1;    % ferequence number
N = 50;   
beta = 2*pi*rand(M,N);  

for x = 1:n
    for y=1:n
        map(x,y) = bo(x,y,M,N,beta);
    end
end

XX = 1:n;
YY = 1:n;
surf(XX, YY, map);
axis([-5, n+5, -5, n+5, -5, 5])

function H = bo(x,y,M,N,beta)
t = 0;     
v = 5;    
g = 9.8;  
H_value = 0.0214*v^2;  
alpha_main = 0;        

da = pi/N; 
a = alpha_main-pi/2+da/2 : da : alpha_main+pi/2-da/2; 

wi = (3.11./(H_value^2*log((M+2)./(1:M+1)))).^(1/4);
% wi = zeros(M+1,1);
% for i = 1:M+1
%     wi(i) = (3.11/(H_value^2*log((M+2)/i)))^(1/4);
% end 

w = (wi(2:end)+wi(1:end-1))/2;
dw = wi(2:end)-wi(1:end-1);

% w = zeros(M,1);
% dw = zeros(M,1);
% for i = 1:M
%     w(i) = (wi(i+1)+wi(i))/2;
%     dw(i) = wi(i+1)-wi(i);
% end

 H = 0;
for i=1:M
    for j=1:N
        adj = a(j);
        wdi = w(i);
        Spm_w = 0.78*exp(-3.11/(wdi^4*H_value^2))/wdi^5;
        Df_alpha = 2*(cos(adj)^2)/pi;
        S3d = Spm_w*Df_alpha;
        A = sqrt(2*S3d*dw(i)*da);
        ki = wdi^2/g;
        H = H + A*cos(ki*(x*cos(adj)+y*sin(adj))-wdi*t+beta(i,j));
    end
end
end

https://gitee.com/miraclefish/picgo/raw/master/notebookPic/blogimgwave.svg
静态波浪

波浪的动态实现

(计算已改为矩阵并行化,为了提升实时的渲染速度)

 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
n = 100;  
t = 1;  
v = 8;  
M = 15; 
N = 15; 

g = 9.8; 
H_value = 0.0214*v^2; 
alpha_main = 0;  

beta = 2*pi*rand(M,N);  

da = pi/N; 
a = alpha_main-pi/2+da/2 : da : alpha_main+pi/2-da/2; 

wi = (3.11./(H_value^2*log((M+2)./(1:M+1)))).^(1/4);

% wi = zeros(M+1,1);
% for i = 1:M+1
%     wi(i) = (3.11/(H_value^2*log((M+2)/i)))^(1/4);
% end 

w = (wi(2:end)+wi(1:end-1))/2;
dw = wi(2:end)-wi(1:end-1);

% w = zeros(M,1);
% dw = zeros(M,1);
% for i = 1:M
%     w(i) = (wi(i+1)+wi(i))/2;
%     dw(i) = wi(i+1)-wi(i);
% end

Spm_w = 0.78*exp(-3.11./(w.^4*H_value^2))./w.^5;
Df_alpha = 2*(cos(a).^2)/pi;
S3d = Spm_w'*Df_alpha;
A = sqrt(2*S3d.*(dw'*da));
ki = w.^2/g;

A = repmat(A(:)', n*n, 1);
aj = repmat(a, M, 1);
a = aj(:)'ki = ki';
ki = repmat(ki, 1, N);
k = ki(:)'; 
extend_w = repmat(w',1,N);
extend_w = repmat(extend_w(:)', n*n, 1);
beta = repmat(beta(:)', n*n, 1);


XX = 1:n; YY = 1:n;
[X,Y] = meshgrid(XX, YY);
t0 = 0;
dt = 0.1T = 100;

X = reshape(X, n*n, 1);
Y = reshape(Y, n*n, 1);

clf
shg
set(gcf);
MAP = wave2(X,Y,A,k,a,extend_w,t0,beta);
MAP = reshape(MAP, n, n);
surfplot = surf(XX, YY, MAP);
%shading interp
axis([-5,n+5,-5,n+5,-10,10])

for t = 0:dt:T
    MAP = wave2(X,Y,A,k,a,extend_w,t,beta);
    MAP = reshape(MAP, n, n);
    set(surfplot,'zdata',MAP);
%     shading interp
    drawnow
end


function wave = wave2(X,Y,A,k,a,extend_w,t,beta)
wave = sum(cos((X*cos(a)+Y*sin(a)).*k-extend_w.*t+beta).*A,2);
end

/images/blogimgwave.gif
动态波浪