Challenge

Project 1 - Parsing NASA thermodynamic data

Parsing data using MATLAB:

Parsing or syntactic analysis is the process of analyzing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar.

Aim of this project:

The main aim of this project is to read and accordingly process data from a .dat file, in which the coefficients for calculating specific heat, enthalpy and entropy of various compounds are stored.

Governing equations:

The three equations that are given are:

Here Cp, H and S denote specific heat, enthalpy and entropy respectively. a1, a2, a3 ...........a7 denote the coefficients. T represents the temperature and R represents universal gas constant (8.314 J/mol/K)

Objectives of this project:

1. The primary objective is to obtain a plot of specific heat, enthalpy and entropy for all the compounds whose coefficients are given in the 'THERMO.dat' file. During this process, the header information has to be treated separately and the information that is read has to converted from a string data type to a number wherever needed.

2. These plots have to be stored under a separate file for each compound automatically.

3. The molecular weights of the compounds also have to be determined and printed on the command window.

The language that was used to code this program is MATLAB R2020a.

Description of the logic:

1. The THERMO.dat file is opened initially using the 'fopen' command. This is assigned to a variable that acts as a pointer to this file. This pointer will be used in later referencing of this file.

2. Another important command used here is 'fgetl'. This command is used to read each line of the text file in a sequential manner.

Processing of the header information:

3. The first five lines of this dat contains header information. As this information is not used anywhere in the program this is just skipped using the 'fgetl' command. Only the global temperatures are converted to a number data type from string data type.

Processing the main part of the THERMO.dat file:

4. From the next line onwards, the information about each species is given. Each compound (species) has four lines of information.

5. The first line contains the species name and its temperature ranges. This line is read an entire string and is split into parts using the 'splitstr' command. Here space is used as a delimiter. So the entire string is divided into parts where instances of space is found.

6. The species temperature ranges are read as a string. They are converted to a number using the 'str2num' command.

7. This is followed by 3 lines with has 14 coefficients. The first seven denote high temperature coefficients and the next seven denote low temperature coefficients. These lines, having 5, 5 and 4 coefficients respectively are read separately. They are also converted to a number using the 'str2num' command.

Logic for identifying the exponent:

a. Each coefficient has an exponent part. So before converting this string to a number, the first coefficient has to be distinguished from the next.

b. To do this, 'findstr' is used in which E is the delimiter. This returns an array of instances where E is found in the entire line.

c. This is manipulated as, from the 1 st character in the line until 3rd character after the first instance of E is one coefficient. Then, from the 4th character of the first instance of E until the 3rd character of the second instance of E is the second coefficient. This is represented as:

a1=str2num(coeff_str(1:coeff_E(1)+3));
a2=str2num(coeff_str(coeff_E(1)+4:coeff_E(2)+3));

8. Then these coefficients are grouped into arrays of high and low temperature coeffecients.

9. Then specific heat, enthalpy and entropy and molecular of various compounds are computed using separate functions.

10. Using the 'plot' command a graph of temperature vs specific heat, enthalpy and entropy of various compounds are created.

11. This entire block is repeated using a for loop to extract data for all 53 compounds.

Plotting the graphs and automatically storing them in separate folders:

1. Using the 'mkdir' command a new folder is created and 'cd' is used to set the current working directory to the newly created folder.

2. The 'saveas' command is used to save the plot.

3. After this, the current working directory has to be set to the previous working directory.

4. The molecular weights of the compounds are also calculated using a separate function and are printed to the command window using the 'sprintf' command.

The program is as below

Main program:

% A program to parse thermodynamic data, which calaulates the specific heat
%, enthalpy and entrpy of the given species and generate plots

close all
clear all
clc

% Opening the data file
fh1=fopen('THERMO.dat','r');

% Reading the first line of the header
sk1=fgetl(fh1);

% Accquring global temperature ranges
global_temp_string=fgetl(fh1);
global_temp_string_no_space=strsplit(global_temp_string(4:end));

% Converting the global temperatures range from string to number
global_low_temp=str2num(global_temp_string_no_space{1});
global_mid_temp=str2num(global_temp_string_no_space{2});
global_high_temp=str2num(global_temp_string_no_space{3});

