关于使用dct求解零诺依曼边界条件PDE的一点说明

DCT的第二型定义

如我的这篇文章中所述,对于纽曼边界条件的偏微分方程,谱方法中,我们一般使用离散余弦变换,即dct来完成。对于fft和dst而言,似乎定义比较唯一。但是对于,对于dct,它的定义形式就有很多种,维基百科中就列出了它的八种形式。

一般常用的形式有两种,即DCT-I

二维形式形如下面这样:

求和符号的两个撇撇表示求和符号中当m取到0或者J时,前面乘个系数0.5,对于n也是这样。

DCT-II

在Matlab中使用的便是DCT-II的定义,截图如下:

一般来说,第二种形式在图像处理等方面更为常见一些,然而,在用快速变换求解PDE时,有些情况下,可能用此定义并不满足你的要求。

第二定义是原数组关于N-1/2点展开,做离散傅里叶变换得到的,第一定义是原数组关于N点展开得到的。那么,在使用谱方法时他们所要求解的坐标节点是不一样的。什么意思呢?比如对于纽曼边界条件问题,定义域等分成N分,节点标号从0到N,共N+1个节点,包括边界。那么,第一定义求解的便是u0,u1,...,uNu_0,u_1,...,u_Nu0​,u1​,...,uN​共N+1个值,而第二型定义求解的是网格中点处的值,即u1/2,u3/2,...,uN−1/2u_{1/2},u_{3/2},...,u_{N-1/2}u1/2​,u3/2​,...,uN−1/2​共N个值。

很多人不明白这一点,瞎用matlab内置的dct来求解网格节点上的值,这是不对的。当你需要第二型定义来求解PDE在剖分节点上的值(包括边界)时,就需要自己写一个dct来求解。

简单用求和的定义写出的dct,idct,dct2,idct2如下,写得很挫,因为不用这个,所以随手写的:

function [ F ] = mydct( f )
%一般的列向量,我们喜欢用列向量
flag = 0;
if size(f,1)==1f = f';flag = 1;
end
N = length(f)-1;
js = 0:N;
ks = 0:N;
[js_mg,ks_mg] = meshgrid(js,ks);%前后保持一致
cos_mat = cos(pi.*js_mg.*ks_mg./N);
f(1) = f(1)*0.5;
f(end) = f(end)*0.5;F = cos_mat*f;if flag==1F = F';
endend
function [ F ] = myidct( f )
%一般的列向量,我们喜欢用列向量
flag = 0;
if size(f,1)==1f = f';flag = 1;
end
N = length(f)-1;
js = 0:N;
ks = 0:N;
[js_mg,ks_mg] = meshgrid(js,ks);%前后保持一致
cos_mat = cos(pi.*js_mg.*ks_mg./N);
f(1) = f(1)*0.5;
f(end) = f(end)*0.5;
F = cos_mat*f;F = F*2/N;if flag==1F = F';
endend
function B = mydct2( A )
[M,N] = size(A);
ms = 1:M;
ns = 1:N;
js = 1:M;
ls = 1:N;
[ms_grid,ns_grid] = meshgrid(ns,ms);
%[ms_grid,ns_grid] = meshgrid(ms,ns);
A(1,:) = A(1,:)*0.5;
A(end,:) = A(end,:)*0.5;
A(:,1) = A(:,1)*0.5;
A(:,end) = A(:,end)*0.5;for j = jsfor l = lsI = A.*cos(pi*(j-1).*(ms_grid-1)/(M-1)).*cos(pi*(l-1).*(ns_grid-1)/(N-1));B(l,j) = sum(sum(I));end
end
end
function B = myidct2( A )
[M,N] = size(A);
ms = 1:M;
ns = 1:N;
js = 1:M;
ls = 1:N;
[ms_grid,ns_grid] = meshgrid(ns,ms);
A(1,:) = A(1,:)*0.5;
A(end,:) = A(end,:)*0.5;
A(:,1) = A(:,1)*0.5;
A(:,end) = A(:,end)*0.5;for j = jsfor l = lsI = A.*cos(pi*(j-1).*(ms_grid-1)/(M-1)).*cos(pi*(l-1).*(ns_grid-1)/(N-1));B(l,j) = sum(sum(I))*4/((M-1)*(N-1));end
end
end

