Neq Sim User Manual
Neq Sim User Manual
1
Volume
NeqSim
USERSGUIDE
NORWEGIAN UNIVERSITY OF TECHNOLOGY AND SCIENCE
1
Chapter
1
D E S I G N C U S T O M I Z A T I O N
Introduction to NeqSim
NeqSim is an open source project for
thermodynamic and fluid-mechanic simulations.
With NeqSim you can simulate the most common
unit operations you find in the petroleum industry.
Users are invited to contribute with their own
modules/models to the code.
History of NeqSim
The development of NeqSim started in 1998. It was implemented in an object-
oriented language (Java@) – and it can easily be extended with new modules
and mathematical models. At the moment NeqSim is based on six modules
Thermodynamic module
Statistical module
GUI module
D E S I G N C U S T O M I Z A T I O N
The modules are independent – so that you could use one ore more of them in
your own programming project. All these modules are described in this manual.
The intention
The chapters in the manual are given in
The main intention of the manual is the order:…
to give a fast introduction to
NeqSim
Installation of NeqSim
The installation of NeqSim is done automatically when downloading it from the
NeqSim homepage (www.stud.ntnu.no/neqsim/neqsim.htm). The Matlab
toolbox must be added to the Matlab search-path if you want to use the NeqSim
toolbox with Matlab. You will need Matlab 6.0 or higher – with support for
Java2.
3
D E S I G N C U S T O M I Z A T I O N
2
Chapter
NeqSim uses some open source tools to do the graphical data processing. These
tools are:
4
D E S I G N C U S T O M I Z A T I O N
on the main toolbar. If the Python interpreter finds any logical errors in the
script – an error message box will pop up – giving the error message from the
interpreter (figure 2).
5
D E S I G N C U S T O M I Z A T I O N
The text editor (Jext) is a powerful text editor – developed as an open source
project with many developers contributing. More information about this text
editor (and new versions) can be found at the web page http://www.jext.org.
The Jext text editor can easily be extended with plugins – and many such
plugins are available from the Jext homepage.
With the View menu you can select witch toolsbars you want to see in the GUI
and you can also open the VisAd Calculator.
6
D E S I G N C U S T O M I Z A T I O N
The toolbars will help you to generate scripts automaticly. Using the toolbars
you should be able to create fully functional scripts – without having to code
anything by hand.
When you click this button the dialog box in the figure below will pop up – and
you are able to select components and the thermodynamic model you want to
use.
After selecting the components and the thermodynamic model – you click the
OK button – and the NeqSim script will be generated automatically. Such a
script is given in the textbox below.
The second button on the thermodynamic toolbar – will help you to generate
flash calculation scripts.
7
D E S I G N C U S T O M I Z A T I O N
When you click this button – the following dialog box will pop up:
When you have selected the type of flash calculation you want to do – you click
the OK button – and the NeqSim script will be generated automatically. The
resulting script will be
system = thermo('srk', 273.15, 1.01325)
addComponent(system,'methane',1.0)
addComponent(system,'water',1.0)
system.setMixingRule(1)
TPflash(system,1)
You can run this script by pressing the “run” button on the main frame. The
results will be displayed as dialogbox (see figure below).
All the buttons on the toolbars will help you to generate specific scripts to
performe thermodynamic-, fluid mechanic- and process simulations.
8
D E S I G N C U S T O M I Z A T I O N
9
3
Chapter Chapter
T
he scripting language used in NeqSim – is Python (www.python.org).
Python is an interpreted, easy, powerful and object oriented language.
The python interpreter used in NeqSim is Jython – a interpreter written
in Java. In this way it is easy to use your exicting Java librarys in Python – you
are even able to inherit from your Java objects in your Python scripts.
The Python interpreter and the extensive standard library are freely
available in source or binary form for all major platforms from the Python
web site, http://www.python.org, and can be freely distributed. The same
site also contains distributions of and pointers to many free third party
Python modules, programs and tools, and additional documentation.
10
An Informal Introduction to Python
In the following examples, input and output are distinguished by the
presence or absence of prompts (">>> " and "... "): to repeat the example,
you must type everything after the prompt, when the prompt appears; lines
that do not begin with a prompt are output from the interpreter. Note that a
secondary prompt on a line by itself in an example means you must type a
blank line; this is used to end a multi-line command.
Many of the examples in this manual, even those entered at the interactive
prompt, include comments. Comments in Python start with the hash
character, "#", and extend to the end of the physical line. A comment may
appear at the start of a line or following whitespace or code, but not within
a string literal. A hash character within a string literal is just a hash
character.
Some examples:
# this is the first comment
SPAM = 1 # and this is the second comment
# ... and now a third!
STRING = "# This is not a comment."
Numbers
The interpreter acts as a simple calculator: you can type an expression at it
and it will write the value. Expression syntax is straightforward: the
operators +, -, * and / work just like in most other languages (for example,
Pascal or C); parentheses can be used for grouping. For example:
>>> 2+2
4
>>> # This is a comment
... 2+2
4
>>> 2+2 # and a comment on the same line as code
4
>>> (50-5*6)/4
5
>>> # Integer division returns the floor:
... 7/3
2
>>> 7/-3
-3
Like in C, the equal sign ("=") is used to assign a value to a variable. The
value of an assignment is not written:
>>> width = 20
>>> height = 5*9
>>> width * height
11
900
Strings
Besides numbers, Python can also manipulate strings, which can be
expressed in several ways. They can be enclosed in single quotes or double
quotes:
>>> 'spam eggs'
'spam eggs'
>>> 'doesn\'t'
"doesn't"
>>> "doesn't"
"doesn't"
>>> '"Yes," he said.'
'"Yes," he said.'
>>> "\"Yes,\" he said."
'"Yes," he said.'
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
Lists
Python knows a number of compound data types, used to group together
other values. The most versatile is the list, which can be written as a list of
comma-separated values (items) between square brackets. List items need
not all have the same type.
>>> a = ['spam', 'eggs', 100, 1234]
>>> a
['spam', 'eggs', 100, 1234]
Like string indices, list indices start at 0, and lists can be sliced,
concatenated and so on:
>>> a[0]
'spam'
>>> a[3]
1234
>>> a[-2]
100
>>> a[1:-1]
['eggs', 100]
>>> a[:2] + ['bacon', 2*2]
['spam', 'eggs', 'bacon', 4]
>>> 3*a[:3] + ['Boe!']
['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boe!']
Unlike strings, which are immutable, it is possible to change individual
elements of a list:
>>> a
['spam', 'eggs', 100, 1234]
>>> a[2] = a[2] + 23
>>> a
['spam', 'eggs', 123, 1234]
Assignment to slices is also possible, and this can even change the size of
the list:
>>> # Replace some items:
... a[0:2] = [1, 12]
>>> a
[1, 12, 123, 1234]
>>> # Remove some:
... a[0:2] = []
12
>>> a
[123, 1234]
>>> # Insert some:
... a[1:1] = ['bletch', 'xyzzy']
>>> a
[123, 'bletch', 'xyzzy', 1234]
>>> a[:0] = a # Insert (a copy of) itself at the beginning
>>> a
[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234]
The built-in function len() also applies to lists:
>>> len(a)
8
It is possible to nest lists (create lists containing other lists), for example:
>>> q = [2, 3]
>>> p = [1, q, 4]
>>> len(p)
3
>>> p[1]
[2, 3]
>>> p[1][0]
2
>>> p[1].append('xtra') # See section 5.1
>>> p
[1, [2, 3, 'xtra'], 4]
>>> q
[2, 3, 'xtra']
Note that in the last example, p[1] and q really refer to the same object!
We'll come back to object semantics later.
if Statements
Perhaps the most well-known statement type is the if statement. For
example:
>>> x = int(raw_input("Please enter a number: "))
>>> if x < 0:
... x=0
... print 'Negative changed to zero'
... elif x == 0:
... print 'Zero'
... elif x == 1:
... print 'Single'
... else:
... print 'More'
...
There can be zero or more elif parts, and the else part is optional. The
keyword `elif' is short for `else if', and is useful to avoid excessive
indentation. An if ... elif ... elif ... sequence is a substitute for the switch or case
statements found in other languages.
for Statements
The for statement in Python differs a bit from what you may be used to in C
or Pascal. Rather than always iterating over an arithmetic progression of
numbers (like in Pascal), or giving the user the ability to define both the
13
iteration step and halting condition (as C), Python's for statement iterates
over the items of any sequence (e.g., a list or a string), in the order that they
appear in the sequence. For example (no pun intended):
>>> # Measure some strings:
... a = ['cat', 'window', 'defenestrate']
>>> for x in a:
... print x, len(x)
...
cat 3
window 6
defenestrate 12
It is not safe to modify the sequence being iterated over in the loop (this can
only happen for mutable sequence types, i.e., lists). If you need to modify
the list you are iterating over, e.g., duplicate selected items, you must
iterate over a copy. The slice notation makes this particularly convenient:
>>> for x in a[:]: # make a slice copy of the entire list
... if len(x) > 6: a.insert(0, x)
...
>>> a
['defenestrate', 'cat', 'window', 'defenestrate']
Defining Functions
We can create a function that writes the Fibonacci series to an arbitrary
boundary:
>>> def fib(n): # write Fibonacci series up to n
... "Print a Fibonacci series up to n"
14
... a, b = 0, 1
... while b < n:
... print b,
... a, b = b, a+b
...
>>> # Now call the function we just defined:
... fib(2000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
The keyword def introduces a function definition. It must be followed by the
function name and the parenthesized list of formal parameters. The
statements that form the body of the function start at the next line, and must
be indented. The first statement of the function body can optionally be a
string literal; this string literal is the function's documentation string, or
docstring.
There are tools which use docstrings to automatically produce online or
printed documentation, or to let the user interactively browse through code;
it's good practice to include docstrings in code that you write, so try to
make a habit of it.
The execution of a function introduces a new symbol table used for the
local variables of the function. More precisely, all variable assignments in a
function store the value in the local symbol table; whereas variable
references first look in the local symbol table, then in the global symbol
table, and then in the table of built-in names. Thus, global variables cannot
be directly assigned a value within a function (unless named in a global
statement), although they may be referenced.
The actual parameters (arguments) to a function call are introduced in the
local symbol table of the called function when it is called; thus, arguments
are passed using call by value (where the value is always an object
reference, not the value of the object).4.1 When a function calls another
function, a new local symbol table is created for that call.
A function definition introduces the function name in the current symbol
table. The value of the function name has a type that is recognized by the
interpreter as a user-defined function. This value can be assigned to another
name which can then also be used as a function. This serves as a general
renaming mechanism:
>>> fib
<function object at 10042ed0>
>>> f = fib
>>> f(100)
1 1 2 3 5 8 13 21 34 55 89
You might object that fib is not a function but a procedure. In Python, like
in C, procedures are just functions that don't return a value. In fact,
technically speaking, procedures do return a value, albeit a rather boring
one. This value is called None (it's a built-in name). Writing the value None
is normally suppressed by the interpreter if it would be the only value
written. You can see it if you really want to:
>>> print fib(0)
None
It is simple to write a function that returns a list of the numbers of the
Fibonacci series, instead of printing it:
>>> def fib2(n): # return Fibonacci series up to n
... "Return a list containing the Fibonacci series up to n"
... result = []
15
... a, b = 0, 1
... while b < n:
... result.append(b) # see below
... a, b = b, a+b
... return result
...
>>> f100 = fib2(100) # call it
>>> f100 # write the result
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
This example, as usual, demonstrates some new Python features:
The return statement returns with a value from a function. return
without an expression argument returns None. Falling off the end of
a procedure also returns None.
The statement result.append(b) calls a method of the list object
result. A method is a function that `belongs' to an object and is
named obj.methodname, where obj is some object (this may be an
expression), and methodname is the name of a method that is
defined by the object's type. Different types define different
methods. Methods of different types may have the same name
without causing ambiguity. (It is possible to define your own object
types and methods, using classes, as discussed later in this tutorial.)
The method append() shown in the example, is defined for list
objects; it adds a new element at the end of the list. In this example
it is equivalent to "result = result + [b]", but more efficient.
Keyword Arguments
Functions can also be called using keyword arguments of the form "keyword
= value". For instance, the following function:
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print "-- This parrot wouldn't", action,
print "if you put", voltage, "Volts through it."
print "-- Lovely plumage, the", type
print "-- It's", state, "!"
16
More on Lists
The list data type has some more methods. Here are all of the methods of
list objects:
append(x)
Add an item to the end of the list; equivalent to a[len(a):] = [x].
extend(L)
Extend the list by appending all the items in the given list;
equivalent to a[len(a):] = L.
insert(i, x)
Insert an item at a given position. The first argument is the index of
the element before which to insert, so a.insert(0, x) inserts at the
front of the list, and a.insert(len(a), x) is equivalent to a.append(x).
remove(x)
Remove the first item from the list whose value is x. It is an error if
there is no such item.
pop([i])
Remove the item at the given position in the list, and return it. If no
index is specified, a.pop() returns the last item in the list. The item
is also removed from the list.
index(x)
Return the index in the list of the first item whose value is x. It is an
error if there is no such item.
count(x)
Return the number of times x appears in the list.
sort()
Sort the items of the list, in place.
reverse()
Reverse the elements of the list, in place.
An example that uses most of the list methods:
>>> a = [66.6, 333, 333, 1, 1234.5]
>>> print a.count(333), a.count(66.6), a.count('x')
210
>>> a.insert(2, -1)
>>> a.append(333)
>>> a
[66.6, 333, -1, 333, 1, 1234.5, 333]
>>> a.index(333)
1
>>> a.remove(333)
>>> a
[66.6, -1, 333, 1, 1234.5, 333]
>>> a.reverse()
>>> a
[333, 1234.5, 1, 333, -1, 66.6]
>>> a.sort()
>>> a
[-1, 1, 66.6, 333, 333, 1234.5]
17
Modules
If you quit from the Python interpreter and enter it again, the definitions
you have made (functions and variables) are lost. Therefore, if you want to
write a somewhat longer program, you are better off using a text editor to
prepare the input for the interpreter and running it with that file as input
instead. This is known as creating a script. As your program gets longer,
you may want to split it into several files for easier maintenance. You may
also want to use a handy function that you've written in several programs
without copying its definition into each program.
To support this, Python has a way to put definitions in a file and use them
in a script or in an interactive instance of the interpreter. Such a file is
called a module; definitions from a module can be imported into other
modules or into the main module (the collection of variables that you have
access to in a script executed at the top level and in calculator mode).
A module is a file containing Python definitions and statements. The file
name is the module name with the suffix .py appended. Within a module,
the module's name (as a string) is available as the value of the global
variable __name__. For instance, use your favorite text editor to create a
file called fibo.py in the current directory with the following contents:
# Fibonacci numbers module
18
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
Packages
Packages are a way of structuring Python's module namespace by using
``dotted module names''. For example, the module name A.B designates a
submodule named "B" in a package named "A". Just like the use of
modules saves the authors of different modules from having to worry about
each other's global variable names, the use of dotted module names saves
the authors of multi-module packages like NumPy or the Python Imaging
Library from having to worry about each other's module names.
Suppose you want to design a collection of modules (a ``package'') for the
uniform handling of sound files and sound data. There are many different
sound file formats (usually recognized by their extension, e.g. .wav, .aiff,
.au), so you may need to create and maintain a growing collection of
modules for the conversion between the various file formats. There are also
many different operations you might want to perform on sound data (e.g.
mixing, adding echo, applying an equalizer function, creating an artificial
stereo effect), so in addition you will be writing a never-ending stream of
modules to perform these operations. Here's a possible structure for your
package (expressed in terms of a hierarchical filesystem):
Sound/ Top-level package
__init__.py Initialize the sound package
Formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
Effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
Filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
The __init__.py files are required to make Python treat the directories as
containing packages; this is done to prevent directories with a common
name, such as "string", from unintentionally hiding valid modules that
19
occur later on the module search path. In the simplest case, __init__.py can
just be an empty file, but it can also execute initialization code for the
4
Chapter
The object-oriented
implementation
NeqSim is built up in a highly object oriented way. Design
patterns have been used as a fundation for the whole
development process of the program.
N
EqSim is built upon well know design patterns in object oriented
programming (Design Patterns by Grad & Booch). The object-oriented
design of the modules has been developed and changed many times
during the last years. The design we have today – will hopefully be the final.
20
The Thermodynamic Module
The main packages are system, phase and component. When you create a
thermodynamic object – you would instaniciate an object from the system
package.
21
A system object holds a vector of phase objects. The number of phase-
objects is dependent on the thermodynamic state of the system. In principle
a system can hold any number of phases.
22
Huron-Vidal mixing rule
Wong-Sandler mixing rule
Electrolyte mixing rule
The component object holds all the data that is specific to a component.
The component properties are read from a database/text file.
It is easy to extend the program with new types of systems, phases and
components. All the diagrams above implements an interface in the top of
the object hierarchy – and this interface tell the object which methods it
must define. Normally very few lines of code have to be typed into the new
object, since you will typically inherit from objects already defined in the
hierarchy.
Thermodynamic operations
The thermodynamic operations are defined in its own object hierarchy. The
structure of this hierarchy is shown in the diagram below:
23
Figure 6 Thermodynamic operations
24
Figure 7 Result dialog from Tpflash
The main packages in the fluid mechanics library developed in this work are
described in this section
25
The process equipment module
26
The process equipment is updated constantly – and new kind of equipment is
added regularly. Normally both a equilibrium process and non-equilibrium
process equipment are added. The equilibrium process is what you find in
common process simulators – and the non-equilibrium process is what is
special for the NeqSim simulator.
The mixer process equipment package e.g. defines the following classes
27
5
Chapter
The thermodynamic
module
The thermodynamic module in NeqSim is built up of
rigorous equation of states and mixing rules. Models for
both non-polar, polar and electrolyte solution are
supported.
Thermodynamic Models
Some of the most used available thermodynamic models are:
PR equation of state
28
Furst and Renon Electroyte Equation of State
NRTL – GE model
Mixing Rules
The available mixing rules are:
Electrolyte Calculations
NeqSim defines models for both strong and weak electrolyte systems. For
strong electrolytes – we assume a complete dissociation into ions – while for
weak electrolytes – we assume partially dissociation into ions
(chemicalReaction package).
The thermodynamic model used for calculations for strong and weak
electrolytes is a modified Furst-Renon equation of State (Solbraa, 2002). The
model assumes 5 contribution to the molecular properties of a system – these 5
terms are
29
Example 1.
The first example shows you how to define a new thermodynamic system, add
a component to the system, and to do a TPflash with this system.
test = thermo('srk',190.0,1.0)
addComponent(test, ‘methane',10.0)
TPflash(test,1)
where
TPflash(system, multiphase)
30
Example 2 Calculation of thermodynamic properties of methane
test = thermo('srk',190.0,1.0)
addComponent(test,'methane',10)
print 'enthalpy ', enthalpy(test,200.0,10.0)
print 'molar mass ', molarmass(test,200.0,10.0)
print 'Z ' , Z(test,200.0,10.0)
31
Example 3
#thermo.TPflash(systemName,1)
TPflash(systemName,0)
enthalpy = enthalpy(systemName)
entropy = entropy(systemName)
molefrac1 = molefrac(systemName,0)
gibbsenergy = gibbsenergy(systemName)
helmholtzenergy = helmholtzenergy(systemName)
density = density(systemName,290)
viscosity = viscosity(systemName)
Z = Z(systemName)
molarmass = molarmass(systemName)
Theprint
result from running ",this
"helmholtzenergy script will be
helmholtzenergy[2]
32
Example 4. 3D-chart with VisAd
from thermoTools.thermoTools import *
reload(thermoTools)
systemName = thermo('srk',290,1.0)
systemName.addComponent('methane', 1.0)
systemName.addComponent('water', 1.0)
systemName.setMixingRule(1)
systemName.initPhysicalProperties()
TPflash(systemName,0)
func = enthalpy
#func = entropy
#func = density
#func = viscosity
z = []
for pres in range(1,10):
a = []
for temp in range(260,450):
a.append(func(systemName,temp,pres)[0])
z.append(a)
graph.clearplot()
f = graph.field(z)
33
Example 4 Strong electrolyte calculation (total association of ions)
system = thermo('electrolyte',298.15,0.01325)
addComponent(system,'Mg++',0.018)
addComponent(system,'Cl-',2*0.018)
addComponent(system,'water',1.0)
print bubp(system)
show(system)
The results from running this script are displayed in the figure below.
34
Example 5. Weak electrolyte calculation (total association of ions)
reactionCheck(system)
mixingRule(system,4)
print bubp(system)
show(system)
35
36
The fluid mechanics
6
Chapter
module
NeqSim is built up in a highly object oriented way…..
T
he fluid mechanics module is used to do numerical calculations for all
kinds of process equipment. These numerical calculations can be
computational demanding – and long computation times often occurs
when we use this module. All fluid mechanical calculations are done with a
one-dimensional one- or two fluid model (depending on the number of phases
present).
The process equipment you would normally simulate with the fluid mechanical
module is
After opening the toolbar – you press the upper toolbar button.
37
When you press this button – the following dialog box will pop up
In the dialog box you set the pipe specifications. A pipe is devided into a given
number of legs – the properties for each leg must be specified and added to the
pipe definition. The properties you have to specify for each leg are
After the properties for each leg is defined – you have to switch to the Solver
frame (in the tabbed frame) in the dialog box.. You will see the following
dialog box:
38
In the Solver dialog frame you select the type of solver you want to use. You
also select the conservation laws to use and which non-equilibrium effects you
want to consider.
If you are sure that you will have maximum one phase – you should select the
one-fluid model as the fluid mechanics model. If two phases can occure – you
must select the two fluid model.
For isothermal flow – you can skip the energy equation. For constant pressure
flow you can skip the mass and momentum equations. If you want to consider
thermodynamic or thermal non-equilibrium effects – you have to mark the
check boxes.
After the desired model has been selected – you click the OK button – and the
NeqSim script will be generated. Such a script is shown in the text box below
39
Reactor flow simulation
In this section we give an example of how you would simulate non-equilibrium
two-phase reactor flow. We begin by opening the fluid-mechanics toolbar – by
selecting view – toolbars – fluid mechanic toolbar on the main menu.
After opening the toolbar – you press the second toolbar button.
More to come……
40
The process system
7
Chapter
module
NeqSim is built up in a highly object oriented way…..
Process Tools
In this section we will present the most commonly used process equipment you
will use in NeqSim. At the moment NeqSim does not support dynamical
calculations – but we are working on implementing a dynamic network solver.
Streams
Streams are objects that connect different process equipment. NeqSim
defines two kinds of streams – these are equilibrium stream (Stream) and
non-equilibrium streams (neqStream). The equilibrium stream assumes that
the fluid is at equilibrium – and returns a fluid system at thermodynamic
equilibrium. The neqStream does not assume equilibrium – and it returns a
copy of the inlet system – not necessarily at equilibrium. You define a
stream by clicking on the process toolbar button:
41
when you click this button – the following dialog box will open
In this dialog box you select the type of stream you want to create – and if
the results from calculations should be visible. You click the OK button
when you have defined the stream. The following script will be generated
Separators
Separators will generate new streams from each of the phases present in the
inlet stream. You define a separator by selecting the button
42
Mixer
Mixers are used to connect different streams – and create one outlet stream.
NeqSim defines two types of mixers (mixer) – equilibrium mixers and
non-equilibrium mixers. (neqmixer).
You open the mixer dialog by clicking the button:
When you select the desired mixer the and click the OK button – the script
will be created.
mixerName = mixer('mixerName')
mixerName.addStream(streamName)
Splitter
The splitter is used to split a stream in to more streams.
Compressor
The compressor is used to increase the pressure of a stream. The
compression is done isentropic – or with a specified isentropic efficiency.
More to be added…..
Expander
The expander is used to decrease the pressure – and to get shaft work.. The
expancion is done isentropic – or with a specified isentropic efficiency.
43
Heater / Cooler
The heater is used to increase/decrease the temperature of a stream to a
specified temperature or with a specified delta T.
Valve
A valve is used to decrease the pressure of a stream. The pressurereduction
is done isenthalpic.
processTools.run()
processTools.view(
44
Example 2. Example of the simulation of a medium large process plant
# Case: Troll-case
8
# By: Even Solbraa
# Date: 01.12.2001 Chapter
from processTools.processTools import *
reload(processTools)
factor1 = 1.0
factor2 = 1.0
mol_sec_TrollA = MSm_day_TrollA*40.0/(3600.0*24.0)
mol_sec_TrollWGP = MSm_day_TrollWGP*40.0/(3600.0*24.0)
T
separator1 = separator(stream1)
fug = system.getPhases()[1].getComponents()[0].getFugasityCoeffisient()
separator2 = separator(stream2)
val = fug/pureFug
print "activity: " + val
stream3 = stream(separator1.getGasOutStream(),"TrollA_gasOut")
return val
stream4 = stream(separator2.getGasOutStream(),"TrollWGP_gasOut")
def setFittingParams(self, i, value):
mixer1 = mixer("mixer1") self.params[i] = value
mixer1.addStream(stream3)
mixer1.addStream(stream4)
he statistic module if i==0: is used for parameter fitting to experimental data. Some
exaples of this self.system.getPhases()[0].getMixingRule().setHVgijParameter(0,1,
module is given in this section
stream5 = stream(mixer1.getOutStream(),"mixerOut")
value)
self.system.getPhases()[1].getMixingRule().setHVgijParameter(0,1, value)
if i==1:
neqheater1 = neqheater(stream5,self.system.getPhases()[0].getMixingRule().setHVgiiParameter(0,1,
"heater1") value)
neqheater1.setdT(-2.5) self.system.getPhases()[1].getMixingRule().setHVgiiParameter(0,1, value)
if(i==2):
stream6 = stream(neqheater1.getOutStream(),"heaterOutEqui")
self.system.getPhases()[0].getMixingRule().setHValphaParameter(0,1, value)
stream7 = neqstream(neqheater1.getOutStream(),"heaterOutNeq")
self.system.getPhases()[1].getMixingRule().setHValphaParameter(0,1, value)
print "tot ant mol" , stream7.getMolarRate()
legHeights = [0,0]#,0,0,0,0,0,0]
print "hei etter"
legPositions = #defines
[0.0, 10.0]#, 62.5, 128.0,
the optimization 190.0, 260.0, 330.0, 400.0]
routines
pipeDiameters = optimizer
[1.025, 1.025]#, 1.025,1.025,1.025,1.025,1.025,
= LevenbergMarquardt() 1.025]
outerTemperature#function
= [295.0, 295.0]#, 295.00, 295.00, 295.00, 295.00, 295.00, 295.00]
= BinaryHVparameterFitToActivityCoefficientFunction()
pipeWallRoughness = [1e-5,
function 1e-5]#, 1e-5, 1e-5, 1e-5, 1e-5, 1e-5, 1e-5]
= fitFunction()
pipe = twophasepipe(stream7, legPositions, pipeDiameters, legHeights, outerTemperature, pipeWallRoughness)
#setting initial guess
guess = [1000,1000]
run() function.setInitialGuess(guess)
processTools.view()
print "hei etter"
#creating a emty list to hold samples
print stream5.getTemperature()
samples = []
#------------------------------------------------------------------
#example of a sample
#definition of the thermodynamic system of the sample
sample_1_System = SystemModifiedFurstElectrolyteEos(298.15,10.00)
sample_1_System.addComponent("water", 100)
sample_1_System.addComponent("MDEA", 10)
sample_1_System.chemicalReactionInit()
sample_1_System.setMixingRule(3) 45
9
Chapter
N
EqSim can be used as a toolbox in Matlab. You can create Python
scripts in NeqSim – and run in Matlab directly. In this way you are
able to use the built in functions in Matlab – in combination with
NeqSim. Some examples of these scripts are given in this section.
Generally we can say that all the methods used by the thermodynamic, process
and fluid mechanics toolbars in NeqSim – also works in Matlab.
46
Example 2 Creating a 3D-graph in Matlab
clear all;
initNeqSim;
test = SystemSrkEos
test.addComponent('methane', 10.0);
test.addComponent('water', 10.0);
test.setMixingRule(2);
i=0;
for temperature = [270:2:290]
i=i+1;
j=0;
temp(i) = temperature;
for pressure = [1:5:100]
j = j+1;
pres(j) = pressure;
test.setTemperature(temperature)
test.setPressure(pressure)
TPflash(test,0);
test.init(3);
numberOfPhases(i,j) = test.getNumberOfPhases;
enthalpy(i,j) = test.getEnthalpy;
density(i,j) = test.getDensity;
internalEnergy(i,j) = test.getInternalEnergy;
molarVolume(i,j) = test.getMolarVolume;
end
end
47
Example 3 Process simulation with Matlab
initNeqSim
processOperations.clearAll
system1 = SystemSrkEos(280,10)
system1.addComponent('methane', 10.0)
system1.addComponent('water', 10.0)
system2 = SystemSrkEos(280,10)
system2.addComponent('methane', 5.0)
system2.addComponent('water', 10.0)
stream1 = stream(system1,'troll1')
stream2 = stream(system2,'troll2')
mixer1 = mixer('troll_mixer')
mixer1.addStream(stream1)
mixer1.addStream(stream2)
separator1 = separator(mixer1.getOutStream,'troll_separator')
valve1 = valve(separator1.getGasOutStream, 5.0, 'troll_valve')
%this is wrong
%resultStream = stream(valve1.getOutStream)
%resultStream.setName('result stream')
processOperations.run
processOperations.displayResult
48
Example 3
initNeqSim
processOperations.clearAll
system1 = SystemSrkEos(280,10)
system1.addComponent('methane', 10.0)
system1.addComponent('water', 10.0)
system2 = SystemSrkEos(280,10)
system2.addComponent('methane', 5.0)
system2.addComponent('water', 10.0)
stream1 = stream(system1,'troll1')
stream2 = stream(system2,'troll2')
mixer1 = mixer('troll_mixer')
mixer1.addStream(stream1)
mixer1.addStream(stream2)
separator1 = separator(mixer1.getOutStream,'troll_separator')
valve1 = valve(separator1.getGasOutStream, 5.0, 'troll_valve')
%this is wrong
%resultStream = stream(valve1.getOutStream)
%resultStream.setName('result stream')
processOperations.run
processOperations.displayResult
In the example below we use Matlab to generate a plot of the vapour pressure
of a weak electrolyte solution at varying temperatures.
reactionCheck(syst)
j=0
for i = (280:360)
j=j+1;
disp 'i',i;
setTemperature(syst,i);
pres(j) = bubp(syst);
end
plot([280:360],pres)
xlabel('Temperature [K]')
ylabel('Pressure [bar]')
title('vapour pressure vs. temperature')
49
The resulting graph is given in the figure below.
50
10
Chapter
FAQ
How do I install NeqSim?
…….
How do I …?
…..
to be written……
51
Index
52
Index 1, 1
A Index 1, 1 W
Index 1, 1 Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1 Index 1, 1
Index 2, 2 Index 2, 2
Index 3, 3 K Index 1, 1
Index 1, 1 Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
L Index 1, 1
B Index 1, 1
Index 1, 1 Index 2, 2
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 2, 2 Index 2, 2
Index 1, 1
C Index 1, 1
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 2, 2
Index 1, 1 M
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 1, 1
D Index 2, 2
Index 1, 1
Index 1, 1 N
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 1, 1
E Index 2, 2
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 2, 2
Index 1, 1 R
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
G S
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 1, 1 Index 2, 2
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 1, 1
H
Index 1, 1 T
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 1, 1 Index 1, 1
Index 2, 2 Index 1, 1
Index 1, 1 Index 2, 2
53
54