实战一之2018A

一维热传导方程

在这里插入图片描述
在这里插入图片描述

1、偏微分方程的解法(pdepe函数):

有初值条件和足够的(两个)边值条件
本来想由外层到内层,每层用解偏微分方程的方法解出U(x,t)可惜这题找不到两个边界条件

2、有限差分法

标准的一维热传导方程的解法(有初值条件和足够的(两个)边值条件)
具体思路和代码见该篇博客

  • 类似有限差分法的思路,将时间和空间离散化,
    在这里插入图片描述

在这里插入图片描述
用代码实现以下 推理式
在这里插入图片描述

function main_program
clc,clear
format short g
rho=[300,862,74.2,1.18]; %密度
c=[1377,2100,1726,1005]; %比热容
k=[0.082,0.37,0.045,0.028]; %热传导率
x=[0.0006,0.006,0.0036,0.005]; %每层的宽度
% dx=[0.0001,0.001,0.0006,0.001]; %空间步长
gcd = GCD(x); %0.0002
dx=gcd;
dt=0.002; %时间步长
Ten=75;Tbd=37; %初始温度
n=sum(x)/dx+1
m=5400/dt
arr=zeros(m,n);

arr(1,:)=37.*ones(n,1);
arr(:,1)=75.*ones(1,m); %arr(1,1)75
tmp=dt/(dx*dx);


sj=zeros(size(x));% x是4块的厚度构成的矩阵
sj(1)=x(1);
for i=2:4 
    sj(i)=sj(i-1)+x(i);
end
sj
sj=sj/dx % 3 33 51 76 
%每一块离散化成多少块,再求前缀和,也就是想记录每段接触点的位置
%下面这种方法更好,记录接触点
%上面方法记录每块的长度,还要考虑下标从2开始

% LEN1=int8(x(1)/dx(1))+1; %记录每段接触点的位置
% LEN2=LEN1+x(2)/dx(2);
% LEN3=LEN2+x(3)/dx(3);
% LEN4=LEN3+x(4)/dx(4)

for i=1:m-1
    mu=k(1)/(c(1)*(rho(1)));
    mu=mu*mu;
    for j=2:sj(1)+1
%     arr(i+1,j)= tmp*k(1)*k(1)*(arr(i,j+1)+arr(i,j-1)-2*arr(i,j))/(c(1)*(rho(1)))*(c(1)*(rho(1)))+arr(i,j);
    arr(i+1,j)= tmp*mu*(arr(i,j+1)+arr(i,j-1)-2*arr(i,j))+arr(i,j);
    end
    mu=k(2)/(c(2)*(rho(2)));
    mu=mu*mu;
    for j=sj(1)+2:sj(2)+1  %sj(1)+1  4
        arr(i+1,j)= tmp*mu*(arr(i,j+1)+arr(i,j-1)-2*arr(i,j))+arr(i,j);
    end 
    mu=k(3)/(c(3)*(rho(3)));
    mu=mu*mu;
    for j=sj(2)+2:sj(3)+1
        arr(i+1,j)= tmp*mu*(arr(i,j+1)+arr(i,j-1)-2*arr(i,j))+arr(i,j);
    end 
    mu=k(4)/(c(4)*(rho(4)));
    mu=mu*mu;
    for j=sj(3)+2:sj(4)  %理论上最后一列是sj(4)+1,要按该公式算会数组越界
        arr(i+1,j)= tmp*mu*(arr(i,j+1)+arr(i,j-1)-2*arr(i,j))+arr(i,j);
    end
end

arr(2,:)
arr(3,:)
arr(50,:)
end

很无奈,由于一维热传导方程中 a 2 a^2 a2理解错了,本来就很小的数再加以平方,得出的U(x,t)几乎全部接近37
最后一列全0,因为按照这一个公式算所有的点,最后一列会越界
实际上块与块之间的接触点、热源与x=0处、第四层与皮肤的接触点需要通过别的公式计算,无奈下面三个式子太难推得
在这里插入图片描述