这么写是跑起来很慢的,我们在用matlab的时候,一个基本的原则是,有内置的函数,尽量用内置的。所以,我们根据dct的定义的来由,根据fft来计算dct,如下:

function y=dctbyfft(x)
% Discrete Cosine Transform DCT-I
[M,N]=size(x);
y=[x;flipud(x(2:M-1,:))];
yy=fft(y);
y=real(yy(1:M,:)/2);
function y=idctbyfft(x)
% Inverse Discrete Cosine Transform IDCT-I
M=size(x,1);
y=2/(M-1)*dctbyfft(x);
function [ Y ] = dct2byfft( X )
Y = dctbyfft(dctbyfft(X)')';
end
function [ Y ] = idct2byfft( X )
Y = idctbyfft(idctbyfft(X)')';
end

我们可以随意地去测试它们,保证两者的结果是一致,说明没有错误:

% a = ([1:20000]');
% myidct(a);
% idctbkl(a);
% mydct(a);
% dctbkl(a);
%A = [4 2;2 4];
A = magic(6);
B1 = myidct2(A)
B2 = idct2byfft(A)
泊松问题下的fft方法分母为零问题

在差分-傅里叶谱方法实际应用当中,如果分母出现了0,怎么办?我看到过别人直接找一个ϵ\epsilonϵ去替代0的,也有直接令那个无穷大的数为0的,我并不知道这是什么机理,不过,既然人家这么搞了,没问题,那我们不妨暂时先接受它。

差分-傅里叶变换法求解泊松方程

举个泊松方程的例子,从代码中,你们可以读出这个方法使用的一些细节,比如说下标从哪到哪等等。

function u=laplacefft(u0,bndcond)
%LAPLACEFFT Solve Laplace's Equation using Fourier's Method.
%   U = LAPLACEFFT(U0) solves Laplace's equation on a rectangle with Dirichlet
%   boundary conditions on all four boundaries ("given values"). The size of
%   the domain and the boundary conditions are given by U0. Note: Only the
%   boundary values of U0 are actually used.
%
%   U = LAPLACEFFT(U0,'DIRICHLET') is equivalent to the above.
%
%   U = LAPLACEFFT(U0,'NEUMANN') uses Neumann conditions ("insulation") on the
%   top and bottom boundaries. Note: Only U0(:,1) and U0(:,end) are used in
%   this case.
%
%   The solver might run faster if the dimensions of U0 are 2^p+1 for
%   integer p (as in the example below).
%   References:
%      G. Strang, "Introduction to Applied Mathematics", Wellesley-
%      Cambridge Press, 1986. (Section 5.5)
%
%      W. Press, S. Teukolsky, W. Vetterling, B. Flannery, "Numerical
%      Recipes in C", 2nd Edition, Cambridge University Press, 1992.
%      (Section 19.4).dirichlet=1;
if nargin>=2switch upper(bndcond)case 'DIRICHLET'case 'NEUMANN'dirichlet=0;otherwiseerror('The second input argument must be ''DIRICHLET or ''NEUMANN''.');end
end[M,N]=size(u0);
if dirichlet % Dirichlet on all four boundariesf=zeros(M-2,N-2);%先求非边界的f,非零边界条件的处理,就是f减去边界条件,就成了边界条件的处理f(:,1)=f(:,1)-u0(2:M-1,1); %f的在内部的第一列减去内部的第一列f(:,N-2)=f(:,N-2)-u0(2:M-1,N); %f在内部的倒数第一列等于自身减去u0的右边界f(1,:)=f(1,:)-u0(1,2:N-1); %f的第一行等于自身减去u0的第一行f(M-2,:)=f(M-2,:)-u0(M,2:N-1);%f的倒数第一行等于自身减去下边界K=2*(cos(pi*(1:M-2)'*ones(1,N-2)/(M-1))+cos(pi*ones(M-2,1)*(1:N-2)/(N-1))-2);fhat=dst(dst(f)')';uhat=fhat./K;u1=idst(idst(uhat')');u=u0;u(2:M-1,2:N-1)=u1;
else % Dirichlet on left and right, Neumann on top and bottomf=zeros(M,N-2);f(:,1)=f(:,1)-u0(:,1);f(:,N-2)=f(:,N-2)-u0(:,N);K=2*(cos(pi*(0:M-1)'*ones(1,N-2)/(M-1))+cos(pi*ones(M,1)*(1:N-2)/(N-1))-2);fhat=dst(dct(f)')';uhat=fhat./K;u1=idst(idct(uhat)')';u=u0;u(:,2:N-1)=u1;
end
% clc
% clear
% close all;
h=1/8;%定义步长为(0.5^5)
[xx,yy]=meshgrid(0:h:2,0:h:1);%横纵坐标的一个meshgrid
U0=xx.^2-yy.^2;     %精确解及边值
U=laplacefft(U0);  %用傅里叶方法求解
contourf(xx,yy,U),view(2),axis equal,colorbar %画图,画等高线图
error=max(abs(U(:)-U0(:))) %求无穷误
[M,N] = size(U);
error=sum(sum(abs(U(:)-U0(:))))/(M*N)

还有一些别的例子,我也贴上来:

function u = poisson1Dneumann(F,x0,xEnd)
% POISSON1DNUEMANN solves the 1D poisson equation d2U/dX2 = F, with neumann
% boundary conditions dUdX = 0 at X = 0 and X = L.
% u = poisson1Dneumann(F,x0,xEnd)
%
% u: Vector of solution
% F: Vector of right-hand-side
% x0: Begining coordinate of domain.
% xEnd: End coordinate of domain.
%% Check for compatibility
xInt = linspace(x0,xEnd,length(F));
fInt = trapz(xInt,F);
if (fInt > 0.0001) || (fInt < -0.0001)disp('Does not satisfy compatibility conditions');
end% Solution
N = length(F);
dx = (xEnd - x0) / (N - 1);b = dct(F);
m = (0:length(b)-1)';
a = dx^2 * b ./ (2 * (cos(m * pi / (N - 1)) - 1))';
a(1) = 0;
u = idct(a);
function U = poisson2Dneumann(F,L)
% POISSON2DNEUMANN solves the the 2D poisson equation d2UdX2 + d2UdY2 = F,
% with the zero neumann boundary condition on all the side walls.
% U = POISSON2DNEUMANN(F,L)
% U: Solution of d2UdX2 + d2UdY2 = F
% F: Right hand side matrix of size N*N
% L: Length of the domain in either X or Y direction. It should be noted
% that Lx = Ly = LN = length(F);
dx = L / (N - 1);
p = 0:N-1;
q = 0:N-1;
[p,q] = meshgrid(p,q);
B = dct2(F);
A = dx^2 * B ./ (2 * cos(pi * p / N) + 2 * cos(pi * q / N) - 4); A(1,1) = 0;
U = idct2(A);

更多的细节,可以参考:

Press W H, Teukolsky S A, Vetterling W T, et al. Numerical recipes 3rd edition: The art of scientific computing[M]. Cambridge university press, 2007.

关于使用dct求解零诺依曼边界条件PDE的一点说明相关推荐

  1. 数字信号处理 | 实验二 MATLAB z换和z逆变换分析+求解差分方程+求解单位冲击响应+求解幅频相频特性曲线+求解零极点

    1.实验目的 (1)掌握离散时间信号的z变换和z逆变换分析 (2)掌握MATLAB中利用filter函数求解差分方程: (3)掌握MATLAB中利用impz函数求解单位冲击响应h(n); (4)掌握M ...

  2. 有限体积法(3)——一维扩散方程数值求解(第一类边界条件)

    例1:无热源导热 考虑一根细棒的导热问题,假设截面内温度均匀,问题简化为一维稳态导热问题,控制方程为 ddx(kdTdx)=0\frac{d}{dx} \left( k \frac{dT}{dx} \ ...

  3. matlab零状态响应幅度频谱,频域分析法求解零状态响应的matlab过程

    今天做信号与系统实验,有用到这部分的知识,感觉这里面道道很多,因此拿出来与大家分享一下. 首先,我们知道matlab是一个很好的编程环境(或许这种解释性语言算不上编程?).总之用matlab对系统的仿 ...

  4. 根据LTI性质快速求解零状态响应微分方程

    系统的判定 认识一个系统的属性,普遍从判断其线性.时不变性.因果性入手. 线性性质: 包括齐次性 e(t)→H→r(t)e(t)→H→r(t)e(t)→H→r(t) ke(t)→H→kr(t)ke(t ...

  5. 边界条件(求解偏微分方程的边界条件)

    研究具体的物理系统,需要考虑研究对象所处的特定的"环境",而周围环境的影响体现在边界上的物理状况,即边界条件. 常见的线性边界条件,数学上分为三类:第一类边界条件,直接规定了所研究 ...

  6. 频域中求解零状态响应,频率响应(自主学习复习傅里叶变换)

    在某一限定时刻t(连续型)或者n(对于离散型)观察到的系统零状态响应 只剩下稳态响应部分,所以正弦激励下稳定系统的零状态响应就是稳态响应. 利用在时域中做卷积则频域中做乘积的性质 可以得出 y(t) ...

  7. 初学python的感受和收获_【雕爷学编程】零基础接触Python的一点收获和学习体会...

    前几天在今日头条上看到一则广告,于是交了8.9元学费(还有不少是0学费的体验课),参加了小咖编程的一个四天课程(每天大概要用二小时左右),是Python的入门基础语法课,老师叫喵酱(教义做的非常棒). ...

  8. 泊松融合进阶——DFT求解二维泊松方程

    前言 泊松融合(Poisson Blending)是图像处理领域著名的图像融合算法,自从2003年发表以来,有很多基于此算法的应用和改进研究出现.泊松融合无需像Alpha blending一样的精确抠 ...

  9. 一种基于物理信息极限学习机的PDE求解方法

    **作者|**PINN山里娃,作者主页 **研究方向|**物理信息驱动深度学习 不确定性 人工智能 偏微分方程 极限学习机 该作者聚焦深度学习模型与物理信息结合前沿研究,提供了一系列AI for sc ...

最新文章

  1. 哈哈哈,这个教人写烂代码的项目在 GitHub 上火了...
  2. web 界面设计 Axure元件样式
  3. linux网络体系架构
  4. 轻松弄懂var、let、const之间的区别
  5. 电脑剪贴板在哪里打开_如何把在公司电脑上复制的内容,粘贴到家里的电脑?超好用!...
  6. Java中的自动拆箱装箱(AutoboxingUnboxing)
  7. win7读取linux硬盘序列号,Windows 下获取硬盘序列号
  8. 关于批判性思维(Critical Thinking)
  9. oracle查询优化不走缓存,Oracle彻底优化——优化内存
  10. [渝粤教育] 西南科技大学 英语国家概况 在线考试复习资料
  11. Shaolin(map)
  12. 使用阿里云的ip地址查询服务-购买ip地址查询服务
  13. mysql bak文件怎么打开_如何打开数据库备份文件(.bak)
  14. 拆掉思维里的墙--书摘+个人理解
  15. 物流快递发货单接口API代码-快递100API
  16. 猜拳游戏(基于TCP socket的编程)
  17. 教你快速制作一个简单的网页
  18. SAS学习笔记之《SAS编程与数据挖掘商业案例》(3)变量操作、观测值操作、SAS数据集管理
  19. vue 的computed和watch在什么时候触发
  20. 关于使用深度学习进行三维点云几何压缩

热门文章

  1. CSS基础、盒子模型、选择器与权重
  2. Java基础知识(三十一)IO流(二) File类、递归、IO流基础
  3. mysql二级证书有用吗,计算机二级证书有效期几年
  4. [Delphi]切换鼠标左右按键
  5. IMS+SAE+LTE(核心网技术1)
  6. Java 8 (1) 行为参数化
  7. 更换计算机桌面背景的教案,黔教版信息技术三年级下册第2课《桌面背景的更换》教案2.doc...
  8. 【附源码】计算机毕业设计SSM社区养老信息管理系统
  9. JavaWeb学习篇——使用通用工厂类解耦MVC框架
  10. 软件工程毕业设计课题(68)微信小程序毕业设计PHP民宿酒店预订小程序系统设计与实现