Function over a vector which involves a sum over 3D coordinates
显示 更早的评论
Hi all, I am working on a numerical approximation for heat capacity as a function of temperature. The temperate is a 1x500 vector, and so the heat capacity vector needs to be 1x500 as well. My problem is that the function at each temperature involves a sum over a 100x100x100 grid. EDIT: The function in question is:

Where the vector
runs over the 100x100x100 values in the grid. The question is how can I deal with creating the discrete values as a function of T with the sum over the grid in each entry? The code I tried to run is:
%%Heat Capacity
%Definining relevant quanitites
k_B = 1.38*10^(-23);
N = 100;
a = 4*10^(-10); %m
L_i = a*N;
w_0 = 10*10^12; %Hz
hbar = 1.0545*10^(-34);
c_v_a_ht = 3*k_B*N^3/a^3;
del_k = (2*pi)^3/L_i^3;
del_k_i = 2*pi/L_i;
bz_1 = pi/a;
%First Brillouin Zone
k_x = -bz_1:del_k_i:bz_1-del_k_i;
k_y = -bz_1:del_k_i:bz_1-del_k_i;
k_z = -bz_1:del_k_i:bz_1-del_k_i;
[X,Y,Z] = meshgrid(k_x,k_y,k_z);
%Temp vector
debye_temp = (hbar/k_B)*w_0*(3*pi^2/4)^(1/3); %K
T = 0.001*debye_temp:debye_temp/500:debye_temp;
%Heat capacity approx
abs_k = sqrt(X.^2+Y.^2+Z.^2);
beta = 1./(k_B*T);
c_v_a = ones(1,500);
for i=1:500
ex_k = exp(beta(i)*hbar*w_0*a.*abs_k/2)
summand = (hbar^2* w_0^2 .*(abs_k.^2)*a^2.*ex_k)./(4*(ex_k-1).^2*k_B*(T(i)^2))
c_v_a(i) = sum(summand,'all')
end
11 个评论
KSSV
2022-9-1
Show us your code.
Jared Goldberg
2022-9-1
Star Strider
2022-9-1
It might be best to interpolate the temperature vector to (1x100) to match the matrix. Doing the opposite (interpolating the matrix to be 500 in the chosen dimension) risks creating data.
Jared Goldberg
2022-9-1
Torsten
2022-9-1
Did you make sure that ex_k is not 1 and T(i) is not 0 ?
Jared Goldberg
2022-9-1
Torsten
2022-9-1
If I exclude the denominator in your expression for "summand", I get no NaN values ...
Jared Goldberg
2022-9-1
>See what MATLAB server returns:
%%Heat Capacity
%Definining relevant quanitites
k_B = 1.38*10^(-23);
N = 100;
a = 4*10^(-10); %m
L_i = a*N;
w_0 = 10*10^12; %Hz
hbar = 1.0545*10^(-34);
c_v_a_ht = 3*k_B*N^3/a^3;
del_k = (2*pi)^3/L_i^3;
del_k_i = 2*pi/L_i;
bz_1 = pi/a;
%First Brillouin Zone
k_x = -bz_1:del_k_i:bz_1-del_k_i;
k_y = -bz_1:del_k_i:bz_1-del_k_i;
k_z = -bz_1:del_k_i:bz_1-del_k_i;
[X,Y,Z] = meshgrid(k_x,k_y,k_z);
%Temp vector
debye_temp = (hbar/k_B)*w_0*(3*pi^2/4)^(1/3); %K
T = 0.001*debye_temp:debye_temp/500:debye_temp;
%Heat capacity approx
abs_k = sqrt(X.^2+Y.^2+Z.^2);
beta = 1./(k_B*T);
c_v_a = ones(1,500);
for i=1:500
ex_k = exp(beta(i)*hbar*w_0*a.*abs_k/2);
if any(ex_k(:) == 1)
fprintf('0 denominator for sure\n')
return
end
summand = (hbar^2* w_0^2 .*(abs_k.^2)*a^2.*ex_k)./(4*(ex_k-1).^2*k_B*(T(i)^2));
c_v_a(i) = sum(summand,'all');
end
Torsten
2022-9-1
I also don't, but I can't just exclude the denominator, it is part of the function I am trying to approximate.
But that's no argument to divide by 0 ...
Jared Goldberg
2022-9-1
采纳的回答
更多回答(1 个)
Bruno Luong
2022-9-1
编辑:Bruno Luong
2022-9-1
You get 0/0 expression when abs_k is small (or 0), returning NaN.
summand = (hbar^2* w_0^2 .*(abs_k.^2)*a^2.*ex_k)./(4*(ex_k-1).^2*k_B*(T(i)^2))
You should make use of Taylor expansion of exp function to simplify the ratio
... (abs_k).^2/(ex_k-1) ...
7 个评论
Jared Goldberg
2022-9-1
"abs_k should never be small or zero"
Not in your script.
How do you check? See what the MATLAB server tell me, there is clearly index where abs_k == 0
%%Heat Capacity
%Definining relevant quanitites
k_B = 1.38*10^(-23);
N = 100;
a = 4*10^(-10); %m
L_i = a*N;
w_0 = 10*10^12; %Hz
hbar = 1.0545*10^(-34);
c_v_a_ht = 3*k_B*N^3/a^3;
del_k = (2*pi)^3/L_i^3;
del_k_i = 2*pi/L_i;
bz_1 = pi/a;
%First Brillouin Zone
k_x = -bz_1:del_k_i:bz_1-del_k_i;
k_y = -bz_1:del_k_i:bz_1-del_k_i;
k_z = -bz_1:del_k_i:bz_1-del_k_i;
[X,Y,Z] = meshgrid(k_x,k_y,k_z);
%Temp vector
debye_temp = (hbar/k_B)*w_0*(3*pi^2/4)^(1/3); %K
T = 0.001*debye_temp:debye_temp/500:debye_temp;
%Heat capacity approx
abs_k = sqrt(X.^2+Y.^2+Z.^2);
beta = 1./(k_B*T);
c_v_a = ones(1,500);
for i=1:500
ex_k = exp(beta(i)*hbar*w_0*a.*abs_k/2);
% Detect pb in denominator
b = ex_k == 1;
if any(b(:))
ibad = find(b(:));
abs_k = abs_k(ibad)
beta(i)*hbar*w_0*a.*abs_k/2
exp(beta(i)*hbar*w_0*a.*abs_k/2)
return
end
summand = (hbar^2* w_0^2 .*(abs_k.^2)*a^2.*ex_k)./(4*(ex_k-1).^2*k_B*(T(i)^2));
c_v_a(i) = sum(summand,'all');
end
Jared Goldberg
2022-9-1
%Definining relevant quanitites
k_B = 1.38*10^(-23);
N = 100;
a = 4*10^(-10); %m
L_i = a*N;
w_0 = 10*10^12; %Hz
hbar = 1.0545*10^(-34);
c_v_a_ht = 3*k_B*N^3/a^3;
del_k = (2*pi)^3/L_i^3;
del_k_i = 2*pi/L_i;
bz_1 = pi/a;
%First Brillouin Zone
k_x = -bz_1:del_k_i:bz_1-del_k_i;
k_y = -bz_1:del_k_i:bz_1-del_k_i;
k_z = -bz_1:del_k_i:bz_1-del_k_i;
[X,Y,Z] = meshgrid(k_x,k_y,k_z);
abs_k = sqrt(X.^2+Y.^2+Z.^2);
find(abs_k==0)
Jared Goldberg
2022-9-1
Bruno Luong
2022-9-1
>> abs_k(505051)
ans =
0
Jared Goldberg
2022-9-1
类别
在 帮助中心 和 File Exchange 中查找有关 MATLAB 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!