Project

Project 1 - Parsing NASA Thermodynamic Data

Project 1 - Parsing NASA Thermodynamic Data

Objectives:

1. 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

2. Calculate the molecular weight of each species and display it in the command window.

3. Plot the Cp, Enthalpy and Entropy for the local temperature range (low temperature : high temperature) specific for each species.

4. Save the plots as images with appropriate names and dump them in separate folders for each species with suitable name. All these should be generated automatically.

5. The main program that you will submit will just take the \"THERMO.dat\" file as an input and generate Cp, H and S plots.

ANS:

Theory

Parsing is the method of reading from or writing to a file (usually a text file) and obtaining information from it. It is the process of analyzing text made up of a sequence of tokens to determine its grammatical structure with respect to a given grammar that may be more or less formal. Parsing a file means reading in a data stream of some sort and then building an in memory model of the semantic content of that data. This is all done for the purpose of transforming the data in the file for some use. The raw data found in the file, initially may be difficult to read or to comprehend as it may be unformatted and disorganized. By performing parsing, we can split the sequence of characters in the data in to smaller parts, based on some rules we create. Hence, we can transform the data for a particular use or application.

In this project, I will be performing file parsing on the NASA thermodynamic file. It is a text file that contains a list of 53 different chemical species and each one carries with it a range of local temperatures and after, a list of 14 coefficients. The first 7 are referred to as high temperature coefficients and the remaining 7 are referred to as low temperature coefficients. The coefficients are applicable for the calculations of specific heat, enthalpy and entropy for each chemical species.

We need to parse the thermodynamic file and obtain the names of each chemical species, their local temperature range, their 14 coefficients and their molecular weights. From this data, we need to calculate the specific heat, enthalpy and entropy of each species using the required coefficients and temperature values. Finally, we need to plot separate graphs of the specific heat, enthalpy and entropy against their respective temperature for each species. This will be performed using functions and scripts to obtain, store and output the necessary information form the thermodynamic file.

An image of an extract of the data in the thermodynamic file is shown below:

As we can see, at the sixth line, the first species is listed with its chemical name and its local temperature range in the same line. In the second, third and fourth lines, the first 7 coefficients are the high temperature coefficients and the remaning 7, the low temperature coefficients. All other text is considered comments and are not useful for our use.

The formulas for the specific heat, enthalpy and entropy are listed below:

1. Specific Heat, Cp (KJ/KmolK)

`C_p / R = a_1 + (a_2*T) + (a_3*T^2) + (a_4*T^3) + (a_5*T^4)`

The specific heat of a material is the measure of the amount of energy (in KJ) required to raise the temperature of 1kg of the material by 1 kelvin.

2. Enthalpy, H (KJ/Kg)

`H/(R*T) = a_1 + (a_2/2*T) + (a_3/3*T^2) + (a_4/4*T^3) + (a_5/5*T^4) + (a_6/T)`

The enthalpy of a material, H, is the sum of its internal energy plus the product of the pressure and volume of the thermodynamic system. It reflects the material\'s capacity to do non-mechanical work and its capacity to release heat. It is essentially, the amount of heat transfer that occurs at a constant pressure and it is measured in KJ/Kg.

3. Entropy, S (KJ/K)

`S/R = (a_1*log*T) + (a_2*T) + (a_3/2*T^2) + (a_4/3*T^3) + (a_5/4*T^4) + (a_7)`

Entropy is a measure of uncertainty or randomness and tells us in a numerical form, how much disorder there is in a thermodynamic system. This is useful for us because this measures how likely a chemical reaction is to take place. By definition, the entropy is the number of possible arrangements that atoms of a system can take. The greater the number of arrangements, the greater the entropy. Entropy is measured in KJ/K.

For all 3 formulas, the notation of the terms are explained below:

where,

Coefficients - a1, a2, a3, a4, a5, a6 and a7

These coefficients can be high temperature or low temperature ones and the ones which are used depends on what temperature level is used to calculate the specific heat, enthalpy and entropy.

Temperature - T (in Kelvin)

Molar Gas Constant - R (J/molK)

Main Program

clear all
close all
clc

