Parsing NASA thermodynamic data using MATLAB
Aim : Parsing NASA Thermodynamic Data in MATLAB
Data Parsing : It refers to the process of converting information represented in one form into another form to make it easier to work with. It is done by first partially analysing the data, understanding its logic & structure , then representing that structure in some code.
Governing Equations : Properties like Specific Heat(C_p), Enthalpy(H) & Entropy(S) of a particular element or compound changes with respect to change in temperature.
The following equations represent that below,
`C_p/R = a_1 + a_2*T + a_3*T^2 + a_4*T^3 + a_5*T^4`
`H/(R*T) = a_1 + a_2*T/2 + a_3*T^2/3 + a_4*T^3/4 + a_5*T^4/5 + a_6/T`
`S/R = a_1*lnT+a_2*T + a_3*T^2/2 + a_4*T^3/3 + a_5*T^4/4 + a_7`
R is the universal gas constant & T is the absolute thermodynamic temperature.
The NASA thermodynamic file contains these (a1-a7) coefficients for low temperature & high temperature range.
The data file link is https://drive.google.com/file/d/1AikCHDlz9s_fu8whE81qee_GD4AyYpCP/view
Objectives :
i. Write a function that extracts the 14 co-efficients and calculates the enthalpy, entropy and specific heats for all the species in the data file.
ii. Calculate the molecular weight of each species and display it in the command window.
iii. Plot the Cp, Enthalpy and Entropy for the local temperature range (low temperature : high temperature) specific for each species.
iv. Save the plots as images with appropriate names and dump them in separate folders for each species with suitable name(automatically).
Explanation of Code :
- First, the 'THERMO.dat' file is loaded , then first line is skipped using fgetl, From second line value of Global Temperature are extracted & again next 3 lines are skipped.
- Now several matrix are predefined for making code more efficient, To get the element names line1 gets the first line required contanning the name of compounds & speecific local temperature range.
- Code for extraction of coefficients is done in the while loop which exits when it encounter string "END" in the dat file.
- Coming back to line1, strsplit command is used to split strings by space between them & names are stored in element_names.
- In the same line1, to get the local temperatures, line1 is flipped using flip command & position 2, 3 & 4 are local mid , high , low temperatures respectively.
- To get the coefficients, each coefficient are made up of 15 value using this information, A for loop is used to obatin this values & are stored in coef_mat.
- Unnecessary variables are cleared whenever required.
- For the plots , A range is required as we have two range one for low temperature & other for high temperature, A variable data_pts is assigned for that purpose.
- The names of compounds are in string data type, but to use them in for loop they are converted into character data type.
- The code for calculation of Cp, H & S is pretty straightforward ahead.
- Lastly, the plots for all three properties for each compound is generated & saved in unique folder as required.
Main Code :
clear all;
close all;
clearvars;
clc;
% open a file descriptor
fd = fopen('THERMO.dat','r');
% Skip first line
fgetl(fd);
% Scan 2nd line temperature range
global_temp = (fscanf(fd, ' %f %f %f\n')).';
% Skip next 3 lines
fgetl(fd);
fgetl(fd);
fgetl(fd);
% Read each data point
element_names = [];
coef_mat = [];
local_temp = [];
line1 = fgetl(fd);
while ~strcmp(line1, 'END')
% only read element name from 1st line
a = strsplit(line1);
element_names = [element_names; a(1, 1)];
% for local temperatures
b = flip(a);
local_low = str2double(b{4});
local_mid = str2double(b{2});
local_high = str2double(b{3});
local_temp = [local_temp; local_low, local_mid, local_high];
% local_temp - end
% extract coefficients
line2 = fgetl(fd);
line3 = fgetl(fd);
line4 = fgetl(fd);
num_start_idx = (1:15:61).'; % . is used to make it column vector
[m, ~] = size(num_start_idx); % why not just m - tanu
coef_row = zeros(1, 15);
for i = 1:m
idx = num_start_idx(i);
val_line2 = str2double(line2(idx:idx+14));
val_line3 = str2double(line3(idx:idx+14));
val_line4 = str2double(line4(idx:idx+14));
coef_row(1, i) = val_line2;
coef_row(1, i + 5) = val_line3;
coef_row(1, i + 10) = val_line4;
end
coef_mat = [coef_mat; coef_row];
line1 = fgetl(fd);
end
fclose(fd);
% drop last col - NAN , Removing 15th entry from each elements
coef_mat = coef_mat(:, 1:14);
% clear unwanted variables
% remove when using this as function
clear fd line1 line2 line3 line4
clear i a idx m num_start_idx val_line2 val_line3 val_line4
clear ans
clear coef_row
clear b local_low local_mid local_high
% Calculation of constants
% local_temp(:,1) = low temperature range
% local_temp(:,3) = high temperature range
% coef_mat column 1 to 7 are high temperature coefficients
% coef_mat column 8 to 14 are low temperature coefficients
R = 8.314472; % Declaration of Universal Gas Constant
data_pts = 100; % It represents the number of data points between temperature range
cp = zeros(53, data_pts*2);
h = zeros(53, data_pts*2);
s = zeros(53, data_pts*2);
temperature = zeros(53,data_pts*2);
species = char(element_names); % Converting string into character data type
for j = 1:length(element_names)
t_l = linspace(local_temp(j,1),local_temp(j,2),data_pts); % low temperature range
t_h = linspace(local_temp(j,2)+1,local_temp(j,3),data_pts);%high temperature range
% CP - Specific Heat
cp_low = zeros(1,data_pts);
cp_high = zeros(1,data_pts);
for i=1:data_pts
cp_low(1,i) = R.*( coef_mat(j,8) ...
+ coef_mat(j,9).*(t_l(1,i))...
+ coef_mat(j,10).*(t_l(1,i)).^2 ...
+ coef_mat(j,11).*(t_l(1,i)).^3 ...
+ coef_mat(j,12).*(t_l(1,i)).^4);
cp_high(1,i) = R.*( coef_mat(j,1) ...
+ coef_mat(j,2).*(t_h(1,i))...
+ coef_mat(j,3).*(t_h(1,i)).^2 ...
+ coef_mat(j,4).*(t_h(1,i)).^3 ...
+ coef_mat(j,5).*(t_h(1,i)).^4);
end
cp(j,:) = [cp_low cp_high];
% H - Enthalpy
h_low = zeros(1,data_pts);
h_high = zeros(1,data_pts);
for i=1:data_pts
h_low(1,i) = (R.*t_l(1,i)).*( coef_mat(j,8)...
+ (coef_mat(j,9).*(t_l(1,i)))./2 ...
+ (coef_mat(j,10).*(t_l(1,i)).^2)./3 ...
+ (coef_mat(j,11).*(t_l(1,i)).^3)./4 ...
+ (coef_mat(j,12).*(t_l(1,i)).^4)./5 ...
+ (coef_mat(j,13)./t_l(1,i)) ) ;
h_high(1,i) = (R.*t_h(1,i)).*(coef_mat(j,1)...
+ (coef_mat(j,2).*(t_h(1,i)))./2 ...
+ (coef_mat(j,3).*(t_h(1,i)).^2)./3 ...
+ (coef_mat(j,4).*(t_h(1,i)).^3)./4 ...
+ (coef_mat(j,5).*(t_h(1,i)).^4)./5 ...
+ (coef_mat(j,6)./t_h(1,i)) ) ;
end
h(j,:) = [h_low h_high];
% S - Entropy
s_low = zeros(1,data_pts);
s_high = zeros(1,data_pts);
for i=1:data_pts
s_low(1,i) = R.*( (coef_mat(j,8) .* log(t_l(1,i))) ...
+ (coef_mat(j,9).*(t_l(1,i)) ) ...
+ (coef_mat(j,10).*(t_l(1,i)).^2)./2 ...
+ (coef_mat(j,11).*(t_l(1,i)).^3)./3 ...
+ (coef_mat(j,12).*(t_l(1,i)).^4)./4 ...
+ coef_mat(j,14) ) ;
s_high(1,i) = R.*( (coef_mat(j,1) .* log(t_h(1,i))) ...
+ (coef_mat(j,2).*(t_h(1,i)) ) ...
+ (coef_mat(j,3).*(t_h(1,i)).^2)./2 ...
+ (coef_mat(j,4).*(t_h(1,i)).^3)./3 ...
+ (coef_mat(j,5).*(t_h(1,i)).^4)./4 ...
+ coef_mat(j,7) ) ;
end
s(j,:) = [s_low s_high];
temperature(j,:) = [t_l t_h];
% Plot Generation
% Creating Folder
folder_name = sprintf( '%d) %s',j,species(j,:));
current_dir = pwd;
mkdir(folder_name); % Create folder
cd(folder_name); % To open that folder
figure(1);
plot(temperature(j,:),cp(j,:),'r','linewidth',3);
grid on
xlabel('Local Temperature (K)')
ylabel('Specific Heat (J/kg-K)')
title('Variation of Specific Heat w.r.t Temperature')
image1 = sprintf("Cp Vs. T of %s.png",species(j,:)); % naming file
saveas(gca,image1) % saving image
figure(2);
plot(temperature(j,:),h(j,:),'b','linewidth',3);
grid on
xlabel('Local Temperature (K)')
ylabel('Enthalpy (J)')
title('Variation of Enthalpy w.r.t Temperature')
image2 = sprintf("H Vs. T of %s.png",species(j,:)); % naming file
saveas(gca,image2) % saving image
figure(3);
plot(temperature(j,:),s(j,:),'g','linewidth',3);
grid on
xlabel('Local Temperature (K)')
ylabel('Entropy (J/K)')
title('Variation of Entropy w.r.t Temperature')
image3 = sprintf("S Vs. T of %s.png",species(j,:)); % naming file
saveas(gca,image3) % saving image
cd(current_dir); % Returning to current directory
% Plot - end
end
% Clearing unwanted variables to mantain workplace minimal
clear cp_low cp_high h_low h_high i j s_low s_high t_l t_h
Code for calculation of Molecular Weight :
- For the purpose of calculation of molecular weight, MATLAB (containers)mapping is used.
- In mapping a key_element is assigned a value, for eg here 'C' for carbon atom its molecular weight is assigned '12.0107'.
- Next, The for loop is initiated to run for all 53 compunds/elements.
- Using strip() command the empty spaces are eliminated.
- So that the while loop runs only for the number of characters present in that string.
- Each character is compard with the mapped elements & their respective molecular weight is appened, When a digit is encountered it is stored alongwith its previous character.
- At the end the final molecular weight is calculated, stored & displayed in command window.
element = {'H','C','N','O','A','(','S',')','R'};
atomic_weight = [1.0078 12.0107 14.0067 15.9949 39.9480, 0.00, 32.0600, 0.00, 0.00];
elem_weight_map = containers.Map(element, atomic_weight);
molecular_weight = zeros(length(element_names),1);
for jj = 1:length(element_names)
speci = strip(species(jj,:));
%fprintf('%s\n', speci);
idx = 1;
len = length(speci);
while idx <= len
elem = speci(1, idx);
num = 1;
if (idx < len) && isstrprop(speci(1, idx+1), 'digit')
num = str2double(speci(1, idx+1));
idx = idx + 2;
else
idx = idx + 1;
end
molecular_weight(jj,1) = molecular_weight(jj,1) + elem_weight_map(elem)*num;
end
fprintf('%2.0f.The molecular weight of %s is %f. \n \n ',jj,speci,molecular_weight(jj,1))
end
Molecular Weights (In amu) :
Plots of all species :
Plots for (`O_2`)
Plots for (`N_2`)
Plots for (`CO_2`)
Erros Faced : Several errors were faced , but the major ones were the following:
1. Incorrect parenthesis in the calculation of Cp, H & S.
2. To get the value of local temperatures firstly I find the postion of G & next three values would be the temperature values, But for some elements this caused a problem because the number of elements in that row were different from the rest, Therefore to avoid that another logic was used incorporationg flip().
Conclusion : During the B.Tech course generally, The value of above properties are taken constant for various problem solving which does not hold true for real-world application, Hence the incorporation of such variation are important.
With the help of Data parsing, these variation of properties can be esaily used in mathematical problem solving in MATLAB.