我最近被赋予的任务发展沿海潮汐模型。我有一些要求,不得时候介入才能尽可能快和在有限的差异是因为事情尽可能简单问。
第一次开始,我试着实现线性化浅水方程和应该一次复指数形式的依存关系。这给了我以下系统:
(1)美元我\ω\帽子u - f \帽子v + g \ partial_x \帽子h = - r u $ \的帽子
(2)美元我\ω\帽子v + f \帽子u + g \ partial_y \帽子h = - r \帽子v $
(3)美元我\ω\ h +帽子\ partial_x h \帽子u + \ partial_y h \帽子v = 0美元
我不知在哪里$ \帽子u $,$ \帽子v $,帽子\ h美元,只有两个参数可能表现出空间变化:r美元和H美元。我试图用有限差分离散化,但我很快意识到我与边界条件需要非常小心。因为我想3变量确定彼此密切相关,实际上$ \帽子u $和$ \帽子v $可以很容易地由衍生品的帽子\ h美元。
所以我修改我的系统为了解决只有这个变量,以下方程组:
(4)$ \帽子u = \压裂{- g (i \ω)h fg \ partial_y \ \ partial_x \帽子帽子h} {f²+ (i \ω)²}$
(5)$ \帽子v = \压裂{- g (i \ω)\ partial_y \ h +帽子fg \ partial_x \帽子h} {f²+ (i \ω)²}$
(6)$ i \ω\帽子h = \ partial_x(\压裂{h} {f²+ (i \ω)²}(g (i \ω)h fg \ partial_y \ \ partial_x \帽子帽子h)) + \ partial_y(\压裂{h} {f²+ (i \ω)²}(g (i \ω)\ partial_y \ h +帽子fg \ partial_x \帽子h)) $
然后我试图与集中一阶近似的衍生方案。我试图复制沿海开尔文波在减少域(10 * 10细胞)。然而,我最多能不崩溃,大部分时间有很强的振荡中心。
这是我使用的代码:
# * * * * * *包导入* #进口numpy np matplotlib进口。pyplot作为plt #解决函数* * * * * * * * # def solver_water_elevation(η,深度,dx, dy, r, f = 2的军医,σ= 2 e-5, g = 9.81):““线性化求解椭圆浅水方程复杂沿海的问题。首先我们使用雅可比迭代器。然后我们会改进的。变量主要是复数。输入:埃塔:Overelevation (m)深度:深度(m) dx, dy:网格单元大小r:线性摩擦系数(m.s-1) f:科里奥利频率(s - 1)σ:考虑波的频率(s - 1) g: Gravitationnal加速度(m.s-2)输出:埃塔:见上图" " #首先我们确定当地的摩擦系数= r / m - 1摩擦深度#然后我们将继续一步一步#首先我们计算梯度埃塔etadx =(埃塔(1:1、2)埃塔[1:1,:2])/ (2。* dx [1: 1, 1: 1]) etady =(埃塔(2:1:1)埃塔[:2,1:1])/ (2。* dy[1: 1, 1: 1]) #现在我们可以计算组件相关的纬向和经向速度u = - g *(摩擦(1:1,1:1)1 j *σ)* etadx-f * g * etady v = - g *(摩擦(1:1,1:1)1 j *σ)* etady + f * g * etadx #打印(v, v) #现在我们相乘,对应于正确的术语乘数=深度(1:1,1:1)/ (f * * 2 +(摩擦(1:1,1:1)1 j *σ)* * 2)打印(“乘数”,乘数)#现在我们计算这些项的梯度dxu =(乘数[1:1,2:]* u(1: 1, 2:)乘数[1:1,:2]* u (1: 1,: 2)) \ / (2。* dx [2: 2, 2: 2]) dyv =(乘数(2:1:1)* v(2: 1: 1)乘数(:2,1:1)* v (: 2, 1: 1)) \ / (2。* dy[2: 2, 2: 2]) #最后,确定埃塔埃塔[2:2,2:2]= 1 j /σ* (dxu + dyv)返回埃塔def simple_convergence_error(η,eta_old):“”“比较2组埃塔的值并返回的最大相对误差。输入:埃塔:新数组eta_old:老数组输出:错误:两个数组之间的最大相对偏差”“”返回np.max (abs ((eta-eta_old))) def sol_Kelvin_wave(深度、grid_size dx, dy, f = 2的军医,σ= 2.31484 e-5, g = 9.81, h_0 = 1 + 0.5 j):“”“我们计算开尔文波的解析解的条件给定的BC。输入:深度:静态水深度、米grid_size:网格的大小(在细胞的数量)dx, dy:在x和y方向网格单元大小,米f:科里奥利的频率,在s - 1σ:频率给定潮流的s - 1 g:重力加速度,在m。2,h_0:初始overelevation,在m(复杂的)输出:埃塔:overelevation水”“#首先我们设置一些有用的值c = np.sqrt (g *深度)ω=σ* 2。* np。π#我们得到rad.s-1 k =ω/ c# wavevector #我们必须确定距离边界X_pos = np.array ([[dx (0, j) / 2。+ dx [: i, j] .sum (j)范围内(grid_size[1])]我的范围(grid_size [0])]) Y_pos = np.array ([[dy (i, 0) / 2。+ dy (i, j): .sum (j)范围内(grid_size[1])]我的范围(grid_size[0])]) #计算值η= h_0 * np.exp (1. j * k [:,:] * X_pos [:,:]) \ * np.exp (- f * Y_pos (:,:) / c[:,:])返回埃塔# * * * * * * * * * * * # nx定义变量,纽约= 10,10η= np.zeros ((nx、纽约),dtype =复杂)dx, dy = 10。* np.ones((纽约nx)), 10。* np.ones((纽约nx))σ= 2 #的军医频率f r = 0 = 2 #科里奥利的军医频率。# 2.5 e - 3 #摩擦系数= np.ones深度((纽约nx)) #常数深度# * * *我试着用解析解进行初始化* * * # eta_test = sol_Kelvin_wave(深度、(nx、纽约),dx, dy, f,σ)#现在我设置边界条件埃塔[:2]= eta_test[2:] #底埃塔[2:,:]= eta_test[2:,:] #上面埃塔[::2]= eta_test[:,: 2] #左埃塔[:2:]= eta_test(:, 2: #右侧#调用解算器* * * * * * * * * * * * * * * # = 1错误。 # Initialzing the error tol=1e-8 # Tolerance to error nbr_iter=0 while error>tol : # We use a simple iterative solver # Counting the iterations nbr_iter+=1 eta_old=eta.copy()# Saving the old value #Calling the solver eta=solver_water_elevation(eta,depth,dx,dy,r,sigma=sigma*2.*np.pi,f=f) #Checking the error error=simple_convergence_error(eta,eta_old) print('Computed in ',nbr_iter,' iterations')
有明确的错误在我的代码吗?还是我只是试图解决我的问题,不适应的工具吗?似乎非常基本的,但仍然很明显的我的手。我发现只有小litterature椭圆方程为潮流计算。所以我猜想这不是非常高效的但我完全找不到一个很好的解释为什么它是如此低效的。
谢谢你的帮助,很抱歉如果它似乎非常基本的。