% Opening of Text File 
f1 = fopen(\'THERMONEW.txt\', \'r\')
fgetl(f1);
fgetl(f1);

% R is the molar gas constant 
R = 8.31;

I began with the clear all, close all and clc commands to reset all variables and values from previous sessions. Next, the \'fopen\' command is used to open a text file for parsing purposes. Within the parentheses, in the first position we need to enter the file name along with its extension followed by whether we want to read or write to the file. The thermodynamic file is a text file with the name, \'THERMONEW\' and it has the extension (.txt). This file name and extension together must be entered within quotation marks. We want to read from this file, so we enter \'r\' for read. The command to open the file is assigned to the variable, \'f1\'. Everytime the command is executed, the command window will show that \'f1\' is equal to some value. If this value is positive, then it means the file has been opened successfully.

Next, the \'fgetl\' command is used to skip comment lines. The first time it is used, it is to get to the first line which is blank. The second time it is used is to get to the second line which contains the comment, \'THERMO\'.

Then, I have created the variable R and assigned it to a value of 8.31 which represents the molar gas constant. This will be used later in the calculations for the specific heat, enthalpy and entropy for each species.

% Finding the global temperatures 
global_temp_str = fgetl(f1);
global_temp = strsplit(global_temp_str, \' \');
global_low_temp = str2double(global_temp(1))
global_mid_temp = str2double(global_temp(2))
global_max_temp = str2double(global_temp(3))

In this section, the \'fgetl\' command is used again to arrive at the second line which contains the global temperatures for the chemical species. Since this is a string, I have assigned this line to the variable, \'global_temp_str\' for global temperature string. Then, I splitted this string using the \'strsplit\' command to separate the temperature values in to 3 different cells (still strings) and assigned them to the variable, \'global_temp\'. The first temperature in the \'global_temp\' variable is the global low temperature and is in the first index position. So in the next three lines, I have assigned variables for the global low, middle and maximm temperatures using the \'str2double\' command to convert the strings to integers. The \'str2num\' command can also be used but calculations seem to be faster to compute for MATLAB with the \'str2double\' command instead.

% Skipping the comment lines
for i = 1:7
    fgetl(f1);
end

% No. of species in the file
spec_num = 53;

Then, a for loop is used to skip the next 7 comment lines. This was done for geting rid of redundant code that can be made shorter without having to repeat itself. Next, the total number of species in the thermodynamic file is given a value of 53 and assigned to the variable, \'spec_num\'. This value was obtained by counting each species individually in the thermodynamic file.

% Calling of function to retreive the local temperatures and coefficients
specdata = get_spec_data(f1, spec_num);

% Calling of function to calculate the Cp 
specdata = cp_calc(specdata, R);

% Calling of function to calculate the enthalpy, H
specdata = enthalpy_calc(specdata, R);

% Calling of function to calculate the entropy, S
specdata = entropy_calc(specdata, R);

% Calling of function to calculate the molecular weights
specdata = MW (specdata);

% Calling of function to plot the graph
graphs(specdata);


% Closing of Text File
fclose(f1)

These next few lines are all for the calling of the different functions I created in different scripts to perform the calculations for the specific heat, enthalpy, entropy and molecular weights. The scripts of these functions will be the next step.

In the last line, the \'fclose\' command is used to close the NASA thermodynamic text file.

Extraction of Coefficients (get_spec_data)

Function Creation

function specdata = get_spec_data(f1, spec_num)

In this section, I have created a function to parse the thermodynamic file to obtain the high and low temperature coefficients for each species. This function will use a for loop to go through each of the 53 species and extract the coefficients using a set of rules. In the first line, I have created the function called \'get_spec_data\' and the script name is the same as well. The inputs for this function come from the variables, \'f1\' and \'spec_num\'. The \'f1\' variable is used to input the data in the thermodynamic file and the variable \'spec_num\' is used as the second input so that the for loop knows how many times to loop for.

First Line

for i = 1:spec_num

% Line 1 Information    
spec_info = fgetl(f1);
spec_name = strtok(spec_info);                                                              % Species Name 
dot = strfind(spec_info, \'.\');                                                                     % Finding the decimal point of the temperatures 
local_low_temp = str2double(spec_info(dot(1) - 4 : dot(1) + 3));        % Local Low Temperature
local_max_temp = str2double(spec_info(dot(2) - 4 : dot(2) + 3));        % Local Maximum Temperature
local_mid_temp = str2double(spec_info(dot(3) - 4 : dot(3) + 3));         % Local Middle Temperature

Here, the for loop is created and the \'i\' counter is used to command the loop to repeat for \'spec_num\' times. Following the for loop used to skip the comment lines in the main program, the \'fgetl\' command is used to arrive at the first line of the first species, Oxygen. This first line is assigned to the variable \'spec_info\' as it contains the species information and it contains the species symbol (e.g. \'O\' for Oxygen) as well as the 3 local temperature values. The three temperature values are the local low, maximum and middle temperature values respectively.

The species name found in the first line will occupy a maximum of 6 characters only because the longest length of the species is 6 characters. So the variable \'spec_name\' is created and assigned to find selected parts of strings with the \'strtok\' command. It will ignore the first whitespace in the \'spec_info\' line and starts with the first non-whitespace character to include all characters from there till the next whitespace. This way, for any of the 53 species, their respective symbol will appear when the \'spec_name\' command is executed.

Then, a variable called \'dot\' is created to find the character \'.\' in the first line for the purpose of extracting the local temperatures. This will output an array of the index positions that each \'.\' takes in the first line. These index positions are used as references to extract each temperature value. The first temperature in the first line is the local low temperature and for Oxygen it is \'200.000\'. So, the dot variable will output the index position of the decimal point in \'200.000\'. So we need to tell the program when to start and finish counting the index positions of the temperatures in the \'spec_info\' line so that we get what we need.

The local middle and maximum temperatures are 4 characters long (before the decimal point), and have 3 zeroes after each decimal point. So, I have programmed the script to begin to find the characters at each index position of the \'dot\' variable. The search begins 4 index positions before a decimal point and ends 3 index positions after. So, I have created the variables \'local_low_temp\', \'local_max_temp\' and \'local_mid_temp\' for the local low, maximum and middle temperatures respectively. Each variable has been instructed to find the strings using the decimal points are references and to convert the strings in to integers using the \'str2double\' command. That way, the temperatures are changed from strings to numerical values which can be used for calculations.

% Saving the Species Name and Local Temp in specdata struct
specdata(i).SpeciesName = spec_name;
specdata(i).LocalTemperatures = [local_low_temp local_mid_temp local_max_temp];

fgetl(f1);

Here, I have instructed the program to save the names of each chemical species, \'spec_name\' and stores them in a struct called \'specdata\' which is the same as the output of the function in the very first line. The names are saved in the struct under the heading \'SpeciesName\'. The same is instructed for the local temperature values of each species where an array is created for the 3 temperature values and stored in the struct under the heading \'LocalTemperatures\'.

Second Line

% Line 2 
line2 = fgetl(f1);
A = strfind(line2, \'E\');                                                % Finds index pos. of \'E\' in line2

% High Temp. Coefficients 
a1 = str2double(line2(1 : A(1) + 3));
a2 = str2double(line2(A(1) + 4 : A(2) + 3));
a3 = str2double(line2(A(2) + 4 : A(3) + 3));
a4 = str2double(line2(A(3) + 4 : A(4) + 3));
a5 = str2double(line2(A(4) + 4 : A(5) + 3));
fgetl(f1);

Here, the \'fgetl\' command is used twice and for the second time, it arrives at the second line of information in the text file. This line is assigned to the variable \'line2\'. In this line the coefficients for the species begin. Each cofficient contains the character, \'E\' and if we can locate it, we can extract the coefficients separately. Each coefficient ends with 3 characters after \'E\' which represents the power to which the coefficient is raised to. So, a variable \'A\' is created and it finds the index positions in \'line2\' for whenever the character \'E\' appears by creating an array. As there are 5 coefficients in the second line, there will be 5 index positions in \'A\'.

Using the same logic for the local temperatures, we will use the indexing rules to tell the program when to start and stop extracting the coefficient values from the text file. The first coefficient will begin at index position 1 and will stop at 3 index positions after the first instance of \'E\'. This is because the 3 characters after \'E\' represents the power to which the coefficient is raised to. So these instructions are assigned to the variable \'a1\' for the first coefficient.

For extracting the subsequent coefficients, the same logic is followed with a small difference. E.g. for the second coefficient, it begins at 4 index positions after the previous index position of \'E\' and ends 3 index positions after the next occurrence of \'E\'. This has been instructed to the remaining coefficients in the second line.

Third Line

% Line 3
line3 = fgetl(f1);
B = strfind(line3, \'E\');                                                   % Finds index pos. of \'E\' in line3
a6 = str2double(line3(1 : B(1) + 3));
a7 = str2double(line3(B(1) + 4 : B(2) + 3));

% Low Temp Coefficients 
b1 = str2double(line3(B(2) + 4 : B(3) + 3));
b2 = str2double(line3(B(3) + 4 : B(4) + 3));
b3 = str2double(line3(B(4) + 4 : B(5) + 3));
fgetl(f1);

This section of code is for the extraction of coefficients of each species from third line of data. The \'fgetl\' command is used to arrive at the third line of the species data and is assigned to the variable, \'line3\'. As the number of coefficients in each line is not the same, for each new line a new variable is assigned to find the index positions of the character, \'E\'. In this case it is the variable, \'B\'. The same logic for the previous coefficients is used here. After the \'a7\' coefficient, the low temperature coefficients begin and they have been named \'b1\', \'b2\' etc.

% Line 4
line4 = fgetl(f1);
C = strfind(line4, \'E\');                                                    % Finds index pos. of \'E\' in line4
b4 = str2double(line4(1:C(1) + 3));
b5 = str2double(line4(C(1) + 4 : C(2) + 3));
b6 = str2double(line4(C(2) + 4 : C(3) + 3));
b7 = str2double(line4(C(3) + 4 : C(4) + 3));

fgetl(f1);

% Saving High&Low Coeffs in specdata struct
specdata(i).HighCoeffs = [a1 a2 a3 a4 a5 a6 a7];
specdata(i).LowCoeffs = [b1 b2 b3 b4 b5 b6 b7];


end

This section of code is for the extraction of the coefficients of each species from the fourth line of species data. The \'fgetl\' command is used twice to arrive at the fourth line and is assigned to the variable, \'line4\'. As this is a new line of coefficients, a new variable, \'C\' is assigned to the array of index positions for \'E\'. The remaining low temperature coefficients are extracted.

Finally, the high and low temperature coefficients for each species are stored in the struct, \'specdata\' as \'HighCoeffs\' and \'LowCoeffs\' respectively. When this function is executed, the struct \'specdata\' will appear in the workspace from where it can be opened and see the extracted data.

Specific Heat Calculation (cp_calc)

Function Creation

function specdata = cp_calc(specdata, R)

In this section, a function called \'cp_calc\' is created for the calculation of the specific heats for each species. It will require the inputs of the \'specdata\' struct and the molar gas constant, R which was predefined in the main program script as 8.31. The output of this function will be stored in the \'specdata\' struct.

Retrieval of Required Data

for i = 1:length(specdata)
    
    % Retrieving Local Temp. from specdata struct
    local_low_temp = specdata(i).LocalTemperatures(1);
    local_max_temp = specdata(i).LocalTemperatures(3);
    local_mid_temp = specdata(i).LocalTemperatures(2);
    
    % Retrieving High&Low Coeffs from specdata struct
    a = specdata(i).HighCoeffs;
    b = specdata(i).LowCoeffs;

Then, a for loop is started using the \'i\' counter ranging from 1 to the length of the \'specdata\' struct for the function should be repeated 53 times (once for each species). As the specific heat calculations require temperature values, we need to retrieve the local temperature values for each species for the function to use. This has been done for the next three lines with each temperature assigned to the appropriate variable name. Then, the coefficient values are retrieved from the \'specdata\' struct as they are also needed to calculate the specific heat. The high temperature coefficients are assigned to the variable, a and the low temperature ones to the variable, b.

The for loop is needed as the the function is going to go through each of the 53 species and calculate the specific heat for each using their coefficients and their local temperature information.

Calculation

% Temp. Array between local low and max temp.
    T = linspace(local_low_temp, local_max_temp, 100);
    
    for j = 1:length(T)
        
        % Comparing Temp. in array with local mid temp. 
        if T(j) >= local_mid_temp
            
            Cp(j) = (a(1) + a(2)*T(j) + a(3)*T(j)^2 + a(4)*T(j)^3 + a(5)*T(j)^4)*R;             % High Temp Coeffs used 
            
        else
            
            Cp(j) = (b(1) + b(2)*T(j) + b(3)*T(j)^2 + b(4)*T(j)^3 + b(5)*T(j)^4)*R;             % Low Temp Coeffs used 

        end
    end

% Storing of Cp values in specdata struct
specdata(i).CpVal = Cp;
specdata(i).Temp = T;
    
end

Here, first a temperature array, \'T\' is created using the local temperature values for each species that ranges from the local low temperature to the local maximum temperature with 100 increments. When calculating the specific heat for each species, the function needs to know if the temperature used in the formula is greater than or lesser than the local middle temperature. If the temperature used is greater than the local middle temperature, then the high temperature coefficients will be used for the calculation. If the temperature used is lesser than the local middle temperature, the low temperature coefficients will be used instead.

Since for each species, the calculation has to compare each temperature in the array, \'T\' another for loop is started with the counter, \'j\' and this ranges from 1 to the length of the \'T\' array. So, we are going to obtain 100 specific heat values for each species with each value corresponding to a temperature in the \'T\' array.

So, an \'if\' statement is started to perform the comparison between the temperatures in \'T\' and the local middle temperature for each species. The formula for the specific heat is coded in 2 different ways but are essentially the same. The specific heat formula was previously discussed in the theory section. When the \'T\' temperatures are greater than the local middle temperature, the coefficients, \'a1\' to \'a5\' are used for the calculation as they are for the high temperature condition.

The \'else\' statement is then used for the converse argument wherein the coefficients \'b1\' to \'b5\' are used instead. The molar gas constant, R can be seen at the end of the calculation and it is the reason why it is an input to the function. For both conditions, the specific heat values are stored in the array \'Cp\'. The end statement is given twice to terminate the \'if\' statement and the for loop.

Finally, the specific heat values, \'Cp\' and the temperature values used for the calculations, \'T\' are stored in the struct \'specdata\' under the heading \'CpVal\' and \'T\' respectively. Another \'end\' statement is entered to terminate the function.

Enthalpy Calculation (enthalpy_calc)

Function Creation

function specdata = enthalpy_calc(specdata, R)

In this section of code, a function has been created to determine the enthalpies of each chemical species in the thermodynamic file. The name of the function is \'enthalpy_calc\' and the script name is the same as well. The function takes the input information of the struct, \'specdata\' and the molar gas constant, R. The output of the function is stored in the struct \'specdata\'.

Retrieval of Required Data

for i = 1:length(specdata)
    
    % Retrieving Local Temp. from specdata struct
    local_low_temp = specdata(i).LocalTemperatures(1);
    local_max_temp = specdata(i).LocalTemperatures(3);
    local_mid_temp = specdata(i).LocalTemperatures(2);
    
    % Retrieving High&Low Coeffs from specdata struct
    a = specdata(i).HighCoeffs;
    b = specdata(i).LowCoeffs;

Here, a for loop is started just as was done with the specific heat function. It will range from 1 to the length of the \'specdata\' struct. Then the local temperatures and the coefficients of each species is retrieved from the \'specdata\' struct and are assigned to appropriate variables. This is exactly as was done for the specific heat function.

Calculation

% Temp. Array between local low and max temp.
    T = linspace(local_low_temp, local_max_temp, 100);
    
    for j = 1:length(T)
        
        % Comparing Temp. in array with local mid temp. 
        if T(j) >= local_mid_temp
            
            H(j) =  (((a(1)*T(j)) + ((a(2)*T(j)^2)/2) + ((a(3)*T(j)^3)/4) + ((a(4)*T(j)^4)/4) + ((a(5)*T(j)^5)/5) + a(6) ) * R);       % High Temp. Coeffs used
            
        else
            
            H(j) =  (((b(1)*T(j)) + ((b(2)*T(j)^2)/2) + ((b(3)*T(j)^3)/3) + ((b(4)*T(j)^4)/4) + ((b(5)*T(j)^5)/5) + b(6) ) * R);       % Low Temp. Coeffs used 
            
        end
    end
    
    % Storing of Enthalpies in specdata struct
    specdata(i).EnthalpyVal = H;
    
end

Just as with the specific heat function, the same temperature array is used ranging from the local low temperature to the local maximum temperature with 100 increments. A second for loop is started for the enthalpy calculations that ranges from 1 to the length of the \'T\' array. An \'if\' statement is started to perform the comparison between the temperatures in \'T\' with the local middle temperature. When the \'T\' temperatures are greater than the local middle temperature, the high temperature coefficients \'a1\' to \'a5\' stored in the variable, a are used for the enthalpy calculation.

The \'else\' statement is then used for the converse argument where the \'T\' temperatures are lesser than the local middle temperature in which case the low temperature coefficients \'b1\' to \'b5\' stored in the variable, b are used for the enthalpy calculation. The molar gas constant, R found at the end of the calculation lines and is why it is needed as the second input to the function. The enthalpies are stored in the variable, \'H\' and just as with the specific heats, we will obtain 100 enthalpy values for each species.

Two \'end\' statements are used to terminate the \'if\' statement and the for loop. Then the calculated enthalpy values, \'H\' are stored in the \'specdata\' struct under the heading \'EnthalpyVal\'. Since the same temperatures were used for the specific heat calculations, we do not need to save the temperatures in \'T\' to the \'specdata\' struct again. Another \'end\' statement is used to terminate the function.

Entropy Calculation (entropy_calc)

Function Creation

function specdata = entropy_calc(specdata, R)

In this section, a function has been created to calculate the entropies of the species. This function is called \'entropy_calc\' and the script is named the same as well. The function will take the inputs of the \'specdata\' struct and the molar gas constant, R and will output the data back in to the \'specdata\' struct.

Retrieval of Required Data

for i = 1: length(specdata)
    
    % Retrieving Local Temp. from specdata struct
    local_low_temp = specdata(i).LocalTemperatures(1);
    local_max_temp = specdata(i).LocalTemperatures(3);
    local_mid_temp = specdata(i).LocalTemperatures(2);
    
    % Retrieving High&Low Coeffs from specdata struct
    a = specdata(i).HighCoeffs;
    b = specdata(i).LowCoeffs;

This section is exactly the same as with the specific heat and enthalpy functions. A for loop is started that ranges to the length of the \'specdata\' struct. The local temperatures and the coefficients are retrieved for each species from the \'specdata\' struct.

Calculation

 % Temp. Array between local low and max temp.
    T = linspace(local_low_temp, local_max_temp, 100);
    
    for j = 1:length(T)
        
        % Comparing Temp. in array with local mid temp. 
        if T(j) >= local_mid_temp
            
            S(j) = (( (a(1)*log(T(j))) + (a(2)*T(j)) + ((a(3)*T(j)^2)/2) + ((a(4)*T(j)^3)/3) + ((a(5)*T(j)^4)/4) + a(7) ) * R);        % High Temp. Coeffs used
            
        else
            
            S(j) = (( (b(1)*log(T(j))) + (b(2)*T(j)) + ((b(3)*T(j)^2)/2) + ((b(4)*T(j)^3)/3) + ((b(5)*T(j)^4)/4) + b(7) ) * R);        % Low Temp. Coeffs used 
            
            
        end
    end
    
    % Storing of Entropies in specdata struct
    specdata(i).EntropyVal = S;
    
end

    

This section of code is exactly the same as with the specific heat and enthalpy functions with the only difference being the formula for the entropy calculation. The same temperature array, \'T\' is created using the local temperature range. The same for loop is created and the temperatures in \'T\' are compared with the local middle temperature again using an \'if\' statement. Two versions of the entropy formula are coded with the first using the high temperature coefficients and the other using the low temperature coefficients. The formula that is used for calculation will depend upon the temperature comparison.

The molar gas constant, R is used at the end of the calculation line. The calculated entropies are assigned to the variable, \'S\' and there will be 100 values for each species that corresponds to a temperature in the \'T\' array. The \'if\' statement and for loop is terminated using the \'end\' statement. After, the entropy values are stored in the struct \'specdata\' under the heading \'EntropyVal\'. The function is terminated with an \'end\' statement.

Molecular Weight Function (MW)

In this function, the molecular weight of each species will be calculated. In order to do this, we need to tell MATLAB what are the different elements that the 53 species are composed of and we also need to code for the respective atomic weights of each element so that the program knows how to calculate the molecular weight of a particular species. The program also needs to be able to differentiate between atomic species and molecular species. This is so that the program can find the molecular weight of a species if it consists of more than 1 atom of an element.

Function Creation

function specdata = MW (specdata)

In this first line, the function for calculating the molecular weights has been created. It is named \'MW\' and only requires the data in the struct \'specdata\' as the input. The output of the function will be stored back to \'specdata\'.

Arrays for Calculation & Comparison

% Basic Elements in the file
elems = [\"O\", \"H\", \"C\", \"S\", \"N\", \"A\"];

% Atomic Weights of each element
atom_wt = [16, 1, 12, 32, 14, 40];

The 53 different species consist of only 6 basic elements namely: Oxygen (O), Hydrogen (H), Carbon (C), Sulphur (S), Nitrogen (N) and Argon (A). So in the first line of code in the function, I have created a variable called \'elems\' which stores the strings of the chemical names of these basic elements. The atomic weights of each element are listed below:

O - 16

H - 1

C - 12

S - 32

N - 14

A - 40

So in the next line, an array of the atomic weights of the respective elements is stored and assigned to the variable \'atom_wt\'.

Calculation

for i = 1 : length(specdata)
    spec_name = specdata(i).SpeciesName;                   % Retrieving species names from specdata 
    mol_wt = 0;                                                                  % Counter for the weight    
    
    for j = 1 : length(spec_name)
        for k = 1 : length(elems)
        if strcmpi(spec_name(j), elems(k)) ==1                 % Compares the species name with the base elements 
            
            mol_wt = mol_wt + atom_wt(k);
            
            position = k;
            
        end
        
        end
        
        mol_num = str2double(spec_name(j));                                 % Check for molecular species
            
            if mol_num > 1
                              
                mol_wt = mol_wt + (atom_wt(position).*(mol_num - 1));     % If a molecule, then the atomic weight is added again
                
            end
    end
        
     
       % Storing of Molecular Weights in specdata
       specdata(i).MolecularWeight = mol_wt;
       
       fprintf(\"Molecular Weight of %s is :  %f  \\n\", spec_name, mol_wt);
        
end

In this section of code, a for loop is intiated using an \'i\' counter that ranges from 1 to the length of the \'specdata\' struct. This is because we need to find the molecular weight for each species in the thermodynamic file. Then, the species name \'spec_name\' is retrieved from the \'specdata\' struct because we need to compare the species name with the string of basic elements found in the \'elems\' array. The initial molecular weight, \'mol_wt\' is set to 0.

So, 2 more for loops are initiated. The first for loop uses the \'j\' counter and ranges from 1 to the length of the species name. The second for loop uses a \'k\' counter and ranges from 1 to the length of \'elems\'. This means that for each species, we need to compare the species name with the basic elements.

To compare the species name with the elements in \'elems\', we need to use an \'if\' statement and the \'strcmpi\' command. The \'strcmpi\' command is used for comparing 2 strings of characters with each other irrespective of the case. This means that is 2 strings are compared and they are exactly the same even though the cases of the characters are not the same, MATLAB will return 1 i.e. true. If the \'strcmp\' command is used instead, then the comparison will be case sensitive. So we want to compare the species name, \'spec_name\' with the elements in \'elems\' and if they are matching i.e. the same, then it should return 1 which basically means the output is true as opposed to false. If the 2 strings are matched, then the loop can proceed with calculating the molecular weight.

The first part of the molecular weight formula is then written and this only concerns the species that are monoatomic i.e. only have 1 atom e.g Oxygen, Hydrogen. In this case, the molecular weight of the species is equal to the atomic weight of the elements found in \'elems\'. A new variable called \'position\' is then created and assigned to the value \'k\' which corresponds to the \'k\' counter used in the for loop. This is needed for the second part of the molecular weight formula.

The second part of the molecular weight formula concerns the species that have more than 1 atom of an element and this may be for a single element or for a compound e.g. O2, H2O2. To be able to calculate the molecular weight for these species, we need to find the number of molecules of each element in a species. This is done by converting the species name from a string to an integer using the \'str2double\' command so that whatever number is in the species name, we can use it as the molecular number. This value is assigned to the variable, \'mol_num\'.

Then, an \'if\' statement is created for the second molecular weight formula. If the number of molecules, \'mol_num\' is greater than 1, the second molecular weight formula will be used to calculate the molecular weight. In this formula, the molecular weight is equal to the sum of the initial molecular weight, 0 and the product of the atomic weight of the element at position, k and the molecular weight minus 1. The elemental operator (.) is used after \'atom_wt(k)\' because the atomic weights of each species is stored in an array and we need to use the correct operator at the correct position to perform calculations with arrays.

The molecular weights calculated (\'mol_wt\') are then stored in the struct \'specdata\' under the heading \'MolecularWeight\'. An end statement is then used to terminate the function.

Finally, to display the molecular weights of each species in the command window, the \'fprintf\' command is used along with the required format specifiers to retrieve the string and numeric float data from the \'specdata\' struct and display it in the command window.

Graphs Function (graphs)

Now that we have performed all the calculations and determined all the numerical information, we need to plot graphs from this data. Specifically, we need separate plots of the Temperature against the specific heat, the enthalpy and the entropy of each species. The temperature used in these plots are the same values used in the calculations for the specific heat, enthalpy and entropy. After these graphs are plotted, we need to save these plots in a different folder from the current directory and each species needs to have its own folder containing its 3 plots.

Function Creation

function P =  graphs(specdata)

Retrieval of Required Data

for i = 1:length(specdata)
    
    % Retrieval of species names for graph titles & folder names
    spec_name = specdata(i).SpeciesName;
    
    % Creating new folder for graphs
    mkdir(\'Results\', spec_name);

In the first line the function was created for the plotting of the graphs whereby the function name was \'graphs\' and the script name was kept the same. The only input for the function is the struct \'specdata\' since it contains the information for the specific heat, enthalpy, entropy and also their respective temperatures. Next, a for loop is used that ranges from 1 to the length of the \'specdata\' struct and within it, we need to retrive the names of the species. This is because this information will be useful for the plotting of the graphs as we can give each one a title that contains the species name for which the data has been plotted. This is mainly for presentation and for a user to know more easily for which species the data has been plotted. Then, a new folder is created using the \'mkdir\' command called \'Results\'. This folder is the parent folder and will be created within the current directory. Inside the parent folder, each species will have its own folder containing its respective graphs.

Plotting

% Plot b/n Temp. & Cp
     figure(1)
     plot(specdata(i).Temp, specdata(i).CpVal);
     xlabel(\'Temperature, K\')
     ylabel(\'Specific Heat, KJ/KgK\')
     grid on
     title(sprintf(\'Temperature Vs. Specific Heat of %s\', spec_name))
     
     
     % Plot b/n Temp. & Enthalpy
     figure(2)
     plot(specdata(i).Temp, specdata(i).EnthalpyVal);
     xlabel(\'Temperature, K\')
     ylabel(\'Enthalpy, KJ/Kg\')
     grid on
     title(sprintf(\'Temperature Vs. Enthalpy of %s\', spec_name))
     
     
     % Plot b/n Temp. & Entropy
     figure(3)
     plot(specdata(i).Temp, specdata(i).EntropyVal);
     xlabel(\'Temperature, K\')
     ylabel(\'Entropy, KJ/K\')
     grid on
     title(sprintf(\'Temperature Vs. Entropy of %s\', spec_name))

Next, the code for the plotting of the graphs is written using the \'plot\' command. The first plot is for the temperature vs. the specific heat. So, we need to extract this data from the struct \'specdata\'. The code \'specdata(i).Temp\' and \'specdata(i).CpVal\' will retrieve the temperatures and specific heat values respectively from the \'specdata\' struct and use them as the x and y axis data respectively.

The axes are then labelled with the names of the variables and their units and the \'grid on\' command is used to turn on the plot grid for easier reading of the plots. Then a title is given using the \'sprintf\' command. This command is needed since we are printing the names of the species in the titles of each graph and the nature of that data is a string. In addition, the format specifier \'%s\' is used to specifiy that the nature of the species name is a string and that it can get the species name from the \'spec_name\' variable that was used in the previous section of code above. The for loop will ensure that the temperature and specific heat values and species name are obtained for the species at which the \'i\' counter lands at.

The same is peformed for the other 2 plots, oinly changing the y axis data to the respective enthalpy and entropy of the species retrieving the data from the \'specdata\' struct and using the same format specifier to label the species name in the titles of each graph.

Saving of Graphs

% Directory of folder where graphs will be saved
     path = (\'C:\\Users\\Arjun\\Documents\\MATLAB\\Results\\\');
     
     % Specifying the name of each figure and its path
     p1 = fullfile(path, spec_name, \'Cp.jpg\');
     p2 = fullfile(path, spec_name, \'H.jpg\');
     p3 = fullfile(path, spec_name, \'S.jpg\');
     
     % Saving of figures in specified path
     saveas(figure(1), p1); 
     saveas(figure(2), p2);
     saveas(figure(3), p3);
     
end

end

This section of code is concerned with saving each plot of each figure and making sure it has the correct file name and file path to be saved in to. First, the directory to which the graphs will be saved is specified in the first line using the \'path\' variable. The path name needs to have quotation marks and must be in parentheses. Then, the \'fullfile\' command is used to create the figures of each plot in different components. These components are the path, the species name for which the plot corresponds to and the file name. The path is previously specified and the species name \'spec_name\' can be retrieved from \'specdata\' struct. The file name for each plot is simply named \'Cp.jpg\' for the specific heat, \'H.jpg\' for the enthalpy and \'S.jpg\' for the entropy. Each plot is given the extension (.jpg) so that it is saved in the jpeg format.

Finally, the \'saveas\' command is used to save the figures with the specified file names in the specified paths. In the \'saveas\' command, the first field in the parentheses if the figure handle to which the \'saveas\' command corresponds to. The second field is for the variable name used for specifying the file path and file name of each figure for each species.

The for loop and the function are then terminated using the \'end\' statement twice.

Output

The screenshot below shows the struct \'specdata\' containing the names of the species, their local temperatures, high and low temperature coefficients, specific heats, enthalpies, entropies and their molecular weights.

The screenshot below shows the molecular weights being displayed in the command window.

The screenshot below shows the folder \'Results\' in which subfolders are created for each species being named after the species name. Each folder contains its respective 3 graphs of Temperature against the specific heat, enthalpy and entropy.

The screenshot below shows the Oxygen subfolder opened and the plots it contains.

  • Plots for O2

  • Plots for N2

  • Plots for CO2

Errors

  • Error 1

This error came about because in the \'graphs\' function, I had not specified the x axis data i.e. the temperature before the plotting section of the code. We need to retrieve all the information we require from the \'specdata\' struct before being able to do anything with it. In this case, I had to retrieve the temperatures from the struct first before using it in the plot command. I thought that I could use the \'T\' array from the \'cp_calc\' function script but then I realized that those values were saved in the struct under the heading \'Temp\'. This results in an error in the function script and in the main program script.

So instead of entering \'T\', I had to enter \'specdata(i).Temp\' since this will retrieve the temperatures of each species that were used for the calculations of specific heat, enthalpy and entropy. This resolved the issue.

  • Error 2

This second error occurred due to the use of the \'cd\' command. I wanted to use the \'cd\' command in the \'graphs\' function script to change the directory to the species name subfolder within the parent folder, \'Results\'. However, this resuled in the warning since that directory did not exist and there was no folder and no folders were created. Although the graphs appeared on the screen as the function was executed, they were not saved in the directory I specified either.

Instead, I used the path variable to specify the destination of the file that I wanted to save the plots to. Then, I used the \'fullfile\' command to incorporate all the different components of the file e.g. the file name, the species name and the path for each of the 3 plots for each species. This resolved the issue and managed to save all the graphs in to their respective folders.

Conclusion

In conclusion, the NASA thermodynamic text file was parsed using MATLAB and the required information of: the species names, their local temperature ranges, their high and low temperature coefficients, their specific heat values, their enthalpy values, their entropy values. In addition, the molecular weight for each species was calculated and graphs for the specific heat, enthalpy and entropy were plotted against their respective temperature values. These plots were saved in a parent folder with each species having its own subfolder containing its respective plots. Also, the errors faced during the programming were also mentioned.

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.