Introduction

Intended audience

Model Users who want to programmatically control their models via the Python scripting language.

System integrator and app developers who want to develop solutions based on the modeling of industrial continuous processes with the LIBPF™ enabling technology, in particular solutions which interact with process models via scripts or automation.

Scope

This document is the manual for the Python incarnation of the LIBPF™ high level Model User API, a simple, high-level API to manage and use process models who have been previously prepared and deployed by model developers.

The LIBPF™ Python Model User API is a SWIG-wrapped version of the C++ Model User API.

Prerequisites

  • having received and installed a LIBPF™ model

  • knowledge of the Python scripting language

  • acquaintance with the field of industrial continuous processes

  • the roles involved with the lifecycle of solutions developed using the LIBPF™ enabling technology, see LIBPF™ Technology Introduction

  • a general knowledge of the concepts of the LIBPF™ high level Model User API, see LIBPF™ Model User API documentation

  • to import successfully the LibpfUserPython module in python, the files LibpfUserPython.py and _LibpfUserPython.so should be present in the current directory

Python interface

Start your Python interpreter and import the LibpfUserPython model:

import LibpfUserPython

Before performing any operation with the LibpfUserPython module, you should call the LibpfUserPython.initializeKernel() method.

Kernel API

The capabilities of the Kernel API can be queried with the command:

dir(LibpfUserPython)

apiVersion

Query the Model User API version

Parameters:

  • (output) error: an intPointer object; on exit contains an error code; the code is 0 if the operation was successful; to obtain more descriptive error codes, use the LibpfUserPython.errorMessage function to convert the code in a human-readable description

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
error = LibpfUserPython.intPointer()
error.assign(1)
apiVersion = LibpfUserPython.apiVersion(error)
print 'error', error.value(), ' message', LibpfUserPython.errorMessage(error.value())
print 'API version = ' + apiVersion

createCase

Creates a new case instance.

Parameters:

  • (input) cdj: a string containing a UTF-8 encoded, JSON-serialized CaseDescriptor object; for more information see the Doxygen-generated reference documentation for the LIBPF™ C++ Model User API section on the CaseDescriptor class.

  • (output) error: an intPointer object; on exit contains an error code; the code is 0 if the operation was successful; to obtain more descriptive error codes, use the LibpfUserPython.errorMessage function to convert the code in a human-readable description

Returns a valid, persistent Case handle on success, or an invalid Handle if there was an error.

A valid returned Handle can be used to access the case instance.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
error = LibpfUserPython.intPointer()
error.assign(1)
ch = LibpfUserPython.createCase('{"type":"Pasteur"}', error)
print 'error', error.value(), ' message', LibpfUserPython.errorMessage(error.value())
print 'ch = ', ch.value()

in this example the JSON string is supplied directly, and contains the only really required field: the type.

The following, more elaborate example uses the Python built-in json module (JSON encoder and decoder) to create the JSON string from a dictionary.

import json, LibpfUserPython
LibpfUserPython.initializeKernel()
error = LibpfUserPython.intPointer()
error.assign(1)
so = { u'a': u'b', u'c':u'd', u'e':u'f' }
io = { u'g': 1, u'h':2 }
cd = { u'type': u'SaltPepper', 
  u'tag': u'case123', 
  u'description': u'case with 1 2 3 times', 
  u'stringOptions': so, 
  u'integerOptions': io }
cdj = json.dumps(cd)
ch = LibpfUserPython.createCase(cdj, error)
print error.value()
print 'ch = ', ch.value()

defaultType

Returns the default model type that createCase will instantiate if the JSON string supplied to LibpfUserPython.createCase is empty.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
dt = LibpfUserPython.defaultType()
print 'default type = ', dt

description

Returns the kernel description as an UTF-8 encoded string

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
d = LibpfUserPython.description()
print 'kernel description = ', d

duplicate

Duplicate an existing case instance

Parameters:

  • (input) handle: the existing case handle

  • (input) tag: tag string for the new Case instance, UTF-8 encoded string

  • (input) description: description string for the new Case instance, UTF-8 encoded string

  • (output) error: an intPointer object; on exit contains an error code; the code is 0 if the operation was successful; to obtain more descriptive error codes, use the LibpfUserPython.errorMessage function to convert the code in a human-readable description

Returns the new case instance handle, or an invalid Handle in case of error