写代码遇到的艰难阻碍

1、确定时间步长、空间步长后,将时间、距离热源距离离散为若干个时域和空域(这里时间m份,空间n份)
首先根据边界条件对 离散矩阵的边界进行初始化,t=0,U(x,0)初始化为37,x=0,U(0,t)初始化为75,要注意的是,matlab矩阵下标从1开始,则以空域为例,初始化下标1,1~N对应的矩阵下标是 2 ~ N+1, 故矩阵的大小应初始化为 (m+1,n+1)
2、由于对MATLAB不熟,每个通过计算得到得变量(尤其是矩阵,最好输出看看,比如这里得sj矩阵,一不小心就算出小数,作为数组下标显然会报错位置 2 处的索引无效。数组索引必须为正整数或逻辑值。

3、每个时域迭代进行矩阵计算

超级牛逼的队友推出了某个牛逼式子(我TM直接谢绝观赏),我只负责计算
设如下矩阵为AX=b
对于时域 i ,通过X=A\b,计算出时域 i 的温度,再通过时域 i 的温度 递推出 进行时域 i+1 计算的 b矩阵

在这里插入图片描述

在这里插入图片描述
首先为得到左侧的A矩阵,主对角线上通过循环,主要是主对角线相邻的两条斜线
本来一开始,初始化上侧,想通过A=A'+A 得到对称矩阵,出错
请注意,通过A=A'+A 得到对称矩阵只适用于 完美对称的矩阵,
像这里,对称的元素所在的行不同,取得 r i r_i ri不同,所以说不是完美对称的,太想当然了
这里就应该分别循环初始化

%文件名称为 skin_T.m
function T = skin_T(Ten,x2,x4)
clc,clear
format short g
rho=[300,862,74.2,1.18]; %密度
c=[1377,2100,1726,1005]; %比热容
k=[0.082,0.37,0.045,0.028]; %热传导率
x=[0.0006,0.006,0.0036,0.005]; %每层的宽度
% dx=[0.0001,0.001,0.0006,0.001]; %空间步长
gcd = GCD(x) %0.0002
dx=0.0002;
dt=0.02; %时间步长
Ten=75;Tbd=37; %初始温度
n=sum(x)/dx % 下标1~ n+1 ,这里不计x=0处的清一色75°
m=5400/dt+1
% U矩阵维度(n,m)

sj=zeros(size(x));
sj(1)=x(1);
for i=2:4 
    sj(i)=sj(i-1)+x(i);
end
sj=sj/dx % 3 33 51 76
% dx
sqrt_a=k./(c.*rho)
r=dt/(dx*dx)*sqrt_a
h=83.6
A=zeros(n,n);
% A=A+-2*eye(n)+diag(ones(1,length(x)-1),1)+diag(ones(1,length(x)-1),-1);

for i=1:n-1
    if(i<=sj(1)+1)A(i,i+1)=-1*r(1);
    elseif(i<=sj(2)+1)A(i,i+1)=-1*r(2);
        elseif(i<=sj(3)+1)A(i,i+1)=-1*r(3);
            elseif(i<=sj(4)+1)A(i,i+1)=-1*r(4);
    end   
end
% A=A'+A ;

for i=2:n
    if(i<=sj(1)+1)A(i,i-1)=-1*r(1);
    elseif(i<=sj(2)+1)A(i,i-1)=-1*r(2);
        elseif(i<=sj(3)+1)A(i,i-1)=-1*r(3);
            elseif(i<=sj(4)+1)A(i,i-1)=-1*r(4);
    end   
end
for i=1:n
    if(i<=sj(1)+1)A(i,i)=1+2*r(1);
    elseif(i<=sj(2)+1)A(i,i)=1+2*r(2);
        elseif(i<=sj(3)+1)A(i,i)=1+2*r(3);
            elseif(i<=sj(4)+1)A(i,i)=1+2*r(4);
    end
end
 A(n,n)=h+k(4)/dx;
 A(n,n-1)=-1*k(4)/dx;
A(1,:);
A(2,:);

 b=zeros(n,1);
 u=zeros(n,m); %m已经算上了t=0的那一列37
%  u=u+37*ones(n,1);
 u(:,1)=37;
 %u(x,t)
% u(1,2)
% u(:,1)


skin=[37];
 for i=2:m %t 270000
     for j=1:n  %x
  if(j==1)b(j)=u(j,i-1)+75*r(1);
  elseif(j==n)
      p=(u(n,i-1)-k(4)/dx*(u(n-1,i-1)-u(n,i-1))/h);
      b(j)=h*p;
      skin=[skin;p];%skin是个列向量
  else b(j)=u(j,i-1);
  end
     end
%      b
 tmp=A\b;

%  u=[u tmp];
%  u=u+tmp ; %u的每一列都会加上tmp列向量
%  u(:,i)=tmp; %正确,但是会自动输出的是整个u矩阵而不是这一列 不利于观察
 u(:,i)=u(:,i)+tmp;
%  for q=1:n
%      u(q,i)=tmp(q);
%  end


u(:,i);
% % i
 end
 disp('--------------------------------');
 u=[u;skin'];

%    xlswrite('work.xlsx',u,'sheet1');
% x=0:dx:sum(x)+dx;
% t=0:dt:5400

 size(u) %n*m
 x=linspace(0,sum(x),n+1) ;
 t=linspace(0,5400,m) ;
 % [X,T]=meshgrid(x,t); 不需要
 mesh(t,x,u); %u(x,t)

shading interp

%  T=skin;
end

%%%%---------------------------子函数如下
%求解最大公因数 Calculate the GCD of an integer array
function result = GCD(array)
n = length(array);
tmp = array;
exp = 0; % Record how many times the array has been multiplied by 10
while ~is_intarray(tmp) % Whether array multiplied by 10's has become integer
    tmp = tmp * 10;
    exp = exp + 1;
end
result = gcd_array(uint32(tmp),n); % Calculate the LCM of the integer array which has been multiplied by 10's
if (exp > 0) % If the array is multiplied by 10's, divide the LCM by 10's in return
    result = double(result) / 10^exp;
end
end
 

function result = gcd_array(array, n)
result = array(1);
for i = 1:n-1
    result = gcd(result,array(i+1)); 
end
end
%判定被乘了10的数组是否已经变成整数了
function result = is_intarray(array)
tmp = round(array);
if (abs(array - tmp) < 10^(-10))
    result = 1;
else
    result = 0;
end
end

要善于输出部分进行测试正误,测试代码如下

%文件名称为 skin_T.m
function T = skin_T(Ten,x2,x4)
% clc,clear
format short g
rho=[300,862,74.2,1.18]; %密度
c=[1377,2100,1726,1005]; %比热容
k=[0.082,0.37,0.045,0.028]; %热传导率
x=[0.0006,0.006,0.0036,0.005]; %每层的宽度
% dx=[0.0001,0.001,0.0006,0.001]; %空间步长
gcd = 0.0002;%GCD(x); %0.0002
dx=0.0002;
dt=0.02; %时间步长
Ten=75;Tbd=37; %初始温度
n=sum(x)/dx ;% 下标1~ n+1 ,这里不计x=0处的清一色75°
m=5400/dt+1;
% U矩阵维度(n,m)
n=5;
sj=zeros(size(x));
sj(1)=x(1);
for i=2:4 
    sj(i)=sj(i-1)+x(i);
end
sj=sj/dx ;% 3 33 51 76
% dx
sqrt_a=k./(c.*rho);
r=dt/(dx*dx)*sqrt_a;
h=83.6;
A=zeros(n,n);


for i=1:n-1
    if(i<=sj(1)+1)A(i,i+1)=-1*r(1);
    elseif(i<=sj(2)+1)A(i,i+1)=-1*r(2);
        elseif(i<=sj(3)+1)A(i,i+1)=-1*r(3);
            elseif(i<=sj(4)+1)A(i,i+1)=-1*r(4);
    end   
end
A=A'+A ;
% 
% for i=2:n
%     if(i<=sj(1)+1)A(i,i-1)=-1*r(1);
%     elseif(i<=sj(2)+1)A(i,i-1)=-1*r(2);
%         elseif(i<=sj(3)+1)A(i,i-1)=-1*r(3);
%             elseif(i<=sj(4)+1)A(i,i-1)=-1*r(4);
%     end   
% end
% for i=1:n
%     if(i<=sj(1)+1)A(i,i)=1+2*r(1);
%     elseif(i<=sj(2)+1)A(i,i)=1+2*r(2);
%         elseif(i<=sj(3)+1)A(i,i)=1+2*r(3);
%             elseif(i<=sj(4)+1)A(i,i)=1+2*r(4);
%     end
% end
%  A(n,n)=h+k(4)/dx;
%  A(n,n-1)=-1*k(4)/dx;
A(1,:);
A(2,:);
A
%  
%  T=skin;
end






matlab较好的取名变量(见名知意)

mu
lamda
theda

求最大公因数

%%%%---------------------------子函数如下
%求解最大公因数 Calculate the GCD of an integer array
function result = GCD(array)
n = length(array);
tmp = array;
exp = 0; % Record how many times the array has been multiplied by 10
while ~is_intarray(tmp) % Whether array multiplied by 10's has become integer
    tmp = tmp * 10;
    exp = exp + 1;
end
result = gcd_array(uint32(tmp),n); % Calculate the LCM of the integer array which has been multiplied by 10's
if (exp > 0) % If the array is multiplied by 10's, divide the LCM by 10's in return
    result = double(result) / 10^exp;
end
end
 

function result = gcd_array(array, n)
result = array(1);
for i = 1:n-1
    result = gcd(result,array(i+1)); 
end
end
%判定被乘了10的数组是否已经变成整数了
function result = is_intarray(array)
tmp = round(array);
if (abs(array - tmp) < 10^(-10))
    result = 1;
else
    result = 0;
end
end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一份适用于MATLAB R2018a版本的代码,实现了对随机噪声和周期噪声的混合噪声进行去噪处理,并计算均方误差评估去噪效果: ```matlab % 读入带噪声的图像,假设图像名为noisy_img.jpg noisy_img = imread('noisy_img.jpg'); % 定义小波基和小波阈值 wname = 'db4'; threshold = 0.05; % 小波变换 [C, S] = wavedec2(noisy_img, 3, wname); % 对小波系数进行阈值处理 thrC = wthresh(C, 'h', threshold); % 小波逆变换 denoised_img = waverec2(thrC, S, wname); % 将图像像素值转换到0-1范围内 denoised_img = double(denoised_img) / 255; % 构建卷积神经网络模型 layers = [ imageInputLayer([256 256 1]) convolution2dLayer(3, 64, 'Padding', 'same') reluLayer() convolution2dLayer(3, 64, 'Padding', 'same') reluLayer() convolution2dLayer(3, 1, 'Padding', 'same') regressionLayer() ]; % 定义训练参数 options = trainingOptions('adam', ... 'MaxEpochs', 10, ... 'MiniBatchSize', 128, ... 'InitialLearnRate', 1e-3, ... 'Shuffle', 'every-epoch', ... 'Verbose', false); % 将带噪声的图像输入模型进行训练,得到一个去噪模型 denoising_net = trainNetwork(denoised_img, noisy_img, layers, options); % 将带噪声的图像输入去噪模型进行去噪处理 denoised_img = predict(denoising_net, denoised_img); % 将图像像素值转换回0-255范围内 denoised_img = uint8(denoised_img * 255); % 计算均方误差 mse = immse(denoised_img, noisy_img); ``` 需要注意的是,以上代码仅是一种实现方案,具体的算法和参数设置还需要根据实际情况进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值