% Skipping the next three lines
for i1=1:3 
    fgetl(fh1);
end



for i7=1:53;


% Acquiring the species name
sk2=fgetl(fh1);
species_head_info=strsplit(sk2,' ');
species_name=species_head_info{1};

% Acquiring the temperature ranges for the species
species_temp_str=sk2(49:75);
species_temp_split=strsplit(species_temp_str);
species_low_temp=str2num(species_temp_split{1});
species_mid_temp=str2num(species_temp_split{3});
species_high_temp=str2num(species_temp_split{2});

species_temp_range=[species_low_temp,species_mid_temp,species_high_temp];

% Reading the values of the coeffecients of first line in the species
coeff_str=fgetl(fh1);
coeff_E=findstr(coeff_str,'E');


a1=str2num(coeff_str(1:coeff_E(1)+3));
a2=str2num(coeff_str(coeff_E(1)+4:coeff_E(2)+3));
a3=str2num(coeff_str(coeff_E(2)+4:coeff_E(3)+3));
a4=str2num(coeff_str(coeff_E(3)+4:coeff_E(4)+3));
a5=str2num(coeff_str(coeff_E(4)+4:coeff_E(5)+3));

% Reading the values of the coeffecients of second line in the species
coeff_str2=fgetl(fh1);
coeff_E2=findstr(coeff_str2,'E');

a6=str2num(coeff_str2(1:coeff_E2(1)+3));
a7=str2num(coeff_str2(coeff_E2(1)+4:coeff_E(2)+3));
a8=str2num(coeff_str2(coeff_E2(2)+4:coeff_E2(3)+3));
a9=str2num(coeff_str2(coeff_E2(3)+4:coeff_E2(4)+3));
a10=str2num(coeff_str2(coeff_E2(4)+4:coeff_E2(5)+3));

% Reading the values of the coeffecients of second line in the species
coeff_str3=fgetl(fh1);
coeff_E3=findstr(coeff_str3,'E');


a11=str2num(coeff_str3(1:coeff_E3(1)+3));
a12=str2num(coeff_str3(coeff_E3(1)+4:coeff_E3(2)+3));
a13=str2num(coeff_str3(coeff_E3(2)+4:coeff_E3(3)+3));
a14=str2num(coeff_str3(coeff_E3(3)+4:coeff_E3(4)+3));


% Calculating specific heat,enthalpy and entropy of the species

R=8.314; % Value of universal gas constant in J/mol-K

temp_array=linspace(species_low_temp,species_high_temp,250);

Cp=specific_heat(a1,a2,a3,a4,a5,a8,a9,a10,a11,a12,temp_array,R,species_temp_range);
H=enthalpy(a1,a2,a3,a4,a5,a6,a8,a9,a10,a11,a12,a13,temp_array,R,species_temp_range);
S=entropy(a1,a2,a3,a4,a5,a7,a8,a9,a10,a11,a12,a14,temp_array,R,species_temp_range);


current_working_folder=pwd;

% Making a new folder for the species to save the plots

mkdir(species_name);
cd(species_name);



% Plotting Specific heat 
figure(1);
plot(temp_array,Cp,'linewidth',2,'color','b');
xlabel('Temperature in K')
ylabel('Specific Heat in J/kg')
title(species_name)

% Plotting Enthalpy 
figure(2);
plot(temp_array,H,'linewidth',2,'color','r');
xlabel('Temperature in K')
ylabel('Enthalpy in J/kg')
title(species_name)

% Plotting Entropy
figure(3);
plot(temp_array,S,'linewidth',2,'color','g');
xlabel('Temperature in K')
ylabel('Entropy in J')
title(species_name)

% Saving the plots of each species in a seperate folder
saveas(1,'Specific heat.jpg')
saveas(2,'Enthalpy.jpg')
saveas(3,'Entropy.jpg')


cd(current_working_folder);

M=molecular_weight(species_name);

fh3=fopen('molecular_weights.txt','a+');
fprintf(fh3,'\n %d. The molecular weight of %s is: %f  \n',i7,species_name, M);
fclose(fh3);


%Printing the molecular weights to the command window
sprintf('The molecular weight of %s is: %f  \n',species_name,M)

end







    





Function to calculate specific heat:

