TKP4120 Process engineering. TKP4140 Process control. TKP4160 Transport
phenomena. TMT4140 Applied thermodynamics. Since I lack a first hand ...
The IKP Matlab Companion
Matlab exercises in TKP4105, TKP4110, TKP4120, TKP4140, TKP4160 and TMT4140 Tore Haug-Warberg D C E, NTNU E-mail address:
[email protected] URL: http://www.nt.ntnu/˜haugwarb
The Author wants to thank Ph.D. student Bjørn Tore Løvfall for his help with HYSYS and the diffusion problem, and Ph.D. student Antonio Carlos Brandao Araujo for his help with the control theory example and ODE description. They have also been very helpful with the Matlab documentation in general. He also wants to thank prof. Hallvard Svendsen for his kind interest in this little project.
Contents List of Tables
v
Preface
vii
Chapter 1. Getting started
1
Chapter 2. Basic concepts 1. Homogeneous containers (vectors and matrices) 2. Heterogeneous containers (lists) 3. User-defined data types (structs) 4. Input/output issues 5. Tricks of the trade
3 3 6 7 8 8
Chapter 3. How to solve equations 1. Linear equations 2. Independent reactions 3. Linear parameter estimation 4. Polynomials 5. Single non-linear equations 6. Sets of many non-linear equations
9 9 12 12 14 15 16
Chapter 4. Write your own functions 1. The function concept 2. Vector functions 3. Iterative functions (algorithms) 4. Recursion — good, evil or maybe bad?
19 19 19 20 20
Chapter 5. Functionals or function(function)s 1. Integration 2. Ordinary differential equations 3. Unconstrained optimization 4. Optimization with constraints 5. Process control
23 23 23 25 25 26
Chapter 6. String parsing 1. Chemical formula arithmetics 2. Cool stuff (regular expressions)
29 29 30
Appendix A.
Language elements
33
Appendix B.
Examples
37
Appendix C. Matlab code 1. randolph 2. octane 3. figure 2 8
39 39 41 42 iii
iv
CONTENTS
4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33.
partialinv fertilizer balance acid base reaction matrix water viscosity 1bar fit water vapor pressure fit water density 1bar fit acid base titration curve colebrook pressure drop at fixed flow friction and reynold flow at fixed pressure drop laminar colebrook vs laminar chon water viscosity 1bar water vapor pressure water density 1bar rachford rice diffusion pitot tube pitot integrand mingibb CSTR process control CSTR time derivatives ODE Jacobian mw from formula parser mw binop make formula matrix get formula vector greenhouse gases from HYSYS
43 43 45 46 47 49 50 51 51 52 52 53 53 54 54 54 54 55 55 57 58 58 59 61 62 63 63 64 66 67
Appendix D. Ruby code 1. greenhouse gases from HYSYS
69 69
Appendix E. Data files 1. pages from water vapor pressure data 2. pages from water density 1bar data 3. water viscosity 1bar data 4. pages from HYSYS report
71 71 72 73 73
List of Tables 1.1
Programming abstractions
1
3.1
Nitro-phosphate fertilizer plant
11
4.1
Recursive calculation of Fibonacci-numbers
22
6.1 6.2
Operator table The most common regular expressions
29 31
A.1 A.2 A.3 A.4 A.5 A.6 A.7 A.8 A.9 A.10 A.11 A.12 A.13 A.14 A.15
File functions Special variables Special characters Basic commands Program flow instructions Instantiation operators Plotting commands Relational operators Algebraic operators Set functions Transcendental functions String functions Linear algebra functions Advanced linear algebra functions Functionals
33 33 33 33 34 34 34 34 35 35 35 35 36 36 36
v
Preface My arguments for enrolling at the Chemistry Faculty in the late 1970s were subtle: I disliked mathematics and hated philosophy, but loved to experiment with (explosive) chemicals. It was therefore quite natural for me to study in Trondheim — just modest mathematics and no Exam Philosophicum. So, here I am, writing a philosophically inclined preface to a companion in mathematical programming! My naive view lasted for only one year, however, or more precisely till my first course in physical chemistry and thermodynamics. I then realized that the subject which had fascinated me as a young boy could be represented by thermodynamic state functions, and after a freshman course in FORTRAN programming I have since spent my professional life in the borderland between chemistry, mathematics and computer science. In retrospect this has not been such a bad fate because the field has expanded tremendously, which means I have had plenty of interesting things to do. So what is studying, and why should we worry about programming? Basically, I think we have three qualities which make us stand out from other mammals, including our cousins — the big apes: Mental abstraction Verbal communication Artistic inclination To me it is important to master all three skill factors, at least to some degree. I therefore enjoy to enjoy∗ mathematics (abstract thinking), computer programming (mind extension) and carpentry (artistic pleasure). However, communication is maybe the most important skill factor these days. But, talking about communication there are at least four levels we need to worry about†: Talking (99) Reading (80) Writing (25) Programming (1) The numbers indicate the percentage of the population that I expect master the subject to such a degree that it help them in communicating with other people. I have no scientific background for my statements, and, before someone accuses me for having fascistic motives, I want to say that it is not my intention (nor is it my profession) to categorize people according to their skills — I simply want you to realize that learning about programming is likely to be a “painful” process in the beginning. However, the fraction of students who enroll to the technical studies at NTNU makes up about two percent of the juvenile vintage in Norway and provided it is true that our university recruits among ∗
It is meant to be a recursive statement — think about it twice. These subjects form, together with mathematics, the five basic skills that all children shall master according to the 200X-reform of the Norwegian primary school system. †
vii
viii
PREFACE
the “science buffs”, it is likely that much more than one percent of you already have some acquaintance with computers and computer programming. My hope is therefore that many of you shall come to appreciate computer programming as a main productivity tool. Second, it is also my hope that some of you will join my research group working on computerized thermodynamics! Before we get started I should mention that this little Matlab companion is intended to follow the students at IKP over 2–3 years in several different subjects of engineering disciplines: TKP4105 Separation technology TKP4110 Chemical reaction engineering TKP4120 Process engineering TKP4140 Process control TKP4160 Transport phenomena TMT4140 Applied thermodynamics Since I lack a first hand experience with each of the course syllabuses it is difficult for me to give a chronological overview of the exercises. A thematic presentation is then more natural, especially when keeping maintainability in mind. Even though this is a course in mathematical programming it will not give you any formal training, neither in mathematics nor in programming. The focus is rather on practical problem solving. Now, since most of the code is vectorized it means that linear algebra is a prerequistite for reading the companion. Having said this, I still want to show that math is done simpler, safer and faster in a mathematical programming language like Matlab, as compared to hand calculations, spread-sheet programming, or no calculations at all∗. The exercises are taken from many different subjects, but I have put quite a lot of effort in keeping the programming style both as general and as uniform as possible (which is the main reason this is a one-man show — it is hard to synchronize two programmers). Throughout the course we shall make use of Matlab, but please understand me right when I say that this is not a Matlab course. Matlab is excellent for prototyping issues, it is abundant, and it has a gentle learning curve, but it is unfortunately a rather inconsistent language. Without some critical sense you may therefore develop bad programming habits, although less so than in e.g. Excel. This is not to say I want a crusade against Matlab or Excel (well, perhaps), what I really want to tell is that the world is big and that there are hundreds of programming languages out there — all having their strong and weak points. The moral is: Pick the language that is best suited for your job! Take e.g. PostScript. Few people realize that this is anything but a relict from Adobe which makes artistic print-outs and fancy fonts available to the end user. However, PostScript is a programming language in its own right and you can write a complete simulation code in this language if you really want to†. I have therefore avoided Matlab-specific programming the best I can, just to make sure you will be able to migrate to other (script) languages like Python or Ruby without too much difficulty.
∗
Plain belief or guts feeling are student favorites which seldom turn out to yield better results than to-the-point calculations. † Wouldn’t it be an intellectual challenge to let the printer do the number-crunching while the computer could concentrate on other things (the question is only what job that should be).
CHAPTER 1
Getting started First of all I should let you know that the Matlab code which is included in Appendix C can also be found on my home page http://www.nt.ntnu/˜haugwarb/matlabcourse. This might save you same typing errors. Before learning about programming (or any other scientific subject) you should definitely ask yourself what the subject is about. In computer terminology program means one out of three things: A systematic plan for the automatic solution of a problem by a computer, or the precise sequence of instructions enabling a computer to solve a problem, or to prepare a program code (ref: Webster’s Encyclopedic Unabridged Dictionary). All three meanings are adequate for the current purpose. Most programming languages are built around the idea that you shall be able to declare variables, write expressions of some kind, make assignments to the variables, and transfer execution control to external procedures∗. External in this context means the procedure has its own namespace where the variables are given a local meaning. In other words; to bring information from the outside world into the procedure it has to be copied, and vice versa; everything you want to be visible outside has to be copied back. Some languages got more abstraction mechanisms, some got less, but these four are the ones needed in Matlab (see Table 1.1). T 1.1: Programming abstractions. With this I mean the different building blocks a language consists of.
Declaration function[lnp]=antoine(T,c) T and c hold copies of the arguments used in the call to antoine Expression c(1)+c(2)/(T+c(3)) The expression is evaluated but not assigned Assignment lnp=c(1)+c(2)/(T+c(3)) Variable lnp now holds a copy of the evaluated expression Procedure antoine(x,y) x and y are copied into antoine, the calculated result is copied back Matlab belongs to a family of languages called script languages (Python, Ruby, Perl, etc.). This is contrary to languages which has to be compiled before you get an executable code† (Pascal, C++, FORTRAN, etc.). The big challenge in this respect is programming ∗
In Matlab, the function abstraction is mixed up with the declaration keyword function which is used to define functions. For this reason I write procedure when I am referring to the abstraction, and function when I refer to the declaration, see Table 1.1. † Nowadays often called an application. On the Windows platform this is a file having the file extension .exe 1
2
1. GETTING STARTED
speed versus calculation efficiency and code syntax versus semantics∗. Script languages are very suitable for rapid prototyping and testing, while a compiled code is more secure in the sense that you can ask for full control over its execution. In Appendix A you will find a small subset of commands, operators, etc. taken from the standard Matlab implementation. The list is complete in the respect that nothing more will be needed in this course. In Appendix B I have given a few examples on how the Matlab-code looks.
∗
Whereas correct syntax only tells us that the program can be executed, a correct semantics tells us that the program does exactly what it is intended to do — now that is a real challenge!
CHAPTER 2
Basic concepts The expression syntax∗ in Matlab is not very different from what you have been taught in mathematics, e.g. a=2; b=3; c=(a-b)ˆ2; c==1;. The central issue here is the statement. A statement is interpreted from the left and proceeds all the way to the first semicolon or the end-of-line (there are four statements in the previous example). If the statement contains an equal sign it is said to be an assignment (there are three assignments in the previous example). At this point things start to diverge from what you have seen before. To illustrate possible pit-falls let us rewrite the Matlab code into mathematical terms: a =2 b =3 def
c = (a − b)2 ?
c =1 First, I assign the values 2 and 3 to the variables a and b, then I define c to be the complete square in a and b, and in the fourth line I ask myself whether c is equal to 1 or not. In daily speech most people just continue to use the = operator and say “equal to” in all four cases. Now, this is something a computer cannot understand without some help! E.g. in Matlab, the first two lines are OK, but the third line gives trouble. Matlab does not know about symbolic algebra (contrary to e.g. Maple, but that is another story). The closest we come to a definition in Matlab is the function concept explained in Section 4.1. Therefore, issuing the statement c=(a-b)ˆ2; in line three, Matlab will simply evaluate the square using the current values of a and b. If a and b are not yet assigned you will get the error message ??? Undefined function or variable ’a’. The fourth line represents a boolean test (booleans are numbers that can take the values true or false†). In Matlab there are no booleans so this feature has to be sneaked in using ordinary numbers combined with the convention that 1 is true, and 0 is false. To test the equality we have to write c==1; which in this particular case will return 1 (true). Hence, we can also write something like d=c==1; where the outcome from the test expression is assigned to the variable d. The moral is: Beware of the difference between definitions, assignments and boolean tests! You must also understand that Matlab executes one line at a time. Hence you must make sure that all statements (lines) comes in the correct order. 1. Homogeneous containers (vectors and matrices) The basic data type in Matlab is a matrix-like‡ container of numbers. The numbers that Matlab operate on are so-called doubles. One double occupies 8 byte of information. Rules for writing correct expressions, i.e. 2 + 3 ∗ 2 will be evaluated as 2 + (3 ∗ 2) and not (2 + 3) ∗ 2. Don’t be too puzzled, this is not very different from an electric charge having the values plus or minus. ‡ What exactly is a matrix? There are at least four meanings of the term: A point in vector space, a linear operator, a row or column basis for a vector space, or just a data “container”. The last interpretation fits the use of matrices in Matlab best. ∗
†
3
4
2. BASIC CONCEPTS
There are 8 bit in one byte which means there are 63 bit available for storing numbers (the last bit is the so-called sign-bit). In practise this means you can represent all integer values in the range −253 , 253 exactly. Outside this region the number field gets more and more scattered until you reach the limit ±21024 . Beyond this Matlab will use the notation inf to signify that you are outside the number representation (over-flow). Creeping towards −1075 −1075 −1075 you will zero you can represent numbers down to ±2 . Inside the range 2 ,2 always get the result 0, i.e. there is no under-flow in Matlab. Let us go back to the container issue. In mathematical texts you will meet several notations for vectors and matrices. The notation I tend to favor is this one: 1 2 A= 3 4 a= 5 6 a = 3.141592 . . . N = 13, where capital boldface denotes a matrix, lower boldface denotes a vector, and normal font (either capital or lower case) is a scalar. In Matlab there are no bold fonts which means vectors and scalars will look the same: snippet from matlab matrix.m starts here A a a N
= = = =
[1,2;3,4]; [5,6]; 3.141592; 13; matlab matrix.m ends here
Of importance for us is to realize that Matlab does not distinguish between matrices, vectors and scalars. To Matlab everything is a matrix which means that executing the size() command on A, a and N will tell they are all two-dimensional objects (do this). We could therefore forget about most of what we have learned in mathematics and start doing things entirely the Matlab-way. This is not encouraged, however, and I shall do my best to present code that is “mathematically correct” in this course. Assume we want to calculate and plot the ideal gas pressure as a function of volume for a given temperature. Mathematically, the operations can be written∗ R = 8.31453 J mol-1 K-1 T = 273.15 K N = 7 mol v = 0.1 m3, 0.3 m3, . . . , 1.5 m3 e = (1, 1, . . . , 1)T t = Te p = NR diag (v)−1 t Note the use of matrix/vector notation in the example. It certainly makes the code compact, but you must know how to handle array and matrix products! Translated to Matlab the same operations look like this: snippet from ideal gas isotherm.m starts here ∗
Since there are no standard mathematical notation available for plotting vectors I cannot show this operation.
1. HOMOGENEOUS CONTAINERS (VECTORS AND MATRICES)
5
clear; R T N v e t p
= = = = = = =
8.31453; 273.15; 7; [0.1:0.1:1.5]; ones(size(v))’; T*e; N*R*inv(diag(v))*t;
plot(v,p); xlabel(’Volume [mˆ3]’); ylabel(’Pressure [Pa]’); title([’p(V)-plot at ’,num2str(T),’ K’]); ideal gas isotherm.m ends here
There are a couple of things we should note here. First of all Matlab has a vector constructor [from:step:to] which is very handy. Second, the matrix constructor ones(size(v)) do two things at one time. Besides filling the vector e with 1’s, it also ensures that e inherits the dimensions of v (or shape if you like). Now, this is a good programming practise! The opposite is also valid: Never, never, . . ., never enter the same definition twice in the code, and never let two dependent matrices (or two vectors) have independent size definitions! Finally, I should mention that in practise I would consider to change the last line in the calculation to p=N*R*(t./v). This is both a matter of CPU-time and readability, although I shall not claim that the compact code is a better alternative under all circumstances. § 1 Repeat the calculations in the last example for the isotherms T=[250:20:350]. Use v=logspace(0.1,10,100)’ to construct the pV-diagram. Make your best at calculating everything as matrix products (no for-loops, index variables, etc.), and make sure your results can be plotted using the command semilogx(v,P) where P is a dim (v) × dim (T )-matrix. For your own understanding of the physical behavior you should also try the command loglog(v,P). I . Nothing really new here, but to become fluent in array programming you must exercise a lot. I want therefore to stress the importance of the compact notation used in ideal gas isotherms. So, do not fake you have grasped the idea but make sure you understand! snippet from ideal gas isotherms.m starts here clear; R t N v e p
= = = = = =
8.31453; [250:20:350]; 7; logspace(-1,1,100)’; ones(size(v)); N*R*(e./v)*t;
semilogx(v,p); xlabel(’Volume mˆ3’); ylabel(’Pressure Pa’);
6
2. BASIC CONCEPTS
title(’p(V)-plot at several isotherms’); legend(num2str(t’)); ideal gas isotherms.m ends here
Everything is a matrix in Matlab, and depending on your attitude to linear algebra this may be a relief or a nuisance. However, take advantage of this feature and try to eliminate for-loops, if-tests, and other spaghetti-ingredients. My own experience is that Matlabprogramming may result in only 10% of the code compared to compiled languages like FORTRAN and C++. 2. Heterogeneous containers (lists) I first decided not to talk about lists, but after joggling back and forth with the code I wrote for this course I finally decided to trouble you with one extra abstraction level. Appearantly, we could have done without lists, but they make things easier, especially in program interfaces. The problem is that Matlab has a dirty implementation of the list concept called a cell array which makes it difficult to remember the syntax from one day to the other. The big difference between a list and a vector is that vectors hold numbers while lists can hold strings, lists, matrices, structs, etc. In Matlab there are a number of functions that let you manipulate the transition from a list to a vector and back: char
abs
char
cellstr
list → character matrix → matrix → character matrix → list Here, a character matrix is like any other matrix execpt that it contains numbers in the range 0–255. If you display this matrix on screen you will see letters and not numbers. However, you can still make use of the matrix as a numerical object, but once you manipulate its content Matlab forget about ASCII-decoding and display plain numbers (unless you explicitly tell something different). A short tour de lists follows: snippet from matlab list.m starts here clear; format compact; mylist = {’some’,’words’,’in’,’the’,’list’}; disp(’List syntax: mylist = {’’some’’,’’words’’,’’in’’,’’the’’,’’list’’}’); disp(’This is how ’’mylist’’ looks:’); pause; disp(mylist); disp(’Run size(mylist) to see the matrix-like size of the list:’); pause; disp([’size(mylist) = ’,num2str(size(mylist))]); disp(’Run char(mylist) to convert to a character matrix:’); pause; disp(char(mylist)); disp(’The new size is:’); pause; disp([’size(char(mylist)) = ’,num2str(size(char(mylist)))]); disp(’Convert to ASCII-numbers using A = abs(char(mylist))’); pause;
3. USER-DEFINED DATA TYPES (STRUCTS)
7
A = abs(char(mylist)); disp(A); disp(’Replace spaces (32) by periods (46)’) pause; i = find(A==32); A(i) = A(i) + 14; disp(A); disp(’Convert back to a character matrix using char(A):’) pause; disp(char(A)); disp(’Convert into a new list using cellstr(char(A)):’); pause; disp(cellstr(char(A)));
matlab list.m ends here
3. User-defined data types (structs) A struct is an extensible data type that Matlab has inherited from C. It is now accepted as a standard data storage facility in most programming languages, not only C and Matlab. Compared to matrices, which are like dense tables, the struct is an open tree-like container. The branches of the tree are given names by the programmer, and at the very end of each branch sits a leaf which keeps a data object. An important feature of the struct is its extensible and heterogenous nature which makes it ideally suited for object oriented programming. This means the struct can hold several different data types at one time; matrices, other structs, strings, etc. One example follows: snippet from matlab struct.m starts here book.author.name.given = ’Tore’; book.author.name.family = ’Haug-Warberg’; book.author.age = ’(now-datenum(’’13-Nov-1958’’))/365’; book.title = ’The IKP Matlab companion’; book.title.subtitle = ’Exercises in TMT4140 etc.’; book.ISBN = 0; matlab struct.m ends here
To figure out my age (uh-oh!) you can issue the command eval(book.author.age). This operation is known as string parsing, see chapter 6 for an introduction to this fascinating subject. Structs can obviously be used to capture data in a systematic way, much like a book with chapters, sections, paragraphs, etc. One specific use is to make programs less sensitive to software upgrades. Imagine you have been asked to program the van der Waal equation function[p]=vdw(v,t,n,tc,pc). Months later, when you have forgotten what you did the first time, you are asked to make the model more general, say function[p]=vdw(v, t,n,tc,pc,K), where K is an interaction parameter matrix. If the model was implemented as function[p]=vdw(v,t,n,par) in the first place, this update had been trivial since you would not need to do any changes to the program interface, just include one new field par.K in the input and change the model accordingly.
8
2. BASIC CONCEPTS
4. Input/output issues To save the current work space simply issue the command save. To load it back use load. All variables in the workspace will then be written to/from a standard (binary) file named matlab.mat. This is OK for day-to-day use, but you should know about one possible pit-fall — you need Matlab installed to view the information in matlab.mat! To have easier access to your data you must save the information in a text file rather than a binary file. Fortunately this is also very easy, just issue the command save yourFileName -ascii to save data with 8 digits, or save yourFileName -ascii -double to save data with 16 digits. You can also write formatted data to a file using the fprintf command, see the files . . .fit.m for examples on how to generate a program from the inside of another program (this is a quite powerful technique). Plotting data in Matlab is a snap once you have become familiar with vectors and matrices. In its simplest version you enter the command plot(x,y), where x and y are two vectors of the same shape. There are numerous ways to produce labels, multiple plots, 3-dimensional plots, etc. Take a look at the files . . .fit.m if you want to see some examples. 5. Tricks of the trade • Always start your script with the clear command to be sure you get a fresh start (avoid overlapping workspaces). • Function variables should always be entered explicitly as in z = f(x,y). • Function parameters should be wrapped into a struct and given at the end of the argument list as in z = f(x,y,s). • Use long variable names e.g. Hungarian notation longNamesLikeThis at the top level of a program, and successively shorter names deeper down in the program hierarchy (i, j, x, y, etc. at the lowest level). Do not use underscore in variable names. • Use underscore in long function (file) names (long function name like this). Do not use Hungarian notation for files names (Windows does not support case sensitive naming). • Segment the code into readable blocks. Consider using whole-line comments in front of each block to explain the gross action of the code. • Use right margin comments to explain complex expressions. • Align the assignment operators in each block (the = operator often plays a particularly important role in mathematical programs).
CHAPTER 3
How to solve equations 1. Linear equations Solving linear equations is all what engineering is about, at least this is not far from the truth, and the importance of this chapter is so immense that you can hardly take it too seriously. Matlab makes the solution of big equation systems a snap, but beware of the dangers if you do not know exactly how the solver works. In the worst case you may get fatally wrong results. This statement is quite harsh, so let us start out with one simple example: § 2 You are asked to make 98 octane gasoline containing 1% aromatics. You have three petroleum fractions at your disposal: Fraction one holds 90 octane with 0.2% aromatics, fraction two holds 105 octane with 2% aromatics, and fraction three holds 95 octane with 0.5% aromatics. The octane number is a mass linear function of each petroleum fraction. Set up an equation system Ax=b that can be solved using Matlab. Invert the equation system by hand (row elimination), and compare with the Matlab solution x=inv(A)*b. 98 . We are given two pieces of information (octane number and aromatic content) which expresses two equations in three unknowns. The total amounts of each fraction (in tons, kilograms or whatever) has no importance, which means we can do the calculations on a normalized basis. This gives us the third piece of information needed to invert the equations: 90 105 95 a 98 0.2 2 0.5 b = 0.96 1 1 1 c 1 The Matlab-script listed in Appendix C.2 takes you through the elimination process, step by step. Notice that “hand-elimination” yields more accurate results than Matlab inversion (this is not a general result though). The difference is barely visible in this case, but in some practical problems like e.g. chemical process simulation there maybe thousands of variables, and the differences between two numerical solutions can be like day and night. Therefore, always check your result by back-calculating the right hand side! So far so good, but things are quite different when working on a computer compared to doing hand calculations. In Section 2.1 I told you that the computer has only a limited range of numbers available. From time to time you will therefore experience that Matlab complains about singular matrices or bad condition numbers. Without any understanding of the possible causes of these messages you are totally lost and may easily produce garbage results. The next exercise gives you a clue of what appears to be a common pitfall. § 3 Change the aromatic analysis in the last example to 1 − 10−15 , 1, and 1% for the three gasoline fractions. What happens to the solution now? 9
10
3. HOW TO SOLVE EQUATIONS
M 98 . The Matlab script is unchanged from the last exercise (your prompt answer decides what to do). The first thing you should notice is the negative (nonphysical) element in the solution vector [−0.1583, 0.2208, 0.9375]. Next you should not take too easy on Matlab’s warning message: “Matrix is close to singular or badly scaled—Results may be inaccurate”. Finally, you should recognize that the backcalculated Matlab solution [51.25, 0.5, 0.5] is pure nonsense. By now we have solved one nice and clean equation system, and we have modified it into something ill-conditioned. Next, let us take the full step and look at a truely singular problem. This may look terrifying, but the important message is: Don’t panic∗! You are told to solve the equations and should focus on your task without too much hesitation. § 4 Solve the component balances of this flowsheet as a simultaneous set of equations Ax = b, where x = (n˙ 1 , n˙ 2 , n˙ 3 , n˙ 4 , n˙ 5 ) and n˙ i [mol s-1 ] are the molar flow rates of the streams i ∈ {1, 2, . . . , 5}. Write the solution as x = x p + Nxh where x p is a particular solution and xh is the (homogeneous) solution Axh = 0. Plot the equilibrium quotient Q = x2B /xA in stream 3 as a function of the recirculation rate. Determine the smallest recirculation flow that is theoretical possible considering that the equilibrium constant is K = 0.74. F 2.8 S’ . You are given a flowsheet with 10 unknowns and 10 equations, but the coefficient matrix is singular! Instead of one unique answer you have infinitly many possible answers, which in practise must be settled by knowing some extra information. In this case it is the conversion constraint Q = x2B /xA ≤ K = 0.74 for the reaction A → 2B. This is a non-linear constraint which we shall not devote time on right now, but we can easily plot Q as function of the recirculation rate and determine an approximate region for possible plant operation (Appendix C.3). In all the examples we have met so far there have one way of expressing the equations — the free variables have been unknown and the specifications have been fixed. Sometimes, however, you will need to solve an partially inverted specification problem, i.e. an equation system Ax = b where some of the x’s are known and a similar number of the b’s are unknown. I have coined the term “partially inverted problem” for this behavior, because in the ultimate case all the x’s are known and you do not need to solve any equations at all (the inverted problem is formulated explicitly). § 5 Write a function [x,b]=partialinv(A,x,b) which solves a partially inverted equation system. Let x(i) = b(j) = NaN denote the free variables x(i), and the specifications b(j), that are considered unknown (on input). Update the vectors x and b such that Ax=b on output. P . You may wonder why it is necessary to spend time on writing a function in this case. After all, re-ordering the variables (and the specifications) will solve the problem. If it is a one-time problem this is definitely the right strategy, ∗
Yes, I have admittedly taken this pun from the hilarious trilogy (in five volumes): A Hitch-hiker’s Guide to the Galaxy by Douglas Adams.
1. LINEAR EQUATIONS
11
T 3.1: Production data for a typical nitro-phosphate fertilizer plant.
Component Case I Case II -1 Ammonia 1300 ton d 1300 ton d-1 Mono-ammonium phosphate 200 ton d-1 200 ton d-1 Calcite − 0 -1 Calcium nitrate tetrahydrate 200 ton d − Oxygen (output) 0 0 Carbon dioxide (input) 0 0 Water (input) 100 ton d-1 0
but if the equations are part of a more general problem setup, it can be easier to keep the coefficient matrix unchanged, and flag the x(i)’s and b(j)’s as suggested above (see Appendix C.4). In process simulation you will find that most of the unit operations are without chemical reactions. Hence, simulating a complete chemical plant will most of the time mean that the mass balance and the component balance are equivalent concepts. However, if you view the plant from the outside and just look at the net reactions going on in its complex inner, you will frequently find that the atom balance is the key concept. One example follows: § 6 The chemistry of a nitro-phosphate fertilizer plant is quite complex and involves several steps of leaching, evaporation, neutralization, etc. The main reactions are NH3 + 2O2 2NH3 + Ca3 (PO4 )2 + 6HNO3 3H2 O + CaCO3 + 2HNO3 HNO3 + NH3
HNO3 + H2 O 3Ca (NO3 )2 + 2NH4 H2 PO4 Ca (NO3 )2 × 4H2 O + CO2 NH4 NO3
where NH3 , O2 , Ca3 (PO4 )2 , CaCO3 , H2 O and CO2 are considered to be (possible) reactants, and Ca (NO3 )2 × 4H2 O, NH4 H2 PO4 , CO2 , NH4 NO3 , O2 and H2 O are (possible) products. Note that H2 O, O2 and CO2 appear as both reactants and products (the recipient act as a buffer). Your task is to calculate all input and output flows given the production data in Table 3.1. Hint: Let x˙ and y˙ be vectors of reactant and product flows respectively, and A and B the corresponding formula matrices. Make sure your definitions are compliant to A˙x = B˙y. You can then choose to solve either B−1 A˙x = y˙ or A−1 B˙y = x˙ using the partial inversion algorithm from the last example.
F . Nothing really new here, except that you have to specify two coefficient matrices in order to solve one equation system (Appendix C.5).
12
3. HOW TO SOLVE EQUATIONS
2. Independent reactions The calculation of mass conservation due to chemical reactions is tightly coupled to linear algebra. Consider the so-called formula matrix for the system CO–H2 O–CO2 –H2 : 0 2 0 2 A = (atoms × species) = 1 0 1 0 1 1 2 0 Given a mole number vector n for the species mentioned above, we can calculate the mole numbers of the atoms from the standard matrix product b = An. For all reactions taking place in a closed system we know that the atoms must be conserved (not talking about nuclear reactors here), and if the changes in the species mole numbers are represented by ∆n this leads to ∆b = A∆n = 0. The next step is to find a general solution to this problem. The full-blown theory belongs to a course in linear algebra, but from physical reasoning we can argue that ∆n must be a function of the independent reactions of the system. Hence, if we let x represent the extents of (independent) chemical reactions, and N the reaction stoichiometry matrix, we can write ∆n = Nx. Combining the last two equations, and realizing that x is by definition a free vector variable, we get the necessary condition AN = 0. By standard row elimination, and column permutation if this proves necessary, matrix A can be factored into I B A→ 0 0 Thus, by setting N = B −I we obviously have a stoichiometric matrix N which fulfills the mass balance equation AN = 0. Neat, isn’t it? § 7 Find a set of independent reaction equations that fully describe monoprotic acid–base titration: HA + B A− + BH+ The equilibrium reactions are assumed to take place in an aqueous environment and you should therefore end up with 3 equations. A- . The Matlab code listed in Appendix C.6 will assist you in getting the reaction stoichiometry right, but traditional hand calculations are perfectly OK. 3. Linear parameter estimation The issue in this section is to find the minimum sum-of-squares of a function that depends linearly on the coefficients. Let the sum-of-squares function be n
(yi − f (xi , c))2 , s= i=1
3. LINEAR PARAMETER ESTIMATION
13
where yi and xi = (xi,1 , xi,2 , . . . , xi,n ) are the experimental observations, and c = (c1 , c2 , . . . , cn ) are the parameters of the model f (xi , c). If the sum-of-square function shall be a minimum one with respect to the parameters c1 , c2 , . . . , cn we must show that ∂s ∂s ∂s = = ... = = 0. ∂c1 ∂c2 ∂cn Provided the model f (xi , c) is linear in the parameters we can write fi = for s we get the expression: 2 n n
yi − s= ai j (xi )c j = (y − A (x) c)T (y − A (x) c) i=1
j
ai j (xi )c j , and
j=1
I have deliberately chosen a matrix definition of the function, because this is one of the key issues in this course: Try to think in terms of matrices and vectors if at all possible! Differentating s with respect to ck and putting the result equal to zero yields n n
∂s yi − =2 ai j (xi )c j aik = 2A (x)T (y − A (x) c) = 0, − ∂ck i=1 j=1 or simply
−1 c = AT A AT y.
These are the so-called normal equations∗ of the system A(x)c = y. Note that the equation system is over-determined, i.e. there are more observations (equations) than parameters. Thus, there will be no solution except if the observations are in perfect agreement with the experimental data. Such coincidence never happens in practise and we must therefore look for an inexact solution. Among all the alternatives we shall go for the solution that minimizes the Euclidean length of the observed deviations yi − f (xi , c). § 8 Fit the coefficients ci∈{1,2,3} in the expression log µ = c1 + c2 T −1 + c3 T −2 to µ, T -data found in water viscosity 1bar data.txt see Appendix E.3 L . You may think this is a non-linear problem, but no! Even though µ is a non-linear function in T it will still be a linear function in the coefficient vector c. The formula matrix is 1 T 1−1 T 1−2 .. , .. A (T ) = ... . . 1 T n−1 T n−2 and the corresponding observation vector is y = log µ1 , . . . , log µn . A Matlab script for solving the least square problem is given in Appendix C.7. § 9 Fit the coefficients ci∈{1,2,3,4} in Wagner’s vapor pressure equation to p, T data found in water vapor pressure.txt see Appendix E.1. Wagner’s equation can be ∗
Actually, Matlab is capable of solving such problems directly with the special “operator” c = A\c but the backslash means several things depending on the arguments and we shall not pursue this alternative any further.
14
3. HOW TO SOLVE EQUATIONS
written: def
T r log Pwagner = c1 τ + c2 τ1.5 + c3 τ3.0 + c4 τ6.0 r def
τ = 1 − Tr def T Tr = Tc def p pr = pc The critical constants of water are T c,water = 647.1 K and pc,water = 220.64 bar. V . Don’t let this seemingly complex model scare you! Note carefully that the function T r log pwagner is linear in the coefficients c1 − c4 . You can therefore use r standard linear parameter estimation theory if the observed T, p-data are converted to T r log pr and τ. This yields τ31 τ61 τ1 τ1.5 1 .. .. .. , A (T ) = ... . . . 1.5 τn τn τ3n τ6n and
T r,1 log pr,1 .. y = . T r,n log pr,n The Matlab code is given in Appendix C.8.
§ 10 Fit the coefficients c1 and c2 in the expression ρ = ρmax ec1 τ ec2 τ to ρ, T -data found in water density 1bar data.txt see Appendix E.2. The definitions of τ and ρmax are: T − 273.15 − 3.98 τ= [K] 1.3
1.6
−3
ρmax = 999.97490 kg m L . As before, the trick is to transform the equation; this time to log(ρ/ ρmax ) = c1 τ1.3 + c2 τ1.6 . The rest is standard, see Appendix C.9. 4. Polynomials Easy to understand, easy to manipulate, and easy to calculate — there are many reasons why polynomials appear in engineering calculations, e.g. when an exact solution is missing or for some reasons out of scope for numerical work. However, polynomials may also be the outcome of theoretical investigations as shown in the pH-calculation discussed below. Dealing with such problems it is important to know that polynomial root finders are very stable, but that it may sometimes be difficult to interpret the physical root among the several false ones. In Ex.7 we discussed the independent reactions of monoprotic acid-base titration. The net reaction equation was HA + B A− + BH+
5. SINGLE NON-LINEAR EQUATIONS
15
Assume that the initial concentration of the base (in the flask) is C 0B , and that the acid is being added in arbitrary amounts. The nominal∗ concentration of the acid C HA is then a free variable. Eliminate the other variables in the equation system till you end up with P4 (C H + ) = f (C 0B , NHA , k1 , k2 , k3 ), where ki∈{1,2,3} are the equilibrium constants and P4 stands for a 4th degree polynomial. § 11 Write a Matlab script that calculates pH as a function of the nominal acid concentration using ca=linspace(0,2*cb,1000), where cb is 0.1 mol l-1 . Neglect possible volume changes during this “numerical experiment”. H-. There are infinite many choices of independent reactions, but a nice choice is the following one (H+ appears only once and this makes the elimination process easier): x
HA + B BH+ + A− y
H2 O + B BH+ + OH− z
H+ + B BH+ The extents of reaction x, y, z (in the right direction) can be used to express the mass balances as shown below: (x + y + z) y C BH + COH − def = 0 = C H2 O 10−pKb = k1 CB CB − x − y − z C A− C H + −xz def = 10−pKa = k2 = C HA CA − x def
COH − C H + = −yz = C H2 O 10−pKw = k3 Elimination of x and y gives −k1 z4 + k1C 0B + k3 + k1 k2 z3 + k1 k2C HA + k1 k3 − k1 k2C 0B − k2 k3 z2 − k2 k3C HA + k32 + k1 k2 k3 z + k32 k2 = 0, which can be solved repeatedly to yield the titration curve for the acid–base pair. At each titration point we have to choose among four possible solutions. There are no clues as to which of the roots is the physical one, but in this case it appears to be the negative root (Appendix C.10). 5. Single non-linear equations There exist several “general-purpose” equation solvers in Matlab, but their mathematical methods are well beyond the current scope. Regretfully so because we are then reduced to ordinary users of advanced code, which in turn makes it hard to tell what is clever and what is dumb. I mean, how could we possibly tell without knowing the underlying theory? An important concept in this chapter will be the functional that is discussed more carefully in Chapter 5. It is achieved in this context by the function handle operator @ which lets the user specify a run-time definition of the equation to be solved. The necessary actions are then taken by the solver through the built-in function feval which is used to run a user specified function with solver specific variables. This is a good example on the “tool-box” idea of Matlab. ∗
Nominal means measured before any reactions take place.
16
3. HOW TO SOLVE EQUATIONS
§ 12 Calculate the pressure drop over a L = 2000 m long pipe transporting ˙ Q = 0.5 m3 min-1 of water. The pipe (D = 5 cm) is made of commercial steel. The temperature of the water is θ = 8 ◦ C. Use density and viscosity functions from Ex.19 and Ex.17. Hint: Colebrook’s equation for the friction factor is: ε 2.51 1 + = −2 lg 3.7 · D f f Re 2 f Lv [m H2 O] ∆p = 2Dg Use function fzero to solve this equation inside your pressure drop calculation. Hint: write a function colebrook(lnf,eod,lnRe) which returns the residual on the form∗: e 1 2.51 log ( f ) + log −2 lg D + 2 3.7 exp 1 log( f ) + log (Re) 2 P-. The friction factor can be solved explicitly as lnf = fzero(@colebrook,lnf,opt,eod,lnRe) where opt=[’display’,’iter’] can be used to display the iteration progress. The Matlab code for the Colebrook residual is given in Appendix C.11, and for the pressure drop calculations in Appendix C.12. This exercise illustrates an extremely important issue in non-linear equation solving. In theory any residual function that evaluates to zero at the solution point is sufficient for finding the correct answer, but in practise only a few residual functions will be same. Finding a good residual is an art, but the following rules of thumb may be of value: (1) Make sure the residual is comparable to 1, i.e. 10−6 should be considered a small residual and 106 a big residual. This can of course be achieved by pure scaling. (2) Make sure the gradient has comparable magnitude in all directions (at least close to the solution point). (3) Residuals that are appealing to the human eye are not necessarily what makes your algorithm effective. Finding one single root of a function is usually not a big problem, but when the issue is to build a more general function these rules may become important (see Exercise 13). 6. Sets of many non-linear equations § 13 The inverted variant of Ex.12 is to calculate the volumetric flow rate for a given pressure drop. This calculation is a little more involved because there are two non-linear functions to be solved simultaneously (Re = ρvD/µ): L v2 D 2 ε 2.51 1 + = −2 lg 3.7 · D f f Re ∆p = ρ f
F-. The same procedure as in Ex.12, except that we must call fsolve rather than fzero. In the function call I have chosen to define a struct for copying the parameters. This is much easier than to remember explicit parameter ordering in the function call ∗
It took me two full days to convince myself that there is no way to avoid the logarithmic form. However, feel free to try other residual forms and prove that I am wrong!
6. SETS OF MANY NON-LINEAR EQUATIONS
17
(just try to remember the order of six parameters for more than five minutes). I have also taken the trouble to vectorize the calculations in order to be prepared for future demands. The solution is this time written x = fsolve(@friction and reynold,[lnRe,lnf], opt,@colebrook,s); where lnRe=x(:,1) and lnf=x(:,2) on output. The Matlab code for the two flow residuals is listed in Appendix C.13, and for the flow rate calculations in Appendix C.14. § 14 From fluid mechanics you know that turbulent flow develops at Re 2300. Write a Matlab script that reveals the transition from laminar to turbulent flow. T . Needs a f -relation for laminar flow which can be 64 compared with Colebrook’s function in Ex.12, i.e. f = Re . This relation is explicit in f and there is no need for a non-linear solver, but who cares since the point here is to learn about solvers (see Appendix C.15)! The flow rate calculations comparing laminar with turbulent flow are found in Appendix C.16. § 15 Hallvard Svendsen, Ex.7: Compressible friction flow. C . Not implemented.
CHAPTER 4
Write your own functions 1. The function concept When you start Matlab you will enter (the topmost) workspace. From there, you can enter commands at the keyboard, or you can import several commands at once from a script file, in order to build up the content of your workspace. You can also make calls to external procedures (called functions in Matlab). When a function has finished its job it will return to the workspace, hopefully with some results. Functions may even call other functions, but eventually the control will be returned to the topmost workspace. Note, however, that all variables passed back and forth in a function call is done “by copy”: In fact, entering x=exp(3) into Matlab, copies the number 3 into the exp function, which returns a copy of the result to the variable x. The exp function does not change the number 3 in any way! To illustrate this further let us try the command sequence x=3; x=exp(x). In this case the variable x is first asked to hold a copy of the number 3. Thereafter, the value of x (which is still 3) is copied into the exp function, and the result is finally copied back into x. In this case x really did change, but only because we told it explicitly to do so. This is called imperative programming. § 16 Write a function chon(x,y,z,w) for calculating the molecular weight of the fictitious compound Cx Hy Oz Nw . M CHON-. See Appendix C.17.
2. Vector functions By vector function I mean a function that calculates more than one output value. Typically, these functions should mimic the shape of their input arguments. As an example take the built-in function exp. If you enter something like x=[1 2; 3 4]; y=exp(x); from the keyboard, you will get an y-matrix with the same shape as x. This is veeery handy and is certainly something you should pursue when you write your own functions. § 17 Make a Matlab function that calculates log µH2 O = c1 + c2 T −1 + c3 T −2 for an arbitrary temperature matrix t. The function syntax is water viscosity 1bar(t) and the parameters are c = [-8.0003593134, -1470.7557834, 526396.01377] see also Ex.8 W . The trick is to inherit the shape of the temperature argument in the function body. The matrix e=ones(size(t)) will do this, as shown in Appendix C.18. = f (T ) for an arbi§ 18 Make a Matlab function that calculates log pwagner water trary temperature matrix t. The Wagner equation is described in Ex.9. The function syntax is water vapor pressure(t) and the parameters are c = [-7.78664494819, 1.50070473755, -2.82073715777, -1.20214640863] 19
20
4. WRITE YOUR OWN FUNCTIONS
W . Same trick as in Ex.17, see Appendix C.19.
§ 19 Make a Matlab function that calculates ρwater = ρmax ec1 τ +c2 τ for an arbitrary temperature matrix t. The function syntax is water density 1bar(t) and the parameters are c = [0.00003932621, -0.00003868077], see also Ex.10. 1.3
W . Same trick as in Ex.17, see Appendix C.20.
1.6
3. Iterative functions (algorithms) The K-value method for solving 2-phase equilibria consists of solving the equations yi = Ki xi and (1 − α)yi + αxi = zi for all components i ∈ [1, n] in the mixture. Normally, yi and xi will be the mole fractions of component −i− in the vapor and liquid phases respectively, and α will be the mole fraction of the liquid phase (i.e. the number of moles in the liquid phase compared to the total numbers of mole present in both phases). Fiddling around with the symbols it can be shown that everything boils down to solving one non-linear equation in α:
z (1 − K ) i i f (α) = =0 α + (1 − α) Ki After this equation has been solved the two mole fractions can be calculated explicitly: zi xi = α + (1 − α) Ki Ki yi = xi § 20 Write a function [x,y,l] = rachford rice(z,k) that calculates the component mole fraction vectors x and y along with the phase mole fraction of the first phase (i.e. the phase from where the x is taken). On the input side z is the total composition vector and k is the vector of K-values. R-R. This problem is ideally suited for Newton’s method because it turns out that the merit function is monotonically decreasing: 2
1 − Ki ∂f =− zi 0) fac = n*recursive_factorial(n-1); else fac = 1; end
4. RECURSION — GOOD, EVIL OR MAYBE BAD?
recursive factorial.m ends here
21
def
Another favorite is the calculation of the Fibonacci sequence F n = F n−2 + F n−1 . The Fibonacci numbers derived from F 0 = 1 and F 1 = 1, and other sequences built on the same principle, appears in surprisingly many fields of science like e.g. biology, number theory, architecture, optimization theory, chemistry, etc. The code listed in (recursive randmine) uses the Fibonacci sequence to generate random numbers given the two start values 0.8 and 0.0 and the imposed rule that all addition is modulo 1. This means we shall not be interested in the magnitude of the number, just the fractional part of it. snippet from recursive randmine.m starts here function [x] = recursive_randmine(n) if (n>2) x = recursive_randmine(n-1) + recursive_randmine(n-2); else x = 0.6 + 0.2*n; end x = x - floor(x); recursive randmine.m ends here
Whereas n! eats CPU-time in proportion to n, F n is much more greedy. It is in fact the worst kind of application you can possibly write because the CPU-time grows exponentially with n, look at Table 4.1 for details. Another interesting observation concerning the modified Fibonacci sequence is its periodicity. Look carefully at the list generated below, n 1 2 3 4 5 6 · · · 19 20 21 22 23 24 mod(F n , 1) 0.8 0.0 0.8 0.8 0.6 0.4 · · · 0.6 0.2 0.8 0.0 0.8 0.8 and you will see that the sequence repeats itself after 20 calculations. In other words: F 21 = F 1 , F 22 = F 2 , and F 23 = F 3 . Since the recursion needs only two members F n−2 and F n−1 to calculate F n it is sufficient to observe the repetition of three numbers in order to prove that the entire sequence will repeat. Another feature is that the sequence is reproduced each time it is evaluated, irrespective of the programming language, the programmer or the computer. This is the reason why random numbers produced by generic formulae are called pseudo-random. So, what has all this to do with chemistry students? A lot really, since random numbers are used heavily to: (1) Replace observations of random nature, e.g. add “white” or “pink” noise to other simulations in order to produce more realistic results. (2) Test algorithms. I cannot possibly think of any better way of testing an algorithm than to let it work on a massive set of random input data. (3) In statistical theory like statistical mechanics, molecular dynamics and Monte Carlo methods. (4) In optimization theory, i.e. “simulated annealing” techniques used in e.g. process optimization. (5) Make you work with individual problem solutions in this course. One comment about the last item: To make sure I will be able to verify your results (on midterm exams), we must use the same random number generator and I have to control the “seed” you use to start the sequence. This is the reason you should implement “randolph” listed in Appendix C.1. Not all programming languages open up for recursive definitions (e.g. FORTRAN77), and the reason is very simple: If you forget to test the input arguments properly, the function will call itself forever! It is like executing the loop while(1>0) without
22
4. WRITE YOUR OWN FUNCTIONS
T 4.1: Calculation of Fibonacci-numbers using recursive function calls. Note exponential growth in CPU-time.
n 1 .. . 14 18 22 26 30
mod (F n , 1) time[s] 0.8 0.000 .. .. . . 0.2 0.020 0.6 0.171 0.0 1.101 0.4 7.500 0.8 51.38
breaks, but because things are less transparent when using function calls such ill-defined recursiveness can be hard to debug. § 21 Solve the problem y = x2 using recursive programming. The function syntax is x = recursive sqrt(y,x0), where x0 is a user supplied start estimate for the algorithm. Hint: The Newton method gives rise to 2xδx + x2 − y = 0. From this scheme we can write an explicit update of xk+1 like this: 1 y + xk xk+1 = 2 xk S . One possible recursive update is x = recursive sqrt(y, 12 yx + x ), and this really works! E.g. evaluating recursive sqrt(2,6.023e23) yields the correct an√ swer 1.4142 . . . after 84 calls (the Avogadro number is a rather poor estimate of 2). The code from recursive sqrt is shown below: snippet from recursive sqrt.m starts here function [x] = recursive_sqrt(y,x) if (abs(x*x-y)>eps*y) x = recursive_sqrt(y,(y/x+x)/2); else x = x; end recursive sqrt.m ends here
You may wonder why you should bother about recursive definitions at all since the applications we have met so far are rather trivial. My advice is: Recursive calculation is very nice if you are able to prove convergence a priori, or if you are interested in the mathematical behavior of the solution, or if you are interested in compact definitions (this may yield a tremendous increase in program readability if your algorithm is complex). Besides, recursiveness is in the heart of declarative (functional) programming. However, since function calls are much more expensive than arithmetic operations (+, i, ∗, /), massive recursiveness should be avoided if the function overhead steals excessive CPU-time.
CHAPTER 5
Functionals or function(function)s A functional in this context means a function that takes another function as input and produces a number. Examples are: Definite integrals, minimization procedures, partial diffentials, Taylor expansions, etc. 1. Integration § 22 The velocity profile in a circular duct is needed to calculate the average volumetric flow of gas. A series of pitot-tube measurements gave the following result where the dynamic pressure is in mm fluid head: 4.7 10.7 18.3 20.5 20.5 23.3 29.6 20.4 16.2 11.8 hNS = 2.1 8.6 15.4 16.2 21.3 21.3 20.5 16.8 13.3 2.2 hEW The gas has molecular weight 28 gmol−1 , temperature 110 ◦ C and pressure 1 bar. The density of the sealing fluid is 850 kgm−3 . The cross-section is divided in five concentric rings, all with the same area (four measurements in each ring). The total diameter of the duct is 1.6 m. Calculate the volumetric flow in m3 /h using Simpson’s integration rule, confer function quad. P-. The determination of gas velocities in large ducts and chimneys is quite regularly done with a pitot-tube. From several measurements at different radial positions the velocity profile is easily constructed. In this particular case we have measurements in the North-South and East-West cross sections. If we average the measurements the velocity profile can be based on polynomial approximation. We can e.g. assume laminar flow (very wrong!) and thereby ask for a parabolic velocity profile. Then a second order polynomial is correct and the function polyfit suffices. However, the velocities at the boundaries are not zero, see Appendix C.23! A better fit is obtained by increasing the number of parameters in the polynomial, but remember that higher order polynomials can oscillate violently (even inside the fitted region). The result may become terribly wrong although in the current example it is not too bad. Alternatively we could give up every analytical effort and go for a cubic spline interpolation. This time the velocity profile becomes flat i.e. the flow is turbulent, but the spline will allways go through all the points so it is not possible to jugde how accurate the “fit” is. It may still be a useful tool to get an idea of shape of the profile, however. 2. Ordinary differential equations When Chemical Engineers face up to model and simulate a given system, it seems that a major concern is whether the ODE-solver will work. This turns into a nightmare when things go wrong and it is really disappointing when the computation crashes. Most often the problem is that we fully trust the “stupid” built-in code to do the whole job for us. In order to solve their simulation models, Chemical Engineers usually deal with explicit first-order systems of differential equations (ODEs) with algebraic side constraints, 23
24
5. FUNCTIONALS OR FUNCTION(FUNCTION)S
turning the problem into a system of differential–algebraic equations (DAEs) of the form: f (dx/ dt, x, t, u, y) = 0 where x is the set of n differential variables, y is the set of m algebraic variables, u is the set of k input variables, and f is the set of n + m DAE equations. The solution of such a problem requires two steps: (1) Defining and solving for the initial state x(0) of the system at t = 0 (initial time). (2) Numerical integration of the DAEs from t = 0 to t (final time). The second step is generally straightforward for simple systems. The challenge is to consistently initialize the DAE system which means to solve step 1 above. If not performed well it may cause the system to diverge in step 2. However, a DAE system might be easier to deal with than a pure ODE system because the extra equations give degrees of freedom we can use in the initialization. E.g. if the temperature evolution is constrained by an energy balance it is easier to initialize T such that the energy balance is fulfilled, than it is to solve the non-linear energy equation with respect to T as would be required in a pure ODE set-up. § 23 Consider a gas A that dissolves into liquid B and diffuses isothermally in the liquid phase. During the diffusion A undergoes an irreversible first order homogenous reaction A + B → AB. If the mixture is treated as a binary solution, ignoring AB, the mass balance can be written: DAB
d cA − k1 cA = 0 d z2
This equation can be solved with the boudary conditions z = 0, cA = cA0 and z = L, d cA / d z = 0. The equation can be rewritten into dimensionless variables (5.1)
d2 Γ − φ2 Γ = 0 2 dζ
= 0, and ζ = 0, Γ = 1 and ζ = 1, with boundary conditions ζ = 0, Γ = 1 and ζ = 1, dΓ dζ Γ = 0. Solve the equation numerically and compare the solution you get to the exact solution given by (5.2)
Γ = C1 cosh(φζ) + C2 sinh(φζ)
D. Any ODE function in matlab will produce the solution to this problem with no problems. ODE functions can only solve (systems of) first order ordinary differential equations. This problem is of second order. This can easily be rewritten to a system of two first order equations. y + y + y = 1 can be written u1 = u2 u2 = 1 + u1 + u2 Another consideration of this problem is the fact that the ODE solvers only support initial conditions. Here, one initial condition is given, and one boundary condition. In order to satisfy the initial conditions one have to iterate as shown in Appendix C.22. The discrepancy between the numerical and analytical solution comes as a consequence of the boundary conditions not being satisfied completely.
4. OPTIMIZATION WITH CONSTRAINTS
25
3. Unconstrained optimization § 24 Terje Hertzberg: Non-linear parameter estimation. N- . Not implemented.
4. Optimization with constraints A thermodynamic equilibrium state is always optimal, i.e. it is either at a minimum or a maximum of the pertinent thermodynamic state function. Exactly which state function we are talking about depends on the constraints, and e.g. for ideal gas combustion it is correct to minimize Gibbs energy: minG(T, p, n) n
An = b. Note that the minimization is subject to n only, keeping T and p constant during the calculation. There are several methods available for solving linearly constrained minima, but my favorite is the Newton-Lagrange scheme which can be derived from the so-called Lagrange function n m
λi Ai j N j − bi = G − λT (An − b) . L=G− i=1
j=1
By differentiation L with respect to Nk and λl at constant T, p, and putting the partial derivatives equal to zero, we end up with the following equations describing the thermodynamic equilibrium: ∂L = µ − AT λ = 0 ∂n ∂L = An − b = 0 ∂λ These stationary conditions are finally solved by Newton’s method: T ∂µ T A δn λ − µ A T ∂n = (5.3) −δλ b − An A 0 § 25 Write a function [n] = mingibb(n0, T, p, mu0, A) which solves Eq.5.3 iteratively for an ideal gas system. The chemical potential vector of an ideal gas is P µig = µ◦ + RT log ◦ N −1 n P n = N1 N2 . . . Nn
N= Ni , and the Hessian matrix:
∂µ ∂nT
ig
−1 N1 def ig .. = H = RT .
Nn−1
RT I − N
26
5. FUNCTIONALS OR FUNCTION(FUNCTION)S
G . Once you master vector/matrix notation, the calculations are straight forward, but you must remember to test for negative mole numbers. The algorithm will quite frequently take you into the unphysical region and the question is what to do then. Many things can be said about this topic, but it appears that in this special case it will be sufficient to shorten the step to, say, a fraction 0.9 of the maximum allowable step, see Appendix C.25.
5. Process control Process control is an engineering discipline that deals with architectures, mechanisms, and algorithms for controlling the output of a specific process (from Wikipedia The Free Encyclopedia). Applications are found almost everywhere e.g. in the chemical process industry, in living organisms and in robotics. Here we shall deal with one brief example taken from the control of chemical reactors. The essential steps in developing a control structure include the following: (1) Objectives: Study the physical behavior of the system and decide on the control objectives. (2) Modeling: Build a mathematical model and simplify if necessary (either from experimental data using identification techniques, or from physical equations describing the plant dynamics). (3) Controllability: Decide which variables are to be controlled (identify the manipulated and measured variables and which links should be made between them). (4) Structure: Decide on the measurements and manipulated variables (what sensors and actuators will be used and where shall they be placed). (5) Design: Select the control configuration and decide on the type of controller to be used (formulate a mathematical design problem which captures the engineering design and synthesize a corresponding controller). (6) Analysis: Decide on performance specifications, based on the overall control objectives (assess the control system by analysis and simulation against the performance specifications or the designers expectations). (7) Implementation: Simulate the resulting controlled system (either on a computer or a pilot plant). In the following example we use steps one to four to study a simple reactor controller. § 26 A continuous stirred tank reactor (CSTR) has variable feed qin and variable heat load Q. In the stationary state the incoming fluid has temperature T in = 350 K, concentration C A,in = 2 kmol m−3 and volume flow qin = 1 m3 min−1 . The corresponding heat load and reactor temperature are Q = 5000 kJ min−1 and T = 400 K respectively. The (only) first order reaction taking place is A → B. The reaction rate r = kC A follows the Arrhenius law k = k◦ e− R E
1 1 T − T◦
where k◦ = 0.5 min−1 , E = 20 kJ mol−1 , R = 8.31453 J mol−1 K−1 and T ◦ = 400 K. The task is to control the output concentration C A using qin and Q as control variables. The temperature T in and concentration C A,in are disturbances to the process. There is no B in the feed. Other (constant) data are: reactor volume V = 4 m3 fluid density ρ = 1000 kg m−3 and heat capacity CP = 0.15 kJ kg−3 K−1 .
5. PROCESS CONTROL
27
CSTR. The Matlab code in Appendices C.26, Appendices C.27 and Appendices C.28 produces four plots. The steady state is first verified (plot 1) before a series of dynamic responses to some step changes and disturbances are calculated (plot 2). The model is then linearized and the state-space matrices A, B, C, D, E and F are calculated along with the controllability, the observability and the stability of the model. Finally, the code generates the transfer function and calculates its poles and zeros, and the RGA in different frequencies (plot 3 and 4).
CHAPTER 6
String parsing 1. Chemical formula arithmetics Consider a simple chemical formula like H2 O. What does it tell us? Of course you know the answer; take two atoms of hydrogen and one atom of oxygen, combine and you have water. However, I am quite sure you have never reflected over how close the chemical formula is an arithmetic expression! E.g. the expansion H2 O → H ∗ 2 + O is a valid expression for the molecular weight of water (assuming that H and O are constants defined as the molecular weight of hydrogen and oxygen respectively). This idea can be carried further, e.g. the expansion Ca (NO3 )2 (H2 O)4 → Ca + (N + O ∗ 3) ∗ 2 + (H ∗ 2 + O) ∗ 4 is a valid expression for the molecular weight of calcium nitrate. The whole idea is to identify tokens in the formula and insert arithmetic operators when required. In the simple examples above we have to distinguish five tokens 0−9 a−z A−Z ) ( and two operators
+ ∗ In addition we must obey three rules which are specific to chemical formulas: Element names contain at most one lower case letter, which cannot be the first letter in the name, and empty parentheses are not allowed in the formula. The full operator table is shown in Table 6.1. It tells you which operator to insert given a left and right operand. Parsing e.g. the input string ’H2O’ from left to right yields the following sequence: H2O
le f t=H,right=2
→
H ∗ 2O
le f t=2,right=O
→
H∗2+O
Note that the two operators + and ∗ are what we call binary operators, i.e. they are of the form x ◦ y where x is the left operand and y is the right operand. Hence, it is sufficient to analyse just two characters at a time! T 6.1: Operator table for converting chemical formulas into arithmetic expressions.
right left 0−9 a−z A−Z ) (
0−9 a−z A−Z none + ∗ error ∗ none ∗ error + + 29
+ + + + none
)
(
none + none + none + none + error none
30
6. STRING PARSING
§ 27 Write a function expr = mw from formula parser(formula) which returns a valid arithmetic expression from a given input string (chemical formula). E.g. the function call expr = mw from formula parser(’H2O’) shall return the string expr = ’H*2+O’. Make use of the function op = mw binop(x,y) in your code. C . No big surprises here, except that I for some reason (don’t remember exactly why) implemented the parser as RL and not LR. Anyway, the Matlab code is nice and clean (Appendix C.29). § 28 Write a function op = mw binop(x,y) that analyses the two operands x (left) and y (right) and returns the correct operator from Table 6.1 (as a string). C . There are many ways to implement this operator table and the one shown in Appendix C.30 is definitely not the most compact. However, legibility is also an important issue! In the next exercise you will benefit from knowing the function [s,b] = get formula vector(s, b, e, f). This function takes an input string s, a vector of stoichiometric factors b which accompanies the list of known element symbols e, and an external multiplicative factor f . The function syntax you should use is get formula vector(s, zeros(length(n), 1), e, 1.0). It will parse s from right to left and try to resolve the stoichiometric factors corresponding to the supplied list of element symbols. The parsing continues till a right paranthesis is found, or till the string is exhausted. If a right paranthesis is found get formula vector calls itself recursively till the string s is exhausted, so in your case s shall allways be an empty string on output. § 29 Write a function [A,e] = make formula matrix(formula1,formula2,. . .) that analyses an arbitrary number of chemical formulas and calculates the coresponding formula matrix A, and a list of chemical symbols e representing the rows of A. F . I have elaborated the interface a little in Appendix C.31 to make the function more flexible, but the biggest job was to get the chemical symbols correct (it turned out that the chemical symbol of Lawrencium had changed from Lw to Lr since the time I was a student). § 30 Last but not least, try to program the function [s,b] = get formula vector(s, b, e, f) as it was introduced above. F . This is a fairly big programming job where you will need recursive programming and ASCII-encoding. To make the code more versatile I have in Appendix C.32 opened up for decimal numbers in the chemical formula. E.g. ’FeO0.977’ is a legal input string. 2. Cool stuff (regular expressions) Consider the situation where you have a huge amount of information with some (known) structure but are only interested in a small part of the data. Typically you may be interested in extracting information from an HTML file (garbage filtering) or to summarise the output from a big simulation run into a small table in Excel (report generation).
2. COOL STUFF (REGULAR EXPRESSIONS)
31
In order to retain the data of interest, regular expressions are very powerful. Table 6.2 shows a list of the most common expressions. T 6.2: The most common regular expressions
Symbol Meaning ˆ Start of string $ end of string . any character \ quote next character ∗ match zero or more + match one or more ? match zero or one [] match set of characters [ˆ] exclude set of characters () group subexpression \w match word [a-z A-Z0-9] \W not a word [ˆa-z A-Z0-9] \d match digit [0-9] \D not a digit [ˆ0-9] \s match white space \S not a white space | logical “or” Assume we want to count the number of sentences in a text document. This can be done using the regular expression [A-Z][ˆ.|ˆ!|ˆ?]+[.|!|?] on a string representation of the document. The search will match everything which starts with a capital letter and ends with . or ! or ? The end of the matching sub-string is used to define the start of the next search till the entire string is fully explored. § 31 Calculate the CO2 equivalents for the vapor streams V1, V2 and V3 reported in the data file HYSYS report.txt. The report format is shown in Appendix E.4. Note that the HYSYS file contains much more data than what is needed to solve the task. Regular expressions are useful to do the filtering job, but the Matlab implementation of RE is rather ackward. It would of course be smarter to filter the data in another language with gives a better support for RE, but we shall stick to Matlab here because “to know a language you must learn about its limits”. G . First, the vapour streams in the output file from HYSYS must be located. It is then possible to filter out the stream data needed and calculate the CO2 equivalents. But, as you can see from Appendix C.33 the code is quite involved. The job is still worth the efforts if there are lots of data to be processed. Ideally, however, you should consider a language which is better suited for string handling and regular expressions like Ruby or Python. They yield less code which at the same time is easier to write and maintain, see Appendix D.1 for an implementation in Ruby.
APPENDIX A
Language elements
T A.1: File functions.
fopen open file fclose close file
T A.2: Special variables of mathematical character.
eps ans pi inf NaN
machine precision last calculated result pi infinity Not-a-Number
ε − π ∞ −
T A.3: Special characters.
% comment (rest of line is ignored) . . . statement continues on next line
T A.4: Basic commands that makes life easier, but has little to do with programming.
pwd whos what disp exit help load save format cd
print working directory list all variables in the work space list all functions in the local directory display text on screen exit the Matlab session give help topics read table from file save table to file change output format change local directory
33
34
A. LANGUAGE ELEMENTS
T A.5: Program flow control instructions.
if;elseif;else;end while;end for start:step:stop; end break return pause persistent function feval keyboard
declare conditional execution block(s) repeat execution block while logical argument is true repeat statements a specific number of times break innermost execution block break function execution suspend execution save variables in local namespace declare function evaluate functional halt execution while reading from keyboard
T A.6: Instantiation operators. Used when shaping or filling a matrix, a vector, etc.
[] , ; =
vector (matrix) constructor row separator column separator assignment operator vector or matrix transposition end last row or column element find evaluate logical argument for all vector/matrix elements T A.7: Plotting commands.
loglog title ylabel xlabel axis plot hold grid legend
logarithmic plot graph title y-axis label x-axis label control axes ranges linear plot hold current graph for additional plotting add grid lines place graph legends on the current plot
T A.8: Relational operators (logical operations).
eq;ne;gt;lt;ge;le and;or;not any all isnan isinf isempty iscell sort
numerical test operators logical (boolean) test operators equivalent to sum(arg > 0) > 0 equivalent to prod(arg > 0) > 0 true if argument is NaN true if argument is ∞ true if empty array true if cell array sort in ascending order
=, , >, > mod(6, 4) ans = 2 >> floor(3.95) ans = 3 >> ceil(3.95) ans = 4 >> isempty([]) ans = 1 >> char([ a , b , c ]) ans = abc >> num2str([1, 2, 3]) ans = 1 2 3 >> sort([2, 1, −4, 0]) ans = −4 0 1 2 Matrix inversion is simple in Matlab, but note that direct inversion is not much used — there are more efficient ways to solve a system of linear equations: A = inv([2, 1; 1, 2]) 0.6667 −0.3333 A= −0.3333 0.6667 LU-factorization is typically used in the first stage of a solution. It holds the outcome of an ordinary Gauss elimination of the rows of the matrix: [A, B] = lu([2, 1; 1, 2]) 1.0000 0.0000 A= 0.5000 1.0000 2.0000 1.0000 B= 0.0000 1.5000 37
38
B. EXAMPLES
QR-factorization is similar to LU but has some nice additional properties (orthogonal Q-matrix): [A, B] = qr([2, 1; 1, 2]) −0.8944 −0.4472 A= −0.4472 0.8944 −2.2361 −1.7889 B= 0.0000 1.3416 The row reduced echelon (staircase) form of a matrix properly identifies linear dependencies: [A, B] = rref([2, 1; 1, 2]) 1.0000 0.0000 A= 0.0000 1.0000 B= 1 2 The 2-norm is a measure for the Euclidian length of a vector. It is defined as the square root of the inner product of the vector with itself: a = norm ([3, 4]) a=5 Matrix eigenvalues and eigenvectors are important in the stability analyses in process control, differential equation solving and thermodynamic equilibrium theory: [A, B] = eig([2, 1; 1, 2]) −0.7071 0.7071 A= 0.7071 0.7071 1.0000 0.0000 B= 0.0000 3.0000 The matrix rank is important for the solvability of an equation system. Matrices with full ranks yield unique solutions while rank deficient matrices do not: a = rank ([2, 1; 1, 2]) a=2
APPENDIX C
Matlab code 1. randolph Randolph is a simple, yet effective random number generator for internal uses in this course. The rand function in Matlab yields far better randomness, but is more difficult to control by simple means (it used to be, but MathWorks has changed it — grrrr). With emphrandolph you can set the initial state of the generator by simply issuing the command randolph(n), where n ≥ 1 is a random number (called the seed) of your choice. The seed is much like a password, you must remember it in order to reproduce your calculations! After randolph has been initialized you can issue the command randolph(n,m) to generate n × m matrices of random numbers. %The program implements a lagged Fibonacci pseudo-random number generator %using subtraction [0]. A sequence of random numbers X(n) is obtained from %the formula: % % X(i) = X(i-q) - X(i-p) mod M % %where M is 1 if the X’s are taken to be floating point reals in [0,1) as %they are here. The period of this generator is (2ˆp-1)*2ˆ(b-1),where p is %the largest lag and b is the number of significant bits in the numbers %X(n).The lag needs to be chosen large enough to give a period much longer %than the number of random numbers to be generated.Only certain lags (p,q) %will give the maximal period of the generator [4, 5]. Some of these are %listed below: % % p q % 9689 4187 % 4423 2098 % 2281 1029 % 1279 418 % 607 273 % 521 168 % 250 103 % 127 63 % 97 33 % 55 24 % 31 13 % 17 5 % %Small lags can cause problems with this generator [1, 2, 5]. Larger lags %give larger periods and empirically seem to give "better" random numbers %[2, 4, 5]). I recommend using at least (1279,418),and ideally much larger %lags such as (9689,4187). Larger lags give higher quality random numbers %and longer period, with the only tradeoff being increased memory use and %initialization time. However initialization is very fast, and the memory 39
40
C. MATLAB CODE
%used is only of order p words, so p=2281 will add less than 10 Kbytes to %the memory required for the user program. This generator performs well in %empirical statistical tests [2, 4] as long as a large lag is used. This %does not necessarily mean it will perform well for your application.It is %recommended that you check your results by also running your program %using another good random number generator (see [1] for recommendations). % %0. http://www.npac.syr.edu/projects/random/generators/fibadd/fibadd.html %1. P. D. Coddington, Random number generators for parallel computers, % NHSE Review, Volume 2, 1996. %2. P. D. Coddington, Analysis of Random Number Generators Using Monte % Carlo Simulation, Int. J. Mod. Phys. C 5, 547 (1994). NPAC technical % report SCCS-526. %3. F. James, A Review of Pseudo-random Number Generators, % Comput.Phys.Comm. 60, 329 (1990). %4. D. E. Knuth, The Art of Computer Programming Vol. 2: Seminumerical % Methods, Addison-Wesley, Reading, Mass., 1981. %5. G. A. Marsaglia, A current view of random number generators, in % Computational Science and Statistics: The Interface, % ed. L. Balliard, Elsevier, Amsterdam, 1985. function [x] = randolph(n,m) persistent x0 o p q; if (nargin==1) if (n= 1, try again!’); return; end x0 = [0.52189398762154 0.22586125989448 0.78962235300517 ... 0.73889796980862 0.61383531911974 0.13010525023880 ... 0.64626222776828 0.22126297192155 0.92287218663571 ... 0.58354708643659 0.36750946939959 0.31286745921603 ... 0.59021783397155 0.05315767833273 0.37021959254501 ... 0.88726820502120 0.97633988457881 0.76793407983075 ... 0.24525730723827 0.91975917519955]; x0 = x0*n; % start modifying the seed vector x0 = x0 - floor(x0); % calculate the new seed o = max(size(x0)); % dim(x0) p = 17; % 1st random parameter. Note that dim(x0) >= p q = 5; % 2nd random parameter else if (isempty(x0)) disp(’You must initialize first, use randolph(n) where n>=1’); return; end x = [x0,zeros(1,n*m)]; % initialize random vector for i=1:n*m % repeat for all elements x(o+i) = x(o+i-p) - x(o+i-q); % Fibonacci sequence x(o+i) = x(o+i) - floor(x(o+i)); % Calculate random numbers end
2. OCTANE
x0 x end
= x(end-o+1:end); = reshape(x(o+1:end),n,m);
41
% update the seed vector % reshape to requested format
2. octane clear; format short; prompt = input(’Normal or bad case? [n/b]: ’,’s’); if (strcmp(prompt,’b’)) A = [90 105 95; 1-1e-15 1 1; 1 1 1]; disp(’Bad coefficient matrix:’) else A = [90 105 95; 0.2 2 0.5; 1 1 1]; disp(’Normal coefficient matrix:’) end disp(A); pause; b = [98; 1; 1]; disp(’Right hand side vector (specifications):’) disp(b); pause; x = zeros(size(b)); B = [A,b]; disp(’Adjoint matrix:’) disp(B); pause; B(2,:) = B(2,:) - (B(2,1)/B(1,1))*B(1,:); disp(’Element 2,1 eliminated:’) disp(B); pause; B(3,:) = B(3,:) - (B(3,1)/B(1,1))*B(1,:); disp(’Element 3,1 eliminated:’); disp(B); pause; B(3,:) = B(3,:) - (B(3,2)/B(2,2))*B(2,:); disp(’Element 3,2 eliminated:’) disp(B); pause; x(3) = B(3,4)/B(3,3); disp(’Solution variable 3:’) disp(x(3)); pause; x(2) = (B(2,4)-B(2,3)*x(3))/B(2,2); disp(’Solution variable 2:’)
42
C. MATLAB CODE
disp(x(2)); pause; x(1) = (B(1,4)-B(1,3)*x(3)-B(1,2)*x(2))/B(1,1); disp(’Solution variable 1:’) disp(x(1)); pause; format long e; disp(’The solution vector compared to Matlab:’) disp([x,inv(A)*b]); pause; disp(’Back calculated results compared to Matlab:’) disp([A*x,A*(inv(A)*b)]);
3. figure 2 8 clear; I O a s1 s2 o e
= = = = = = =
eye(2,2); zeros(2,2); [2 , 1]; [99, -1]; [10,-90]; O(1,:); I(1,:);
b = [101; 0; 2; 0; 0; o’; 0; o’]; A = [I, O, O, O , O ; ... o, o, o, o , e ; ... o, o, o, o , s1; ... o, o, o, s2, o ; ... I,-I, O, I , O ; ... o, a,-a, o , o ; ... O, O, I,-I ,-I ];
% specification of stream 1 % specification of A in stream 5 % specification of top product % specification of bottom product % component balance (mixer) % atom balance (reactor) % component balance (separator)
[B,j] xp xp(j) xh
= = = =
rref([A,b]); zeros(size(b)); B(1:length(j),end); null(A);
n X
= 200; = xp*ones(1,n) - xh*linspace(0,2000,n);
s3 s4 n3 n4 Q
= = = = =
[5,6]; [7,8]; sum(X(s3,:),1); sum(X(s4,:),1); X(s3(2),:).ˆ2./(X(s3(1),:).*n3);
loglog(n4,Q,’r’);
% stair case (exchelon form) % initialize % particular solution % homogenous solution % number of plot points % n solution vectors % % % total flow of % total flow of % equilibrium
stream 3 stream 4 stream 3 stream 4 quotient
5. FERTILIZER BALANCE
43
title(’Equilibrium restricted reaction’) ylabel(’x_{B}ˆ{2}/x_{A}’) xlabel(’Resirculation flow [mol sˆ{-1}]’) axis([10 1000 0.05 10]); hold on; grid; K i
= 0.74; = find(QK’,’Qtc); % find temperatures outside range = []; % remove them (avoid trouble) = []; % rearrange p in the same order = ones(size(t)); % unity vector = t/tc; % reduced temperature = p/pc; % reduced pressure = [e-tr,(e-tr).ˆ1.5,(1-tr).ˆ3,(e-tr).ˆ6]; % coefficient matrix = tr.*log(pr); % right hand side
48
%c [Q,R] c
C. MATLAB CODE
= inv(A’*A)*A’*b; = qr(A); = inv(R’*R)*A’*b;
% solve normal equations % QR-decomposition % more stable solution
%Generate (overwrite) the vapor pressure function "on the fly" ans = input(’Overwrite old ’’water_vapor_pressure.m’’ y/n [n]: ’,’s’); if ans==’y’ out = 0; func = ’water_vapor_pressure’; mfil = [func,’.m’]; format = ’%s\r\n’; fid = fopen(mfil,’w’); out = out + fprintf(fid,format,[’%Vapor pressure of water’, ... ’ using Wagner’’s equation.’]); out = out + fprintf(fid,format,[’%Pressure in [Pa],’, ... ’ temperature in [K].’]); out = out + fprintf(fid,format,[’ function [lnp] = ’,func,’(t);’]); out = out + fprintf(fid,format,[’ tc = ’,num2str(tc),’;’]); out = out + fprintf(fid,format,[’ pc = ’,num2str(pc),’;’]); out = out + fprintf(fid,format,[’ c = [’,num2str(c’,’%15.11f’),’];’]); out = out + fprintf(fid,format, ’ e = ones(size(t));’); out = out + fprintf(fid,format, ’ tr = t/tc;’); out = out + fprintf(fid,format,[’ tmp = c(1)*(e-tr) + c(2)*(e-tr).ˆ1.5’,... ’ + c(3)*(e-tr).ˆ3 + c(4)*(e-tr).ˆ6;’]); out = out + fprintf(fid,format, ’ lnp = tmp./tr + log(pc)*e;’); fclose(fid); disp([num2str(out),’ bytes of code written to ’,mfil]); end %The experimental data span the entire range from the triple point to the %critical point, which means it will be quite pointless to show the fit in %an ordinary 1/T,lnP-plot. The data are therefore transformed into the %deviation plot 1/T,dlnP, where dlnp = log(p) - [a + b(1/Tmin-1/T)], and %a = log(Pmin), and b = (log(Pmax)-log(Pmin))/(1/Tmin-1/Tmax). tmin tmax lnpmin lnpmax a b lnplin dpobs dtnorm dpcalc
= = = = = = = = = =
min(t); % mininum temperature max(t); % maximum temperature min(log(pr)); % minimum log(reduced pressure) max(log(pr)); % maximum log(reduced pressure) lnpmin; % 1 parameter in linearized plot (lnpmax-lnpmin)/(1/tmin-1/tmax);% 2 parameter in linearized plot a*e + b*(e/tmin-e./t); % linearized 1/T,lnP-plot log(pr) - lnplin; % observed deviations (e./t - e/tmin)/(1/tmax-1/tmin); % normalized 1/T data (A*c)./tr - lnplin; % calculated pressure devations
plot(dtnorm,dpobs,’o’,dtnorm,dpcalc); title(’Vapor pressure of water (Wagner’’s equation)’) xlabel(’Normalized 1/T (from triple to critical point)’) ylabel(’Transformed log(p) - [a+b(1/Tmin-1/T)]’) grid; pause;
9. WATER DENSITY 1BAR FIT
49
plot(t,exp((A*c)./tr)./pr-e); title(’Vapor pressure of water (Wagner’’s equation)’) xlabel(’Temperature [K] (from triple to critical point)’) ylabel(’Relative pressure deviation’) grid;
9. water density 1bar fit clear; %Maximum density of air-free water is approx. 999.97490+/-0.0001 kg mˆ{-3} %at 3.98 degree Celsius. Interpolated from Takenaka,M.,Masui,R.Metrologia, %27, 165-171, (1990). K2C = 273.15; dmax = 999.97490; tmax = K2C + 3.98; load -ascii ..\data\water_density_1bar_data.txt t d e [t,i] d dt A c
= = = = = = = =
water_density_1bar_data(:,1); % experimental temperatures water_density_1bar_data(:,3); % experimental densities ones(size(t)); % unity vector sort(t); % sort in ascending order d(i); % re-order the densities as well t - tmax*e; % make sure max. temperature is right [abs(dt).ˆ1.3,abs(dt).ˆ1.6]; % coefficient matrix inv(A’*A)*A’*log(d/dmax); % least square solution
%Generate (overwrite) the density function "on the fly" ans = input(’Overwrite old ’’water_density_1bar.m’’ y/n [n]: ’,’s’); if ans==’y’ out = 0; func = ’water_density_1bar’; mfil = [func,’.m’]; format = ’%s\r\n’; fid = fopen(mfil,’w’); out = out + fprintf(fid,format, ’%Density of water (1 bar) calculated’); out = out + fprintf(fid,format, ’%from log(rho) = tauˆ1.3 + tauˆ1.6,’); out = out + fprintf(fid,format, ’%where rho is d/dmax and tau is ’); out = out + fprintf(fid,format, ’%t-tmax. Densities in [kg/mˆ3] and’); out = out + fprintf(fid,format, ’%temperatures in [K].’); out = out + fprintf(fid,format,[’ function [d] = ’,func,’(t);’]); out = out + fprintf(fid,format,[’ c = [’,num2str(c’,’%15.11f’),’];’]); out = out + fprintf(fid,format, ’ e = ones(size(t));’); out = out + fprintf(fid,format,[’ tmax = ’,num2str(tmax,’%15.11f’),’;’]); out = out + fprintf(fid,format,[’ dmax = ’,num2str(dmax,’%15.11f’),’;’]); out = out + fprintf(fid,format, ’ dt = abs(t-tmax*e);’); out = out + fprintf(fid,format, ’ d = dmax*exp(c(1)*dt.ˆ1.3+c(2)*dt.ˆ1.6);’); fclose(fid); disp([num2str(out),’ bytes of code written to ’,mfil]); end %The model looks quite OK in absolute terms plot(t-K2C,d,’*’,t-K2C,dmax*exp(A*c));
50
C. MATLAB CODE
title(’Density of water at 1 bar’); xlabel(’Temperature [C]’); ylabel(’Density [kg/mˆ3]’); pause; %But the deviation plot shows oscillations (typical for heuristic models) plot(t-K2C,d-dmax*exp(A*c),’o’); title(’Residual density of water at 1 bar’); xlabel(’Temperature [C]’); ylabel(’Density [kg/mˆ3]’); grid;
10. acid base titration curve clear; %Solve the titration problem B+HA = BH(+) + A(-) using direct substitution %of variables to obtain a fourth order polynomial in n(H+), i.e the number %of moles of protons at equilibrium. k1 %k1 %k1 k2 %k2 %k2 k3
= = = = = = =
10ˆ(-4.76); 10ˆ(-2.35); 10ˆ(+2.00); 10ˆ(-4.76); 10ˆ(-3.74); 10ˆ(+1.37); 10ˆ(-14);
% % % % % % %
pKb pKb pKb pKa pKa pKa pKw
NH3 H2O2 NaOH CH3COOH HCOOH HNO3
cb ca e ph
= = = =
0.1; linspace(0,2*cb,1000)’; ones(size(ca)); zeros(size(ca));
c
= [-k1*e, ... k1*k2*e + k1*cb + k3, ... k1*k2*ca + k1*k3 - k1*k2*cb - k2*k3, ... -k2*k3*ca - k3*k3 - k1*k2*k3, ... k3*k3*k2*e];
% molar concentration of base % moles of acid added % unity vector with same shape as n % negative log10(molar H+ concentration) % % % % %
4th 3rd 2nd 1st 0th
order order order order order
coefficient coefficient coefficient coefficient coefficient
%Solve fourth order polynomial repeatedly (i.e. all titration points) for k=1:max(size(ca)) x = roots(c(k,:)); ph(k) =-log10(-max(x(find(x 1.0; l=1.0; x=z; y=0.0*e; end if l < 0.0; l=0.0; y=z; x=0.0*e; end return
22. diffusion function dummy
end end end end end
56
C. MATLAB CODE
clear all close all % Solution of the differential equation with no reaction on the surface D zeta = [0 1]; % Starting value for zeta % The starting values of gamma is chosen to satisfy the boundary conditio% ns given for the problem. Here with a better starting value, the numeri% cal solution could be closer to the analytical. gamma = [1 -0.26]; % Starting value for gamma and its derivative [a,b] = ode23(@equations,zeta,gamma); % Solving the differential equation plot(a,b(:,1),’:’) hold on % Solution of the differential equation with reaction on the surface D zeta = [0 1]; % starting value for zeta gamma = [1 -1.1]; % Starting value for gamma and its derivative [a,b] = ode23(@equations,zeta,gamma); %solving the differential equation plot(a,b(:,1),’-.’) % To compare the numeric solution with the analytical the analytical solu% tion is found zetad = [0:.001:1]; kodab = 0.25; l = 1; th = sqrt(kodab*lˆ2); % Analytical solution with no reaction on surface D g1 = (cosh(th).*cosh(th.*zetad) - sinh(th).*sinh(th.*zetad))./cosh(th); plot(zetad,g1,’-.g’) % Analytical solution with reaction on surface D g2 = (sinh(th).*cosh(th.*zetad)-cosh(th).*sinh(th.*zetad))./sinh(th); plot(zetad,g2,’:m’) legend(’No reaction on D, numeric sol’,’No reaction on D, analytic sol’,... ’Reaction on D analytic sol’,’Reaction on D numeric sol’) xlabel(’\zeta’) ylabel(’\Gamma’) hold off % Function containing the equations to be solved by the ODE solver function d = equations(z,g) kodab = 0.25; l = 1; th = sqrt(kodab*lˆ2); dz = g(2); ddz = thˆ2*g(1); d = [dz;ddz];
23. PITOT TUBE
57
23. pitot tube clear all close all %Initial g R D Ptot Tg Mgas rholiq Cp
data = 9.8065; = 8.31453; = 1.6; = 1.01325e5; = 273.15 + 110; = 28; = 850; = 1;
% m/sˆ2 % J/(mol K) % pipe diamerter in m % Pa % K % molecular weight g/mol % kg/mˆ3 % assume incompressible flow
%Velocity profiles North-South and West-East hNS = [4.7 10.7 18.3 20.5 20.5 23.3 29.6 20.4 16.2 11.8]; hEW = [2.1 8.6 15.4 16.2 21.3 21.3 20.5 16.8 13.3 2.2];
% North-South % East-West
%Now we calculate the velocity from the the measured heights. In order to %do this, we first need to know the radial position of the measurement. We %know there are five concentric rings, with the same area. N = 5; n = [1 2 3 4 5]; r = (D/2)*sqrt((2*n-1)/(2*N)); % position of the area center in each ring %In order to plot the velocity profiles, we need an axis from wall to wall. z = [fliplr(D/2-r) D/2+r]; %Next we need the preassure drop delpNS = hNS*rholiq*g/1000; delpEW = hEW*rholiq*g/1000; rhogas = Ptot*Mgas/(R*Tg*1000); vNS = Cp*sqrt(2*delpNS/rhogas); vEW = Cp*sqrt(2*delpEW/rhogas); %We add vNSw vEWw z vmid z1
the boundary conditions = [0 vNS 0]; = [0 vEW 0]; = [0 z 1.6]; = (vNSw+vEWw)./2; % Calculate the average velocity = [0:D/30:D]; % Adding a few extra points gives a smooth plot
%Do polynomial approximation p2 = polyfit(z,vmid,2); p4 = polyfit(z,vmid,4); sp = spline(z,vmid); t2 = polyval(p2,z1); t4 = polyval(p4,z1); fsp = ppval(z1,sp); plot(z,vmid,’*’,z1,t2) title(’2nd degree polynomial’) ylabel(’Average velocity, m/s’)
% %
2nd degree polynomial 4th degree polynomial % spline approximation
58
C. MATLAB CODE
xlabel(’Distance from left wall, m’) axis([min(z),max(z),0,30]) legend(’Datapoints’,’Fitted profile’) pause plot(z,vmid,’*’,z1,t4) title(’4th degree polynomial’) ylabel(’Average velocity, m/s’) xlabel(’Distance from left wall, m’) axis([min(z),max(z),0,30]) legend(’Datapoints’,’Fitted profile’) pause plot(z,vmid,’*’,z1,fsp) title(’Spline approximation’) ylabel(’Average velocity, m/s’) xlabel(’Distance from left wall, m’) axis([min(z),max(z),0,30]) legend(’Datapoints’,’Fitted profile’) %Compute the volumetric flow in mˆ3/h for the different cases. Q_sp = num2str(round(quad(@pitot_integrand,0,D,[],[],sp)*3600)); Q_p2 = num2str(round(quad(@pitot_integrand,0,D,[],[],p2)*3600)); Q_p4 = num2str(round(quad(@pitot_integrand,0,D,[],[],p4)*3600)); disp([’Volumetric flow (cubic spline) : ’,Q_sp,’ mˆ3/h’]) disp([’Volumetric flow (2nd order polynomial): ’,Q_p2,’ mˆ3/h’]) disp([’Volumetric flow (4th order polynomial): ’,Q_p4,’ mˆ3/h’])
24. pitot integrand function f = pitot_integrand(r,p) %Function to calculate the integrand of the pitot-tube experiment. % % p = transferred polynomial coefficients for the velocity % r = The position in the tube. % %The velocity is calculated from the polynomial coefficients. Since spline %and polyfit uses different formats, we need to do a test and choose the %appropriate function. if isstruct(p) == 1 v = ppval(r,p); else v = polyval(p,r); end f = pi.*r.*v./2;
25. mingibb %Equilibrium calculation n = minGibb(n0,t,p,m0,A) at a given temperature, %pressure and total composition in ideal mixture phases. % %n0 = initial mole number vector [mol] %t = temperature [K]
26. CSTR PROCESS CONTROL
%p %m0 %A %n
= = = =
59
pressure [Pa] standard chemical potential (ideal gas at T) formula matrix (atoms x substances) final mole number vector [mol]
function[n] = minGibb(n0,t,p,m0,A) %Parameters and physical quantities r = 8.31453; p0 = 1e5; tol = 1e-6; maxiter = 100; maxstep = 0.9; epx = 1e-6; [nc,ns] = size(A);
% universal gas constant % standard state pressure % convergence tolerance % maximum number of iterations % maximum relative step length % arbitrarily small mole fraction % number of atoms and substance
%Initialization n = n0; i = find(n==0); n(i) = zeros(length(i),1) + sum(n)*epx; e = ones(ns,1); %Equilibrium calculation for iter=1:maxiter m = m0 + r*t*log(p/p0*n/sum(n)); D = diag(n)/(r*t); lhs = [A*D*A’, A*n; (A*n)’, 0]; rhs = [A*D*m-A*(n-n0); n’*m]; x = inv(lhs)*rhs; dn =-D*(m-A’*x(1:nc)) + n*x(nc+1); step =-maxstep/min([-maxstep,min(dn./n)]); n = n + step*dn; if max(abs(dn./n))0); A = A(i,:); b = {name{i}}’;
% find non-zero rows in matrix A % shrink matrix A to include non-zero rows only % shrink the element list accordingly
%Recursive unpacking of input argument list function [out] = unpack(in); out = {}; % empty cell array for i=1:length(in); % do for all members of the list if (iscell(in{i})) % check if this is a new cell tmp = unpack(in{i}); % recursive unpacking out = {out{:},tmp{:}}; % augment output list else % out = {out{:},in{i}}; % augment output list
66
C. MATLAB CODE
end end
32. get formula vector %Adds stoichiometric coefficients for a specified chemical species using %recursive string parsing.Eg [s,b]=get_formula_vector(’(CH3(CH2)2COOH)1.5’ %,[0 0 0],{’C’,’H’,’O’},1) returns s=’’ and b=[6 12 3]. The chemical ele%ments need not be specified in any particular order, but their order must %coincide with the stoichiometric coefficients also specified in the input % %Author : Tore Haug-Warberg %Version : March 10 2000 (THW) % %function [s,b] = get_formula_vector(s,b,name,factor) % % s = Chemical formula [string]. % b = Stoichiometric coefficients [vector]. % name = Recognized formula symbols [cell array]. % factor = External multiplier. % function [s,b] = get_formula_vector(s,b,name,factor) coef sym
= ’’; = ’’;
% initialize stoichiometric coefficient % initialize chemical symbol
while not(isempty(s)) % continue while string is non-empty next = s(end); % pick next token from end of string s = s(1:end-1); % decrement the formula string if isletter(next) % token is a letter a-z or A-Z sym = strcat(next,sym); % build a chemical symbol (He, Mg, etc.) i = strmatch(sym,name,’exact’); % test against known symbols if any(i) % SYM is a recognized symbol b(i) = b(i) + factor*stoichiometry(coef); % increment stoich. coeff coef = ’’; % reset the stoichiometric coefficient sym = ’’; % reset the chemical symbol end % elseif isnumber(next) % token is a period or a number 0-9 coef = strcat(next,coef); % build a stoichiometric coefficient sym = emptystring(sym); % test that SYM is empty elseif isright(next) % token is a right paranthesis ) [s,b] = get_formula_vector(s,b,name, ... % call myself recursively factor*stoichiometry(coef)); % increase premultiplic. factor coef = ’’; % reset the stoichiometric coefficient sym = emptystring(sym); % test that SYM is empty elseif isleft(next) % token a left paranthesis ( sym = emptystring(sym); % test that SYM is empty return; % return (from recursive call only) end % end % sym = emptystring(sym);
% test that SYM is empty
33. GREENHOUSE GASES FROM HYSYS
67
%Verify that input string is empty function [s] = emptystring(s) if (not(isempty(s))) disp([’Unrecognized string: ’,s]); end sym = ’’; %Verify that input string is a period or a number in the range 0-9 function [i] = isnumber(s) i = or(and(ge(abs(s),48),le(abs(s),57)),eq(abs(s),46)); %Verify that input string is a left paranthesis ( function [i] = isleft(s) i = eq(abs(s),40); %Verify that input string is a right paranthesis ) function [i] = isright(s) i = eq(abs(s),41); %Convert input string to number (empty input string is treated as 1) function [n] = stoichiometry(s) if isempty(s) n = 1; else n = str2num(s); end
33. greenhouse gases from HYSYS clear all warning(’off’)
% clear work space % avoid warning when the while loop terminates
component = {’Methane’,’Ethane’,’Propane’,’n-Butane’,’n-Pentane’}; % names cnum = [1 2 3 4 5]; % Relative amount of carbon in each component
co2 co2{1,1} co2{1,2} fid t c st
= = = = = = =
cell(4,2); ’Stream’; ’Co2 equivalent’; fopen(’..\data\HYSYS_report.txt’); 1; 1; ’’;
% Read file into one long string. while t>0; t = fgets(fid); st = strcat(st,t); end fclose(’all’); % close file a = regexp(st,’(Material Stream:)’); % find start position of the streams a(end+1) = length(st); % add end positions of the string to a vector for i=1:length(a)-1
68
C. MATLAB CODE
stream = st(a(i):a(i+1)); % Look through the string one stream at a time if ˜isempty(regexp(stream,’Material Stream: V’)) % Find wanted data [tmp,tmp1] = regexp(stream,’(Overall Phase).*(Vapour Phase)’); c = c + 1; co2{c,2}(1) = 0; % initialize the container for CO2 equivalents vap = stream(tmp:tmp1); % copy the interesting part [tb,te] = regexp(vap,’Total ,\d*\.\d*’); % find the total stream tmp2 = vap(tb:te); [tb1,te1] = regexp(tmp2,’\d*\.\d*’); % pick out the numbers total = str2num(tmp2(tb1:te1)); % convert from text to numbers for j=1:length(component) % find the position of each component, and take out the % amount from the string. afterward the CO2 equivalent is % calculated and added to the container. [start,stop] = regexp(vap,strcat(component{j},’,\d*\.\d*’)); comp = vap(start:stop); [start1,stop1] = regexp(comp,’\d+\.\d+’); co2{c,2}(1) = co2{c,2}(1) + ... str2num(comp(start1:stop1))*cnum(j)/total*100; co2{c,1} = str2num(stream(19)); end else % do nothing, we are only seeking vapour data end end disp(co2);
%display the final result
APPENDIX D
Ruby code 1. greenhouse gases from HYSYS #read output file and remove end-of-line character f = File.open(’..\data\HYSYS_report.txt’).read.gsub!(/\n/,’’) #Split file into sections of stream data. Remove non-vapour streams arr = f.split(/(?=Material Stream: V)/).each{|i| i.gsub!(/Material Stream: [ˆV].*/,’’) } #Create hash with key="component name" and value="relative amount of C" co2 = {"Methane",1.0,"Ethane",2.0,"Propane",3.0, "n-Butane",4.0,"n-Pentane",5.0} #Create empty Hash to store the final result. Default flow is zero. hsh = Hash.new(0.0) #Define some practical regular expressions streams = Regexp.new(’Material Stream: V(\d)’) totflow = Regexp.new(’COMPONENTS,MOLAR.*Total ,(\d*\.\d*).*Vapour Phase’) vapflow = Regexp.new(’COMPONENTS,MOLAR.*Vapour Phase’) cmpflow = Regexp.new(’([a-z]\-[A-Z][a-z]*|[A-Z][a-z]*),(\d*\.\d*)’) #Scan the vapor stream sections of the output file arr.each{|i| n = i.scan(streams).to_s # vapor stream number t = i.scan(totflow).to_s.to_f # total stream flow i.scan(vapflow).to_s.scan(cmpflow).each{|j| # each component flow hsh[n] += co2[j.first]*j.last.to_f/t*100 # % CO2 equivalent } } #Make a report hsh.each{|n,p|puts "Stream V#{n}: #{p.to_i}% CO2 of total molar flow"}
69
APPENDIX E
Data files 1. pages from water vapor pressure data %PDOUS71 %Douslin, D.R. %J. Chem. Thermodynamics, 3, 187 (1971). % T90(K) P(MPa) 270.651 .0005088 273.150 .0006114 273.160 .0006121 274.150 .0006573 275.150 .0007061 276.149 .0007587 277.149 .0008137 278.149 .0008730 280.649 .0010370 283.148 .0012291 288.147 .0017066 285.647 .0014485 290.646 .0020007 293.145 .0023395 % %PHANA84 %Hanafusa,H.,Tsuchida,T.,Kawai.,Sato,H.,Uematsu,M.,and Watanabe, K. %Proc. 10th ICPS, Moscow 1984, 180;High Temp.-High Pres., 15, 311(1983). % T90(K) P(MPa) 643.174 21.0502000 645.607 21.6715000 645.607 21.6705000 646.106 21.7997000 646.356 21.8645000 646.607 21.9309000 646.607 21.9303000 646.857 21.9974000 % %PKELL85 %Kell, G.S., McLaurin, G.E., and Whalley, E. %Phil. Trans. R. Soc. London, 315A, 235 (1985). % T90(K) P(MPa) 423.133 .4759000 423.134 .4759000 423.133 .4758000 423.108 .4752000 423.112 .4757000 448.114 .8918000 448.114 .8918000 71
72
E. DATA FILES
473.109 473.109 498.107 498.118 523.168 523.168 548.108 548.108 573.111 573.110 598.110 598.111 623.183 623.183 623.109
1.5536000 1.5535000 2.5474000 2.5479000 3.9780000 3.9772000 5.9416000 5.9416000 8.5821000 8.5822000 12.0446000 12.0443000 16.5370000 16.5370000 16.5196000
2. pages from water density 1bar data %Kell, G.S. %J. Chem. Eng. Data, 20(1) 97 (1975). % T90(K) P(MPa) d(kg/m3) 273.150 .101325 999.84260 278.147 .101325 999.96690 283.144 .101325 999.70311 288.141 .101325 999.10362 293.138 .101325 998.20874 298.136 .101325 997.05027 303.134 .101325 995.65331 308.132 .101325 994.03845 313.130 .101325 992.22289 318.128 .101325 990.22074 323.137 .101325 988.03930 328.125 .101325 985.70316 333.134 .101325 983.20192 338.124 .101325 980.56279 343.132 .101325 977.77266 348.124 .101325 974.85613 353.123 .101325 971.80450 358.123 .101325 968.62628 363.123 .101325 965.32527 373.124 .101325 958.36664 383.126 .101325 950.94723 393.127 .101325 943.07942 403.130 .101325 934.76863 413.132 .101325 926.01485 423.134 .101325 916.81308 % %Owen, B.B., White, J.R., and Smith, J.S. %J. Am. Chem. Soc., 78, 3561 (1956). % T90(K) P(MPa) d(kg/m3) 313.130 .101325 992.22250 318.128 .101325 990.21900 323.127 .101325 988.04030 328.125 .101325 985.69720
4. PAGES FROM HYSYS REPORT
333.124 338.124 343.124 348.123 353.123 358.123
.101325 .101325 .101325 .101325 .101325 .101325
983.19870 980.55310 977.76690 974.84530 971.79200 968.61060
3. water viscosity 1bar data %Barrow, G. M., Physical Chemistry, 3rd ed., %McGraw-Hill, 535 (1973). % T(C) P(MPa) visc(kg/m*s) 0 .101325 0.001792 20 .101325 0.001005 40 .101325 0.000656 60 .101325 0.000469 80 .101325 0.000356 100 .101325 0.000284
4. pages from HYSYS report Material Stream: V3,Fluid Package: Basis-1 , ,Property Package: Peng Robinson CONDITIONS ,Overall,Vapour Phase,Liquid Phase,, Vapour / Phase Fraction ,1.0000,1.0000,0.0000,, Temperature: (C),45.00,45.00,45.00,, Pressure: (kPa),3924,3924,3924,, Molar Flow (kgmole/h),42.19,42.19,0.0000,, Mass Flow (kg/h),1223,1223,0.0000,, Std Ideal Liq Vol Flow (m3/h),3.090,3.090,0.0000,, Molar Enthalpy (kJ/kgmole),-8.852e+004,-8.852e+004,-1.179e+005,, Molar Entropy (kJ/kgmole-C),158.3,158.3,114.1,, Heat Flow (kJ/h),-3.735e+006,-3.735e+006,0.0000,, Liq Vol Flow @Std Cond (m3/h),,,0.0000,, COMPOSITION Overall Phase ,Vapour Fraction 1.0000 , COMPONENTS,MOLAR FLOW,MOLE FRACTION,MASS FLOW,MASS FRACTION, LIQUID VOLUME,LIQUID VOLUME , (kgmole/h), , (kg/h), ,FLOW (m3/h),FRACTION Methane,17.7435,0.4206,284.6569,0.2328,0.9508,0.3077 Ethane,13.4946,0.3199,405.7803,0.3319,1.1408,0.3692 Propane,7.8865,0.1869,347.7726,0.2845,0.6864,0.2221 n-Butane,2.6142,0.0620,151.9480,0.1243,0.2605,0.0843 n-Pentane,0.4487,0.0106,32.3749,0.0265,0.0514,0.0166 Total ,42.1875,1.0000 ,1222.5327,1.0000 ,3.0899,1.0000 Vapour Phase,Phase Fraction 1.000 , COMPONENTS,MOLAR FLOW,MOLE FRACTION,MASS FLOW,MASS FRACTION, LIQUID VOLUME,LIQUID VOLUME , (kgmole/h), , (kg/h), ,FLOW (m3/h),FRACTION Methane,17.7435,0.4206,284.6569,0.2328,0.9508,0.3077 Ethane,13.4946,0.3199,405.7803,0.3319,1.1408,0.3692
73
74
E. DATA FILES
Propane,7.8865,0.1869,347.7726,0.2845,0.6864,0.2221 n-Butane,2.6142,0.0620,151.9480,0.1243,0.2605,0.0843 n-Pentane,0.4487,0.0106,32.3749,0.0265,0.0514,0.0166 Total ,42.1875,1.0000 ,1222.5327,1.0000 ,3.0899,1.0000 Liquid Phase,Phase Fraction 0.0000 , COMPONENTS,MOLAR FLOW,MOLE FRACTION,MASS FLOW,MASS FRACTION, LIQUID VOLUME,LIQUID VOLUME , (kgmole/h), , (kg/h), ,FLOW (m3/h),FRACTION Methane,0.0000,0.1091,0.0000,0.0404,0.0000,0.0664 Ethane,0.0000,0.2463,0.0000,0.1710,0.0000,0.2363 Propane,0.0000,0.3223,0.0000,0.3282,0.0000,0.3184 n-Butane,0.0000,0.2364,0.0000,0.3172,0.0000,0.2673 n-Pentane,0.0000,0.0859,0.0000,0.1431,0.0000,0.1117 Total ,0.0000,1.0000 ,0.0000,1.0000 ,0.0000,1.0000