Académique Documents
Professionnel Documents
Culture Documents
Tore Haug-Warberg
D C E, NTNU
E-mail address: haugwarb@nt.ntnu.no
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 3
1. Homogeneous containers (vectors and matrices) 3
2. Heterogeneous containers (lists) 6
3. User-defined data types (structs) 7
4. Input/output issues 8
5. Tricks of the trade 8
Chapter 3. How to solve equations 9
1. Linear equations 9
2. Independent reactions 12
3. Linear parameter estimation 12
4. Polynomials 14
5. Single non-linear equations 15
6. Sets of many non-linear equations 16
Chapter 4. Write your own functions 19
1. The function concept 19
2. Vector functions 19
3. Iterative functions (algorithms) 20
4. Recursion — good, evil or maybe bad? 20
Chapter 5. Functionals or function(function)s 23
1. Integration 23
2. Ordinary differential equations 23
3. Unconstrained optimization 25
4. Optimization with constraints 25
5. Process control 26
Chapter 6. String parsing 29
1. Chemical formula arithmetics 29
2. Cool stuff (regular expressions) 30
Appendix A. Language elements 33
Appendix B. Examples 37
Appendix C. Matlab code 39
1. randolph 39
2. octane 41
3. figure 2 8 42
iii
iv CONTENTS
4. partialinv 43
5. fertilizer balance 43
6. acid base reaction matrix 45
7. water viscosity 1bar fit 46
8. water vapor pressure fit 47
9. water density 1bar fit 49
10. acid base titration curve 50
11. colebrook 51
12. pressure drop at fixed flow 51
13. friction and reynold 52
14. flow at fixed pressure drop 52
15. laminar 53
16. colebrook vs laminar 53
17. chon 54
18. water viscosity 1bar 54
19. water vapor pressure 54
20. water density 1bar 54
21. rachford rice 55
22. diffusion 55
23. pitot tube 57
24. pitot integrand 58
25. mingibb 58
26. CSTR process control 59
27. CSTR time derivatives 61
28. ODE Jacobian 62
29. mw from formula parser 63
30. mw binop 63
31. make formula matrix 64
32. get formula vector 66
33. greenhouse gases from HYSYS 67
Appendix D. Ruby code 69
1. greenhouse gases from HYSYS 69
Appendix E. Data files 71
1. pages from water vapor pressure data 71
2. pages from water density 1bar data 72
3. water viscosity 1bar data 73
4. pages from HYSYS report 73
List of Tables
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 in-
clined 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 be-
tween 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
Talking (99)
Reading (80)
Writing (25)
Programming (1)
The numbers indicate the percentage of the population that I expect master the sub-
ject 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 cate-
gorize 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 prac-
tical 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 lan-
guage 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 inconsis-
tent 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 pro-
gramming 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 def-
initely 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 de-
clare variables, write expressions of some kind, make assignments to the variables, and
transfer execution control to external procedures∗. External in this context means the pro-
cedure 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).
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 val-
ues 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 ex-
pression 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 exe-
cutes one line at a time. Hence you must make sure that all statements (lines) comes in
the correct order.
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
zero you can represent numbers down to ±2 . Inside the range 2 ,2 you will
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 = [1,2;3,4];
a = [5,6];
a = 3.141592;
N = 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 com-
pact, 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 = 8.31453;
T = 273.15;
N = 7;
v = [0.1:0.1:1.5];
e = ones(size(v))’;
t = T*e;
p = 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 con-
structor [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 indepen-
dent 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 cal-
culating 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 program-
ming 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 = 8.31453;
t = [250:20:350];
N = 7;
v = logspace(-1,1,100)’;
e = ones(size(v));
p = N*R*(e./v)*t;
semilogx(v,p);
xlabel(’Volume mˆ3’);
ylabel(’Pressure Pa’);
6 2. BASIC CONCEPTS
mylist = {’some’,’words’,’in’,’the’,’list’};
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)));
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 par-
ticularly important role in mathematical programs).
CHAPTER 3
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:
98 . We are given two pieces of information (octane number and aro-
matic 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 inver-
sion (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 neg-
ative (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 back-
calculated 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.
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. Some-
times, 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).
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
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 chem-
ical 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:
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 (pos-
sible) 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 ẋ and ẏ be vectors of reactant and
product flows respectively, and A and B the corresponding formula matrices. Make
sure your definitions are compliant to Aẋ = Bẏ. You can then choose to solve either
B−1 Aẋ = ẏ or A−1 Bẏ = ẋ using the partial inversion algorithm from the last example.
F . Nothing really new here, except that you have to specify two coef-
ficient 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 vari-
able, 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?
A- . The Matlab code listed in Appendix C.6 will assist you in get-
ting the reaction stoichiometry right, but traditional hand calculations are perfectly OK.
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 = j ai j (xi )c j , and
for s we get the expression:
2
n
n
s= yi − ai j (xi )c j = (y − A (x) c)T (y − A (x) c)
i=1 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
∂s
n
n
− =2 yi − 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).
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.
∗
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
r = c1 τ + c2 τ1.5 + c3 τ3.0 + c4 τ6.0
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
r is linear in the coefficients c1 − c4 . You can therefore use
standard linear parameter estimation theory if the observed T, p-data are converted to
T r log pr and τ. This yields
τ1 τ1.5 τ31 τ61
.. .. ,
1
A (T ) = ... ..
. . .
τn τn τ3n τ6n
1.5
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
1.3 1.6
found in water density 1bar data.txt see Appendix E.2. The definitions of τ and ρmax
are:
τ=
T
− 273.15 − 3.98
[K]
−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 rea-
sons 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 dis-
cussed 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.
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:
C BH + COH − (x + y + z) y 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).
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
compared with Colebrook’s function in Ex.12, i.e. f = Re 64
. 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.
2. Vector functions
By vector function I mean a function that calculates more than one output value. Typ-
ically, 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.
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.
19
20 4. WRITE YOUR OWN FUNCTIONS
§ 19 Make a Matlab function that calculates ρwater = ρmax ec1 τ +c2 τ for an ar-
1.3 1.6
bitrary temperature matrix t. The function syntax is water density 1bar(t) and the
parameters are c = [0.00003932621, -0.00003868077], see also Ex.10.
R-R. This problem is ideally suited for Newton’s method because it turns
out that the merit function is monotonically decreasing:
∂f
1 − Ki
2
=− zi <0
∂α α + (1 − α) Ki
The implementation is therefore straight forward, see Appendix C.21.
n mod (F n , 1) time[s]
1 0.8 0.000
.. .. ..
. . .
14 0.2 0.020
18 0.6 0.171
22 0.0 1.101
26 0.4 7.500
30 0.8 51.38
breaks, but because things are less transparent when using function calls such ill-defined
recursiveness can be hard to debug.
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:
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
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.
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 alge-
braic 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 homoge-
nous reaction A + B → AB. If the mixture is treated as a binary solution, ignoring
AB, the mass balance can be written:
d cA
DAB − 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
d2 Γ
(5.1) 2
− φ2 Γ = 0
dζ
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 dif-
ferential 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.
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, mecha-
nisms, 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 manip-
ulated 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 engineer-
ing 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 per-
formance 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 correspond-
ing 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 T − T◦
E 1 1
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
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).
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.
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.
In order to retain the data of interest, regular expressions are very powerful. Table 6.2
shows a list of the most common 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 re-
ported 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 ex-
pressions 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
33
34 A. LANGUAGE ELEMENTS
exp exponentiation
log natural logarithm
sin sine
cos cosine
sqrt square root
Examples
In Matlab a command can be entered at the system prompt without any left assigment.
It will then return the numerical value of the operation in the default variable ans (so there
is an assigment after all). Some trivial examples follow:
>> 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:
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 com-
mand 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 cal-
culations! 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.
persistent x0 o p q;
if (nargin==1)
if (n<1)
disp(’Your seed number must be >= 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 41
2. octane
clear;
format short;
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;
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;
3. figure 2 8
clear;
I = eye(2,2);
O = zeros(2,2);
a = [2 , 1];
s1 = [99, -1];
s2 = [10,-90];
o = O(1,:);
e = I(1,:);
s3 = [5,6]; % stream 3
s4 = [7,8]; % stream 4
n3 = sum(X(s3,:),1); % total flow of stream 3
n4 = sum(X(s4,:),1); % total flow of stream 4
Q = X(s3(2),:).ˆ2./(X(s3(1),:).*n3); % equilibrium quotient
loglog(n4,Q,’r’);
5. FERTILIZER BALANCE 43
loglog(n4(i),Q(i),’g’);
legend(’Q>K’,’Q<K’);
hold off;
disp(round(xp-1568.44*xh));
4. partialinv
%Purpose : Solve the partial inversion problem Ax = b where some of the
% elements in b are unknown, while an equal number of elements in
% x are known (a total of rank(A) elements in x and b must be
% known all over)
%Author : Tore Haug-Warberg
%Date : October 16 1999
%Syntax : [x,b] = partialinv(A,x,b)
%Input : A = coefficient matrix
% x = left hand side vector
% b = right hand side vector
%Output : x = updated left hand side vector
% b = updated right hand side vector
%External: eye inv isnan not size
i = isnan(x);
j = isnan(b);
I = eye(size(A));
c = inv([I(not(i),:);A(not(j),:)])*[x(not(i));b(not(j))];
x(i) = I(i,:)*c;
b(j) = A(j,:)*c;
5. fertilizer balance
clear;
0 0 2 0 0 0]; ... % P
%Molecular weights
w = [14.0067 1.00797 15.9994 12.01115 40.08, 30.9738]; % atoms
wa = w*A; % reactants
wb = w*B; % products
x = zeros(size(wa))’;
y = zeros(size(wb))’;
%Let’s first put up the formula matrix (identical to the atom matrix if
%the B, H, A, OH symbols are interpreted differently).
disp(’Formula matrix:’)
disp(A);
pause;
tmp = A(:,5);
A(:,5) = A(:,4);
A(:,4) = tmp;
tmp = name{5};
name{5}= name{4};
name{4}= tmp;
disp([’Swap components ’,name{4},’ and ’,name{5}])
disp(A);
pause;
N(:,1) = [A(:,5);-1;0;0];
disp(’First set of reaction coefficients:’)
disp([char(name),abs(zeros(length(name),3)),num2str(N)]);
pause;
N(:,2) = [A(:,6);0;-1;0];
disp(’Second set of reaction coefficients:’)
disp([char(name),abs(zeros(length(name),3)),num2str(N)]);
pause;
N(:,3) = [A(:,7);0;0;-1];
disp(’Third set of reaction coefficients:’)
disp([char(name),abs(zeros(length(name),3)),num2str(N)]);
pause;
N(:,2) = -N(:,2);
N(:,1) = -N(:,1);
disp(’Change direction of reaction 1 and 2:’)
disp([char(name),abs(zeros(length(name),3)),num2str(N)]);
K2C = 273.15;
%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).
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;
%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;
%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.
plot(ca,ph);
title(’Titration curve for NH3 - CH3COOH’);
xlabel(’Acid added [mol]’);
ylabel(’pH’);
hold on;
grid;
%Find inflexion points (quite simple because the x-axis values are mono-
%tonic and equidistant)
12. PRESSURE DROP AT FIXED FLOW 51
11. colebrook
function [r] = colebrook(lnf,lnRe,eod)
r = lnf/2 + log(-2*log10(eod/3.7+2.51./(exp(lnf/2).*exp(lnRe))));
lnf = fzero(@colebrook,lnf,opt,lnRe,eod);
disp([’ ’]);
disp([’Case I’]);
disp([’Diameter : ’,num2str(D ,4),’ [m]’]);
disp([’Pressure drop : ’,num2str(hs,4), ...
’ [m H2O at ’,num2str(round(T-273.15)),’ C]’]);
disp([’Pressure drop : ’,num2str(dp,4),’ [bar]’]);
disp([’ ’]);
disp([’Press any key to continue’]);
pause;
lnf = fzero(@colebrook,lnf,opt,lnRe,eod);
disp([’ ’]);
disp([’Case II’]);
52 C. MATLAB CODE
lnRe = x(:,1);
lnf = x(:,2);
r = zeros(size(x));
dp = s.dp;
D = s.D;
rho = s.rho;
L = s.L;
eod = s.eod;
mu = s.mu;
x = fsolve(@friction_and_reynold,[lnRe,lnf],opt,@colebrook,s);% solve
Q = 60*pi*exp(x(:,1)).*s.mu.*s.D./(4*s.rho); % flow rate [mˆ3/min]
f = exp(x(:,2)); % friction factor
disp([’ ’]);
disp([’Case I’]);
disp([’Diameter : ’,num2str(s.D ,4),’ [m]’]);
disp([’Pressure drop : ’,num2str(s.dp,4),’ [bar]’]);
disp([’Friction factor : ’,num2str(f ,4),’ [-]’]);
disp([’Flow rate : ’,num2str(Q ,4),’ [mˆ3/min]’]);
disp([’ ’]);
disp([’Press any key to continue’]);
pause;
16. COLEBROOK VS LAMINAR 53
x = fsolve(@friction_and_reynold,[lnRe,lnf],opt,@colebrook,s); % solve
Q = 60*pi*exp(x(:,1)).*s.mu.*s.D./(4*s.rho); % flow rate [mˆ3/min]
f = exp(x(:,2)); % friction factor
disp([’ ’]);
disp([’Case II’]);
disp([’Diameter : ’,num2str(s.D ,4),’ [m]’]);
disp([’Pressure drop : ’,num2str(s.dp,4),’ [bar]’]);
disp([’Friction factor : ’,num2str(f ,4), ’[-]’]);
disp([’Flow rate : ’,num2str(Q ,4),’ [mˆ3/min]’]);
15. laminar
function [r] = laminar(lnf,lnRe,dummy)
r = lnf + lnRe - log(64);
x = fsolve(@friction_and_reynold,[lnRe,lnf],opt,@laminar,s); % solve
Rel = exp(x(:,1)); % laminar Reynold number
Ql = 60*pi*Rel.*s.mu.*s.D./(4*s.rho); % laminar flow rate [mˆ3/min]
fl = exp(x(:,2)); % laminar friction factor
x = fsolve(@friction_and_reynold,[lnRe,lnf],opt,@colebrook,s); % solve
Ret = exp(x(:,1)); % turbulent Reynold number
Qt = 60*pi*exp(x(:,1)).*s.mu.*s.D./(4*s.rho); % flow rate [mˆ3/min]
ft = exp(x(:,2)); % turbulent friction factor
loglog(s.D,Ql,’b’,s.D,Qt,’r’);
title(’Turbulent & laminar flow at constant \Delta P’);
xlabel(’Pipe diameter [m]’);
ylabel(’Flow rate [mˆ3/min]’);
legend(’Laminar’,’Turbulent’);
grid;
disp(’ ’)
54 C. MATLAB CODE
loglog(s.D,Rel,’b’,s.D,Ret,’r’)
title(’Turbulent & laminar Re at constant \Delta P’);
xlabel(’Pipe diameter [m]’);
ylabel(’Re’);
legend(’Laminar’,’Turbulent’);
grid;
pause;
loglog(Rel,fl,’b’,Ret,ft,’r’);
title(’Turbulent & laminar Fanning friction at constant \Delta P’);
xlabel(’Re’);
ylabel(’Friction factor f’);
legend(’Laminar’,’Turbulent’);
grid;
pause;
17. chon
%Calculates molecular weight of CHON-compounds.
function [mw] = chon(x,y,z,w)
mw = x*12.01115 + y*1.00797 + z*15.9994 + w*14.0067;
e = ones(size(t));
tmax = 277.13000000000;
dmax = 999.97490000000;
dt = abs(t-tmax*e);
d = dmax*exp(c(1)*dt.ˆ1.3+c(2)*dt.ˆ1.6);
%Initializations
tol = 1.e-6; %Convergence tolerance
e = ones(length(k),1); %Unity vector
l = 0.5; %Initial estimate of liquid fraction
dl = 1.0; %Liquid fraction increment
z = z/sum(z); %Normalize feed composition
%Verifications
if length(z)˜= length(k); return; end
if min (z) < 0.0 ; return; end
if min (k) < 0.0 ; return; end
if min (k) > 1.0 ; l=0.0; x=0.0*z; y=z; return; end
if max (k) < 1.0 ; l=1.0; y=0.0*z; x=z; return; end
%Rachford-Rice iteration
while abs(dl) > tol
f = e’*((z.*(e-k))./(l*e+(1-l)*k));
dfdl = -e’*((z.*(e-k).ˆ2)./((l*e+(1-l)*k).ˆ2));
dl = -f/dfdl;
l = l + dl;
end
x = z./(l*e+(1-l)*k);
y = k.*x;
return
22. diffusion
function dummy
56 C. MATLAB CODE
clear all
close all
plot(a,b(:,1),’:’)
hold on
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);
plot(zetad,g1,’-.g’)
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
%Initial data
g = 9.8065; % m/sˆ2
R = 8.31453; % J/(mol K)
D = 1.6; % pipe diamerter in m
Ptot = 1.01325e5; % Pa
Tg = 273.15 + 110; % K
Mgas = 28; % molecular weight g/mol
rholiq = 850; % kg/mˆ3
Cp = 1; % assume incompressible flow
%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];
plot(z,vmid,’*’,z1,t2)
title(’2nd degree polynomial’)
ylabel(’Average velocity, m/s’)
58 C. MATLAB CODE
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 59
%p = pressure [Pa]
%m0 = standard chemical potential (ideal gas at T)
%A = formula matrix (atoms x substances)
%n = final mole number vector [mol]
function[n] = minGibb(n0,t,p,m0,A)
%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))<tol; return; end
end
%Not converged
n = NaN*n;
return
t = [0 100];
[t0,y0] = ode15s(func,t,x0,[],u0,d0); % steady-state check
figure(1)
60 C. MATLAB CODE
subplot(2,1,1);
plot(t0,y0(:,1)), grid; title(’Steady-state behavior of the system’);
ylabel(’C_a [kmol/mˆ3]’);
subplot(2,1,2);
plot(t0,y0(:,2)), grid; xlabel(’t [s]’); ylabel(’T [K]’)
figure(2)
subplot(4,2,1); plot(t1,y1(:,1)), ylabel(’T1 [K]’), grid; title(’ca [kmol/mˆ3]’);
subplot(4,2,2); plot(t1,y1(:,2)), grid; title(’T [K]’);
subplot(4,2,3); plot(t2,y2(:,1)), ylabel(’caf [kmol/mˆ3]’), grid;
subplot(4,2,4); plot(t2,y2(:,2)), grid;
subplot(4,2,5); plot(t3,y3(:,1)), ylabel(’Q [kJ/min]’), grid;
subplot(4,2,6); plot(t3,y3(:,2)), grid;
subplot(4,2,7); plot(t4,y4(:,1)), ylabel(’q [mˆ3/min]’), grid; xlabel(’t [s]’)
subplot(4,2,8); plot(t4,y4(:,2)), grid; xlabel(’t [s]’)
%Linearization
[A,B,E] = ode_jacobian(func,[],x0,u0,d0);
C = eye(2);
D = zeros(2);
F = zeros(2);
disp(’Eigenvalues of A’)
disp(eig(A))
disp(’Size Co, Rank Co’)
disp([size(Co,1), rank(Co)])
disp(’Size Ob, Rank Ob’)
disp([size(Ob,2), rank(Ob)])
Gss = ss(A,B,C,D);
Gdss = ss(A,E,C,D);
G = tf(Gss);
Gd = tf(Gdss);
[num,den] = tfdata(G);
[numd,dend] = tfdata(Gd);
sz = size(G);
i = 1:sz(1);
j = 1:sz(2);
w = logspace(-2,2);
figure(3)
sigma(G,w)
grid
%RGA
sz = size(G);
i = 1:sz(1);
j = 1:sz(2);
w1 = logspace(-3,1,200);
H = freqresp(G,w1);
for k=1:length(w1)
Hinv = inv(H(:,:,k));
RGA(i,j,k) = H(i,j,k).*Hinv’;
end
rga_diag = abs(RGA(1,1,:));
rga_offdiag = abs(RGA(1,2,:));
figure(4)
plot(w1,rga_diag(:),w1,rga_offdiag(:)); grid
xlabel(’Frequency [rad/s]’), ylabel(’Magnitude of the RGA Elements’)
legend(’\Lambda_{11} = \Lambda_{22}’,’\Lambda_{12} = \Lambda_{21}’)
To = 400; % K
V = 4; % reactor volume [m3]
cp = 0.150; % heat capcity [kJ/kg*K]
E = 20000; % activation energy [kJ/kmol]
rho = 1000; % density [kg/m3]
ko = 0.5; % rate constant [minˆ-1]
R = 8.31453; % universal gas constant [kJ/K*kmol]
H = 1875; % reaction enthalpy [kJ/kmol]
ca = x(1); % concentration of A
T = x(2); % temperature
Q = u(1); % heat (input)
q = u(2); % volumetric flow (input)
T1 = d(1); % temperature in (disturbance)
caf = d(2); % concentration (disturbance)
k = ko*exp(-E/R*(1/T-1/To)); % Arrhenius rate
62 C. MATLAB CODE
del = 1.0e-10;
30. mw binop
%Binary operator (x o y) table for molecular
%weight parsing of chemical formulas.
%
%Author : Tore Haug-Warberg
%Version : April 30 2002 (THW)
%
%function [o] = mw_binop(x,y)
%
%x = Left operand [char].
%y = Right operand [char].
%o = Operator [char].
o = ’’;
if (isdigit(x))
if (islower(y)|isupper(y)|isleft(y))
o = ’+’;
end
elseif(islower(x))
if(isdigit(y))
o = ’*’;
elseif(islower(y))
o = ’<multiple_lower_case_letters>’;
elseif(isupper(y)|isleft(y))
o = ’+’;
64 C. MATLAB CODE
end
elseif(isupper(x))
if(isdigit(y))
o = ’*’;
elseif(isupper(y)|isleft(y))
o = ’+’;
end
elseif(isright(x))
if(isdigit(y))
o = ’*’;
elseif(islower(y))
o = ’<name_starts_with_lower_case>’;
elseif(isupper(y)|isleft(y))
o = ’+’;
end
elseif(isleft(x))
if(isdigit(y))
o = ’<name_starts_with_digit>’;
elseif(islower(y))
o = ’<name_starts_with_lower_case>’;
elseif(isright(y))
o = ’<empty_name>’;
end
end
%make_formula_matrix({’CH3OH’,{’H2’,’O2’,’H2O’},’CO’,’CO2’});
%
%Note, however, that the output variables do not mimic the input cell
%structure, i.e. A will be a straightforward matrix and b will be a list.
%
%Author : Tore Haug-Warberg
%Version : April 30 2002 (THW)
%
%function [A,b] = make_formula_matrix(arg1,arg2,...,argN)
%
% A = Formula matrix [elements x species].
% b = Element name cell array [elements].
% arg1 = species formula (or cell array)
% arg2 = species formula (or cell array)
% ...
% argN = species formula (or cell array)
persistent name;
if (isempty(name))
name = {’H’ ,’He’,’Li’,’Be’,’B’ ,’C’ ,’N’ ,’O’ ,’F’ ,’Ne’,’Na’,’Mg’,...
’Al’,’Si’,’P’ ,’S’ ,’Cl’,’Ar’,’K’ ,’Ca’,’Sc’,’Ti’,’V’ ,’Cr’,...
’Mn’,’Fe’,’Co’,’Ni’,’Cu’,’Zn’,’Ga’,’Ge’,’As’,’Se’,’Br’,’Kr’,...
’Rb’,’Sr’,’Y’ ,’Zr’,’Nb’,’Mo’,’Tc’,’Ru’,’Rh’,’Pd’,’Ag’,’Cd’,...
’In’,’Sn’,’Sb’,’Te’,’I’ ,’Xe’,’Cs’,’Ba’,’La’,’Ce’,’Pr’,’Nd’,...
’Pm’,’Sm’,’Eu’,’Gd’,’Tb’,’Dy’,’Ho’,’Er’,’Tm’,’Yb’,’Lu’,’Hf’,...
’Ta’,’W’ ,’Re’,’Os’,’Ir’,’Pt’,’Au’,’Hg’,’Tl’,’Pb’,’Bi’,’Po’,...
’At’,’Rn’,’Fr’,’Ra’,’Ac’,’Th’,’Pa’,’U’ ,’Np’,’Pu’,’Am’,’Cm’,...
’Bk’,’Cf’,’Es’,’Fm’,’Md’,’No’,’Lr’}’;
end
for i=1:length(varargin)
[s,A(:,i)] = get_formula_vector(varargin{i},A(:,i),name,1.0);
end
end
end
co2 = cell(4,2);
co2{1,1} = ’Stream’;
co2{1,2} = ’Co2 equivalent’;
fid = fopen(’..\data\HYSYS_report.txt’);
t = 1;
c = 1;
st = ’’;
for i=1:length(a)-1
68 C. MATLAB CODE
Ruby code
#Create empty Hash to store the final result. Default flow is zero.
hsh = Hash.new(0.0)
#Make a report
hsh.each{|n,p|puts "Stream V#{n}: #{p.to_i}% CO2 of total molar flow"}
69
APPENDIX E
Data files
71
72 E. DATA FILES
473.109 1.5536000
473.109 1.5535000
498.107 2.5474000
498.118 2.5479000
523.168 3.9780000
523.168 3.9772000
548.108 5.9416000
548.108 5.9416000
573.111 8.5821000
573.110 8.5822000
598.110 12.0446000
598.111 12.0443000
623.183 16.5370000
623.183 16.5370000
623.109 16.5196000
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