% Function to calculate specific heat
function [Cp]=specific_heat(a1,a2,a3,a4,a5,a8,a9,a10,a11,a12,temp_array,R,species_temp_range);
    % Checking if the temperature falls in the low or high temperature
    % range (a1,a2,a3,a4,a5 are for high temp & a8,a9,a10,a11,a12 are for
    % high temp)
    for i=1:length(temp_array)
    
        if temp_array(i)>species_temp_range(2);
            Cp(i)=R*(a1+a2*temp_array(i)+a3*(temp_array(i))^2+a4*(temp_array(i))^3+a5*(temp_array(i))^4);
        else 
            Cp(i)=R*(a8+a9*temp_array(i)+a10*(temp_array(i))^2+a11*(temp_array(i))^3+a12*(temp_array(i))^4);
                
        end
end

Function to calculate enthalpy:

% Function to calculate enthalpy
function H=enthalpy(a1,a2,a3,a4,a5,a6,a8,a9,a10,a11,a12,a13,temp_array,R,species_temp_range);
% Checking if the temperature falls in the low or high temperature
    % range (a1,a2,a3,a4,a5,a6 are for high temp & a8,a9,a10,a11,a12,,a13 are for
    % high temp)
    for i=1:length(temp_array)
    
        if temp_array(i)>species_temp_range(2);
            H(i)=R*(a1+a2*(temp_array(i))/2+a3*((temp_array(i)^2)/3+a4*((temp_array(i)))^4+a5*((temp_array(i))^4)/5+a6*((temp_array(i))^5)/6));
        else 
         H(i)=R*(a8+a9*(temp_array(i))/2+a10*((temp_array(i)^2)/3+a11*((temp_array(i)))^4+a12*((temp_array(i))^4)/5+a13*((temp_array(i))^5)/6));
                
        end
end

Function to calculate entropy:

% Function to calculate entropy
function S=entropy(a1,a2,a3,a4,a5,a7,a8,a9,a10,a11,a12,a14,temp_array,R,species_temp_range);
% Checking if the temperature falls in the low or high temperature
    % range (a1,a2,a3,a4,a5,a7 are for high temp & a8,a9,a10,a11,a12,a14 are for
    % high temp)
    
    for i=1:length(temp_array)
    
        if temp_array(i)>species_temp_range(2);
            S(i)=R*(a1*log(temp_array(i)) + a2*temp_array(i) + a3*(temp_array(i)^2)/2 + a4*(temp_array(i)^3)/3 + a5*(temp_array(i)^4)/4 + a7);
        else 
          S(i)=R*(a8*log(temp_array(i)) + a9*temp_array(i) + a10*(temp_array(i)^2)/2 + a11*(temp_array(i)^3)/3 + a12*(temp_array(i)^4)/4 + a14);
                
        end
end

Function to calculate the molecular weight of the species:

% Function to calculate the molecular weight of the species
function M=molecular_weight(species_name);
elements={'H','C','N','O','S','Ar'};
atomic_mass=[1.00797,12.011,14.0067,15.9994,32.06,39.948];

M=0;

for i=1:length(species_name)
    for j=1:length(elements)
        if strcmp(species_name(i),elements(j));
            M=M + atomic_mass(j);
            temp_m=j;
            
        end
    end

    temp2_m=str2num(species_name(i));
    
    if temp2_m>1;
        M= M + atomic_mass(temp_m)*(temp2_m - 1);
    end 
end
end

Results:

Screenshot of the window where folders for each species was created

Plots for O2

Plots for N2

Plots for CO2

Molecular weights being displayed on the command window and being stored in a seperate text file

Errors faced while programming:

1. If the parameters are not passed in the correct order while calling a function, an error will be created.

2. One of the difficult errors to spot are logical error. While coding this program, I initially assigned the value of a cell array for the species low, mid and high temperatures. But later, I found out that the no of elements of the cell array was fluctuating between 8 and 9 elements .So the values were assigned based on the position of the characters as they were the same for all the species.

3. If the output argument is not indexed within a loop, only a single value will be returned instead of a matrix. Instead of Cp(i) , only Cp was entered. This resulted in the last value of Cp in the loop being displayed instead of a matrix.

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.