import LibpfUserPython
LibpfUserPython.initializeKernel()
h1 = LibpfUserPython.Handle('0')
error = LibpfUserPython.intPointer()
error.assign(1)
h2 = duplicate(h1, 'new tag', 'new description', error)
print h2.value()

errorMessage

Parameters:

  • (input) error: one of the values of the ErrorCode enum

Returns the textual representation of the error

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
error = LibpfUserPython.intPointer()
error.assign(1)
enumerator = LibpfUserPython.jsonEnumerator('aaaaaaaaaaaaaaaaa', error)
print 'error', error.value(), ' message', LibpfUserPython.errorMessage(error.value())

initializeKernel

This function initializes the library and the kernel, in detail:

  • sets verbosityGlobal to 2

  • initializes several internal LIBPF™ global data structures

  • fills in the component list

  • registers the kernel as a product

  • registers the kernel-supplied enumerators and types

  • prints the startup banner

It should be called at least once before performing any operation with the library.

This function executes these initializations only once discarding subsequent calls.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()

intPointer

Creates an integer variable pointer, which can be supplied as a parameter to all the LIBPF™ Python Model User API functions that take an error parameter rather than returning an integer.

After the function returns, the error code can be accessed via the value method.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
error = LibpfUserPython.intPointer()
error.assign(1)
print error.value()

jsonEnumerator

Parameters:

  • (input) name: the name of the enumerator

  • (output) error: an intPointer object; on exit contains an error code; the code is 0 if the operation was successful; to obtain more descriptive error codes, use the LibpfUserPython.errorMessage function to convert the code in a human-readable description

Returns a UTF-8 encoded string with the JSON-serialized Enumerator object, or an empty JSON object if there was a problem

Example usage:

import LibpfUserPython, json
LibpfUserPython.initializeKernel()
error = LibpfUserPython.intPointer()
error.assign(1)
je = LibpfUserPython.jsonEnumerator('feedType', error)
if (error.value() == 0):
    e = json.loads(je)
    print 'feedType = ', e

Sample returned JSON:

{
  "name": "feedType",
  "description": "Feed type selection - It selects the fluid composition to be pasteurization",
  "options": [
    {
      "name": "milkWhole",
      "description": "Milk, whole, 3.25% milkfat, with added vitamin D"
    },
    {
      "name": "chocolateIceCream",
      "description": "Ice cream, soft serve, chocolate"
    },
    {
      "name": "eggWhole",
      "description": "Egg, whole, raw, fresh"
    },
    {
      "name": "vanillaFatFreeIceCream",
      "description": "Ice creams, BREYERS, 98% Fat Free Vanilla"
    },
    {
      "name": "user",
      "description": "(default) user specified defaults to pure water"
    }
  ]
}

jsonListTypes

Queries the available types

Parameters:

  • error: an intPointer object

Returns UTF-8 encoded string with the JSON-serialized list of TypeDescriptor objects, or an empty JSON object if there was a problem.

Example usage:

import LibpfUserPython, json
LibpfUserPython.initializeKernel()
error = LibpfUserPython.intPointer()
error.assign(1)
jlt = LibpfUserPython.jsonListTypes(error)
if (error.value() == 0):
    lt = json.loads(jlt)
    print 'listTypes = ', lt

Sample returned JSON:

{
  "types": [
    {
      "name": "chiller",
      "description": "packaged chiller unit",
      "category": "flowsheet",
      "instantiable": true,
      "integerOptions": [
        {
          "name": "stages",
          "value": 2,
          "min": 1,
          "max": 10
        }
      ],
      "stringOptions": [
        {
          "name": "type",
          "value": "scroll",
          "enumerator": "compressorType"
        }
      ]
    }
  ]
}

jsonTypeDescriptor

Queries a specific type

Parameters:

  • name the name of the type to query

  • error: an intPointer object

Returns UTF-8 encoded string with the JSON-serialized TypeDescriptor object, or an empty JSON object if there was a problem

Example usage:

import LibpfUserPython, json
LibpfUserPython.initializeKernel()
error = LibpfUserPython.intPointer()
error.assign(1)
jtd = LibpfUserPython.jsonTypeDescriptor('Pasteur', error)
if (error.value() == 0):
    td = json.loads(jtd)
    print 'Paster = ', td

Sample returned JSON:

