Function over a vector which involves a sum over 3D coordinates
Mostra commenti meno recenti
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 Commenti
KSSV
il 1 Set 2022
Show us your code.
Jared Goldberg
il 1 Set 2022
Star Strider
il 1 Set 2022
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
il 1 Set 2022
Torsten
il 1 Set 2022
Did you make sure that ex_k is not 1 and T(i) is not 0 ?
Jared Goldberg
il 1 Set 2022
Torsten
il 1 Set 2022
If I exclude the denominator in your expression for "summand", I get no NaN values ...
Jared Goldberg
il 1 Set 2022
>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
il 1 Set 2022
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
il 1 Set 2022
Risposta accettata
Più risposte (1)
Bruno Luong
il 1 Set 2022
Modificato: Bruno Luong
il 1 Set 2022
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 Commenti
Jared Goldberg
il 1 Set 2022
Bruno Luong
il 1 Set 2022
Modificato: Bruno Luong
il 1 Set 2022
"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
il 1 Set 2022
%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
il 1 Set 2022
Bruno Luong
il 1 Set 2022
>> abs_k(505051)
ans =
0
Jared Goldberg
il 1 Set 2022
Categorie
Scopri di più su MATLAB in Centro assistenza e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!