{
  "name": "chiller",
  "description": "packaged chiller unit",
  "category": "flowsheet",
  "instantiable": true,
  "integerOptions": [
    {
      "name": "stages",
      "value": 2,
      "min": 1,
      "max": 10
    }
  ],
  "stringOptions": [
    {
      "name": "type",
      "value": "scroll",
      "enumerator": "compressorType"
    }
  ]
}

license

Returns the kernel license as an UTF-8 encoded string

Example usage:

import LibpfUserPython, json
print 'license = ', LibpfUserPython.license()

listEnumerators

Queries the available enumerators

Parameters

  • (output) error: an intPointer object; on exit contains an error code; the code is 0 if the operation was successful; to obtain more descriptive error codes, use the LibpfUserPython.errorMessage function to convert the code in a human-readable description

Returns a list of the available enumerators as strings.

Example usage:

import LibpfUserPython, json
LibpfUserPython.initializeKernel()
error = LibpfUserPython.intPointer()
error.assign(1)
le = LibpfUserPython.listEnumerators(error)
if (error.value() == 0):
    for e in le:
        print json = json + '"' + enumerator + '"'

name

Returns the kernel name as an UTF-8 encoded string

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
n = LibpfUserPython.name()
print 'kernel name = ', n

purge

Remove all existing case instances

Returns the error code; the code is 0 if the operation was successful; to obtain more descriptive error codes, use the LibpfUserPython.errorMessage function to convert the code in a human-readable description

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
error = LibpfUserPython.purge()

remove

Remove an existing case instance

Parameters:

  • handle: the existing case handle

Returns error code; the code is 0 if the operation was successful; to obtain more descriptive error codes, use the LibpfUserPython.errorMessage function to convert the code in a human-readable description

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
error = LibpfUserPython.remove(ch);

setVerbosityGlobal

Sets the global verbosity level:

  • 0 for high-priority messages

  • 1 for informational messages

  • 2 for function and member function entry/exit

  • 3 for detailed diagnostic

Parameters:

  • verbosity: global verbosity level

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
LibpfUserPython.setVerbosityGlobal(3)

uninitializeKernel

Frees all resources acquired by initializeKernel.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
LibpfUserPython.uninitializeKernel()

version

Returns the kernel version as an UTF-8 encoded string

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
v = LibpfUserPython.version()
print 'kernel version = ', v

Case API

The capabilities of the Case API can be queried with the command:

dir(LibpfUserPython.Case)

constructor

Establishes a connection to the case

Parameters:

  • handle: case handle

If the handle is invalid or there is an error, the Case is instantiated in the invalid state.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)

calculateSync

Synchronously calculate the case.

Returns the error code.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
error = c.calculateSync()

errorMessage

Parameters:

  • error: one of the values of the ErrorCode enum

Returns the textual representation of the error

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
error = c.calculateSync()
print 'error', error.value(), ' message', c.errorMessage(error.value())

exportDataBase

Export database snapshot of all data related to the case instance in sqlite3 format

Parameters:

  • sqliteFileName: full path to the sqlite database binary format file that should be written; if the file exists, it will be overwritten

Returns the error code.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
error = c.exportDataBase('0.sqlite')

exportSvg

Export to SVG format, saving a file handle.svg

Parameters:

  • tiny: if true, print the layout to SVG Tiny 1.1 format, else to Full SVG 1.1 format

Returns the error code.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
error = c.exportSvg('0.svg')

exportTxt

Export text file report of all data related to the case instance

Parameters:

  • txtFileName: full path to the text format file that should be written; if the file exists, it will be overwritten

Returns the error code.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
error = c.exportTxt('0.txt')

exportXml

Export to XML: recursively print all Quantities, Strings and Integers to xml files in the directory dir

Parameters:

  • dir: the directory to save files to

Returns the error code.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
error = c.exportXml('0')

get

Query the value of a Quantity

Parameters:

  • path: the string full path to the variable, i.e. S01:Tphase.ndot

  • error: an intPointer object

Returns the current value in SI units

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
error = LibpfUserPython.intPointer()
error.assign(1)
value = c.get('S01:Tphase.ndot', error)

getInteger

Query the value of an Integer

Parameters:

  • path: the string full path to the variable, i.e. C101.nStage

  • error: an intPointer object

Returns the current value

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
error = LibpfUserPython.intPointer()
error.assign(1)
value = c.getInteger('C101.nStage', error)

getString

Query the value of a String

Parameters:

  • path: the string full path to the variable, i.e. S01.flashoption

  • error: an intPointer object

Returns the current value

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
error = LibpfUserPython.intPointer()
error.assign(1)
value = c.getString('S01.flashoption', error)

homotopySync

Synchronously perform a homotopy calculation of the case.

Parameters:

  • homotopyInput: UTF-8 encoded, JSON-serialized HomotopyInput object with the information on the changes to be applied

Returns the error code.

Example usage:

import LibpfUserPython, json
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
cv = [ 
    { 
        u'variable': u'S01.T', 
        u'start': 298.15, 
        u'end': 300
    }, { 
        u'variable': u'RX:reactions[0].z', 
        u'start': 0.9, 
        u'end': 0.95 
    } ]
hi = { u'type': u'SaltPepper', 
    u'id': int(ch.value()), 
    u'points': 20, 
    u'controlled': cv }
jhi = json.dumps(hi)
error = c.homotopySync(jhi)

isValid

Returns true if the Case is valid

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
print c.isValid()

sensitivitySync

Synchronously perform a sensitivity calculation of the case.

Parameters:

  • sensitivityInput: UTF-8 encoded, JSON-serialized SensitivityInput object with the information on the sensitivity to perform

Returns the error code.

Example usage:

import LibpfUserPython, json
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
cv = [ { 
        u'variable': u'FILTER.outSplit[0][2]', 
        u'label': u'Filter efficiency', 
        u'unit': u'', 
        u'start': 0.9, 
        u'end': 0.99, 
        u'points': 3 
    }, {
        u'variable': u'RX:reactions[0].z', 
        u'label': u'Product conversion', 
        u'unit': u'', 
        u'start': 0.9, 
        u'end': 0.95, 
        u'points': 3
    }, {
        u'variable': u'SPL.outSplit[0]', 
        u'label': u'Purge fraction', 
        u'unit': u'', 
        u'start': 0.8, 
        u'end': 0.98, 
        u'points': 3
    } ]
mv = [ 
    { 
        u'variable': u'S01.T', 
        u'label': u'temperature', 
        u'unit': u'Ku'
    }, {
        u'variable': u'S01:Tphase.mdot', 
        u'label': u'mass flow', 
        u'unit': u'kg/h' 
    } ]
si = { u'type': u'SaltPepper', 
    u'name': u'aaaaaaaaa', 
    u'order': u'boustrophedon', 
    u'startinground': 0, 
    u'timeout': 0.0, 
    u'controlled': cv, 
    u'manipulated': mv }
jsi = json.dumps(si)
error = c.sensitivitySync(jsi)

set

Set one or more quantities

Parameters:

  • homotopyInput: UTF-8 encoded, JSON-serialized HomotopyInput object with the information on the changes to be applied; not all fields must be filled in, basically what is required is the controlled array be non-empty and each element of the controlled array be a dictionary with at least two keys, value and end

Returns the error code.

Example usage:

import LibpfUserPython, json
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
cv = [ 
    { 
        u'variable': u'S01.T', 
        u'end': 300 }, 
    { 
        u'variable': u'RX:reactions[0].z', 
        u'end': 0.95 
    } 
  ]
hi = { u'controlled': cv }
jhi = json.dumps(hi)
error = c.set(jhi)

setDescription

Change the description of the instance

Parameters

  • desc UTF-8 encoded string with the new description

Returns the error code.

Example usage:

import LibpfUserPython, json
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
error = c.setDescrition('test case')

setTag

Change the tag of the instance

Parameters

  • tag: UTF-8 encoded string with the new tag

Returns the error code.

Example usage:

import LibpfUserPython, json
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
c = LibpfUserPython.Case(ch)
error = c.setTest('test')

Handle API

The capabilities of the handle API can be queried with the command:

dir(LibpfUserPython.Handle)

constructor

Instantiates the Handle

Parameters:

  • value: a string representation of the Handle

If the value is invalid the Handle is instantiated in the invalid state.

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')

isValid

Returns true if the Handle is valid

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
print ch.isValid()

value

Returns a string representation of the Handle

Example usage:

import LibpfUserPython
LibpfUserPython.initializeKernel()
ch = LibpfUserPython.Handle('0')
print ch.value()