Contents

Operability analysis of a multistage membrane separation process for direct air capture (m-DAC) using AVEVA Process Simulation

Author: Vitor Gama, West Virginia University (PhD Student)

To address the impacts of fossil fuel emissions on climate change, CO2 capture has been expanded from point-source capture to CO2 removal from the atmosphere. The figure shows the direct air capture process, which utilizes gas separation membranes for the CO2 removal.

m-DAC Process flow diagram

Figure 1: m-DAC Process flow diagram.

Process Overview: Multistage Membrane-Based Direct Air Capture (DAC)

This process is designed for direct air capture (DAC) of CO2, using a multistage membrane separation approach to concentrate carbon dioxide from atmospheric levels (~420 ppm) to a low-purity product (~5% CO2 molar fraction). The system is engineered to handle approximately 1 megaton of air per year, aligning with urgent climate action goals.

The final CO2-enriched stream is suitable for applications that tolerate lower purity, such as:

  • Algae cultivation
  • Enhanced indoor farming and greenhouses
  • Mineral carbonation processes

Key operations include vacuuming the permeate using vacuum pumps, compressors to restore pressure, and heat exchangers to maintain temperatures to acceptable ranges in order to avoid membrane degradation [8].

Step-by-step set up of Opyrability with AVEVA Process Simulation

Step 1: Necessary imports for connection with APS and for Operability computations:

APS connection import

import simcentralconnect #AVEVA PROCESS SIMULATION REQUIRED IMPORT TO ENABLE CONNECTION

This import is essential to enable communication with APS. Once you have installed and configured your APS, you should be able to find the Scripting Interface files. In it, a step-by-step README file guides the user through enabling the connection.

import numpy as np
from opyrability import AIS2AOS_map, multimodel_rep, OI_eval #Operability algorigthms import from Opyrability library
from scipy.io import savemat

# Instantiating the required interfaces for the scripting interface

sc = simcentralconnect.connect().Result
sm = sc.GetService("ISimulationManager")
vm = sc.GetService("IVariableManager")
snap = sc.GetService("ISnapshotManager")

# Example of how to set options.  API logging is ON by default.  Disabled by changing to 'false'
sc.SetOptions(repr({'Timeout': 500000, 'EnableApiLogging': 'false'}))
SimCentral.Client.Auto loaded from: C:\Program Files\SimSci\SimCentral\Scripting\DotNetFwk

Step 2: Calling the simulation file you want to work with:

simFile = "APS_mDAC"
simName = "APS_mDAC" #WARNING: Sometimes APS might rename your simulation as its opened so always make sure the name of the simulation you are working with aligns with the current opened simulation
nameSnap_FM = "steady" #Note: This is only required in case the user wants to set the simulation to a specific snapshot (Forward mapping case snapshot)
nameSnap_MR = "steady2" #Note: This is only required in case the user wants to set the simulation to a specific snapshot (Multimodel representation case snapshot)

Step 3: Function for double checking if simulation exists:

def open_simulation(simName):
    opened = False
    try:
        opened = sm.OpenSimulation(simName).Result         
    except System.AggregateException as ex:
        if not isinstance(ex.InnerException, System.InvalidOperationException) \
                or "simulation doesn't exists" not in ex.InnerException.Message:
            raise
    return opened



open_simulation(simName)
True

Step 4: Process model function to communicate with APS and Opyrability:

def M(u):

    y = np.zeros(2) #Prealocating outputs
     
    # Membrane properties case - First membrane module study

    # --------- Restarting simulation snapshot before changes -----------------------------
        
    snap.RevertSnapshot(simName,nameSnap_FM)

    #Parameters required for SetVariable method vm.SetVariableValue(<string> simulation name, <object> variable, <object> value, <object> unit, <object> apiOptions)(more on methods and interfaces is available in the AVEVA Scripting Interface documentation)
    vm.SetVariableValue(simName, "MDAC1.QCO2", u[0], "", ).Result 
    vm.SetVariableValue(simName, "MDAC2.QCO2", u[1], "", ).Result

    # --------- Checking solution status ----------------------------- 

    print(f"\nCalling simulation with inputs: {u}")
    try:
        status = sm.GetSimulationStatus(simName).Result #Retrieving solution status of the simulation. Argument [2] holds the boolean value that informs if the solver was capable to solve (True) or not (False) the simulation.
        print(f"Initial simulation status: {str(status[2])}")
    except Exception as e:
        print("Failed to get simulation status:", e) 

    if (status[2]):
        flag_conv = True
    else:
        flag_conv= False

    if flag_conv is True:
        
        # ------------------ PRODUCTIVITY VARIABLES -----------------------------------------

        Feed_flow = vm.GetVariableValue(simName, "Air_feed.F", "kmol/h").Result         
        Permeate = vm.GetVariableValue(simName, "Product.F", "kmol/h", ).Result            
        Purity =  vm.GetVariableValue(simName, "Product.z[CO2]", "mol frac", ).Result       

        # ---------------- AOS VARIABLES --------------------------------------------------
                
        # -------------------- Purity vs. Recovery case study ----------------------
        y[0] = Purity*100
        y[1] = 100*((Permeate*Purity) / (Feed_flow*0.000420))
        
    else:
            # --------- Restarting solver to try again -----------------------------
        
            snap.RevertSnapshot(simName,nameSnap_FM)

            # --------- Checking solution status again-----------------------------   
                
            status = sm.GetSimulationStatus(simName).Result

            print(u[0], u[1],"failed")
            if (status[2]):
                flag_conv = True
            else:
                flag_conv= False
            
            if flag_conv is True:
                            
                # ------------------- MEMBRANE PROPERTIES CASE -------------------------------
                
                #First membrane module study
                                
                vm.SetVariableValue(simName, "MDAC1.QCO2", u[0], "", ).Result
                vm.SetVariableValue(simName, "MDAC2.QCO2", u[1], "", ).Result
            
                       
                # ------------------ PRODUCTIVITY VARIABLES -----------------------------------------

                Feed_flow = vm.GetVariableValue(simName, "Air_feed.F", "kmol/h").Result         
                Permeate = vm.GetVariableValue(simName, "Product.F", "kmol/h", ).Result            
                Purity =  vm.GetVariableValue(simName, "Product.z[CO2]", "mol frac", ).Result                
   
                
                # ---------------- AOS VARIABLES --------------------------------------------------
                
                # -------------------- Purity vs. Recovery case study ----------------------
                y[0] = Purity*100
                y[1] = 100*((Permeate*Purity) / (Feed_flow*0.000420))              
                
            else:
                pass
            
            
    return y #Returning outputs for the Operability study

Step 5: Defining Operability study

The current case study aims to analyze how the membrane’s CO2 permeance on both modules affect the overall capture of CO2 in terms of its purity and recovery.

Input (AIS)

Output (AOS)

CO2 Permeance (Membrane module 1) [GPU]

CO2 purity [mol%]

CO2 Permeance (Membrane module 2) [GPU]

CO2 recovery [%]

#---------------------- OPERABILIY STUDY --------------------------------------------------

AIS_bounds =  np.array([[3.35e-8, 6.7e-06],[3.35e-8, 6.7e-07]]) #AIS bounds definition for the 2 inputs x 2 outputs case study
AIS_resolution =  [10,10] #AIS discretization definition for the 2 inputs x 2 outputs case study
AIS, AOS = AIS2AOS_map(M, AIS_bounds, AIS_resolution) #Forwad mapping call for the 2 inputs x 2 outputs case study
Calling simulation with inputs: [0. 0.]
Initial simulation status: True

Calling simulation with inputs: [3.35e-08, 3.35e-08]
Initial simulation status: True

Calling simulation with inputs: [7.742222222222222e-07, 3.35e-08]
Initial simulation status: True

Calling simulation with inputs: [1.5149444444444445e-06, 3.35e-08]
Initial simulation status: True

Calling simulation with inputs: [2.255666666666667e-06, 3.35e-08]
Initial simulation status: True

Calling simulation with inputs: [2.9963888888888892e-06, 3.35e-08]
Initial simulation status: True

Calling simulation with inputs: [3.7371111111111116e-06, 3.35e-08]
Initial simulation status: True

Calling simulation with inputs: [4.477833333333333e-06, 3.35e-08]
Initial simulation status: True

Calling simulation with inputs: [5.2185555555555555e-06, 3.35e-08]
Initial simulation status: True

Calling simulation with inputs: [5.959277777777778e-06, 3.35e-08]
Initial simulation status: True

Calling simulation with inputs: [6.7e-06, 3.35e-08]
Initial simulation status: True

Calling simulation with inputs: [3.35e-08, 1.0422222222222223e-07]
Initial simulation status: True

Calling simulation with inputs: [7.742222222222222e-07, 1.0422222222222223e-07]
Initial simulation status: True

Calling simulation with inputs: [1.5149444444444445e-06, 1.0422222222222223e-07]
Initial simulation status: True

Calling simulation with inputs: [2.255666666666667e-06, 1.0422222222222223e-07]
Initial simulation status: True

Calling simulation with inputs: [2.9963888888888892e-06, 1.0422222222222223e-07]
Initial simulation status: True

Calling simulation with inputs: [3.7371111111111116e-06, 1.0422222222222223e-07]
Initial simulation status: True

Calling simulation with inputs: [4.477833333333333e-06, 1.0422222222222223e-07]
Initial simulation status: True

Calling simulation with inputs: [5.2185555555555555e-06, 1.0422222222222223e-07]
Initial simulation status: True

Calling simulation with inputs: [5.959277777777778e-06, 1.0422222222222223e-07]
Initial simulation status: True

Calling simulation with inputs: [6.7e-06, 1.0422222222222223e-07]
Initial simulation status: True

Calling simulation with inputs: [3.35e-08, 1.7494444444444446e-07]
Initial simulation status: False
3.35e-08 1.7494444444444446e-07 failed

Calling simulation with inputs: [7.742222222222222e-07, 1.7494444444444446e-07]
Initial simulation status: False
7.742222222222222e-07 1.7494444444444446e-07 failed

Calling simulation with inputs: [1.5149444444444445e-06, 1.7494444444444446e-07]
Initial simulation status: False
1.5149444444444445e-06 1.7494444444444446e-07 failed

Calling simulation with inputs: [2.255666666666667e-06, 1.7494444444444446e-07]
Initial simulation status: False
2.255666666666667e-06 1.7494444444444446e-07 failed

Calling simulation with inputs: [2.9963888888888892e-06, 1.7494444444444446e-07]
Initial simulation status: False
2.9963888888888892e-06 1.7494444444444446e-07 failed

Calling simulation with inputs: [3.7371111111111116e-06, 1.7494444444444446e-07]
Initial simulation status: False
3.7371111111111116e-06 1.7494444444444446e-07 failed

Calling simulation with inputs: [4.477833333333333e-06, 1.7494444444444446e-07]
Initial simulation status: False
4.477833333333333e-06 1.7494444444444446e-07 failed

Calling simulation with inputs: [5.2185555555555555e-06, 1.7494444444444446e-07]
Initial simulation status: False
5.2185555555555555e-06 1.7494444444444446e-07 failed

Calling simulation with inputs: [5.959277777777778e-06, 1.7494444444444446e-07]
Initial simulation status: False
5.959277777777778e-06 1.7494444444444446e-07 failed

Calling simulation with inputs: [6.7e-06, 1.7494444444444446e-07]
Initial simulation status: False
6.7e-06 1.7494444444444446e-07 failed

Calling simulation with inputs: [3.35e-08, 2.4566666666666674e-07]
Initial simulation status: False
3.35e-08 2.4566666666666674e-07 failed

Calling simulation with inputs: [7.742222222222222e-07, 2.4566666666666674e-07]
Initial simulation status: False
7.742222222222222e-07 2.4566666666666674e-07 failed

Calling simulation with inputs: [1.5149444444444445e-06, 2.4566666666666674e-07]
Initial simulation status: False
1.5149444444444445e-06 2.4566666666666674e-07 failed

Calling simulation with inputs: [2.255666666666667e-06, 2.4566666666666674e-07]
Initial simulation status: False
2.255666666666667e-06 2.4566666666666674e-07 failed

Calling simulation with inputs: [2.9963888888888892e-06, 2.4566666666666674e-07]
Initial simulation status: False
2.9963888888888892e-06 2.4566666666666674e-07 failed

Calling simulation with inputs: [3.7371111111111116e-06, 2.4566666666666674e-07]
Initial simulation status: False
3.7371111111111116e-06 2.4566666666666674e-07 failed

Calling simulation with inputs: [4.477833333333333e-06, 2.4566666666666674e-07]
Initial simulation status: False
4.477833333333333e-06 2.4566666666666674e-07 failed

Calling simulation with inputs: [5.2185555555555555e-06, 2.4566666666666674e-07]
Initial simulation status: False
5.2185555555555555e-06 2.4566666666666674e-07 failed

Calling simulation with inputs: [5.959277777777778e-06, 2.4566666666666674e-07]
Initial simulation status: False
5.959277777777778e-06 2.4566666666666674e-07 failed

Calling simulation with inputs: [6.7e-06, 2.4566666666666674e-07]
Initial simulation status: False
6.7e-06 2.4566666666666674e-07 failed

Calling simulation with inputs: [3.35e-08, 3.1638888888888895e-07]
Initial simulation status: False
3.35e-08 3.1638888888888895e-07 failed

Calling simulation with inputs: [7.742222222222222e-07, 3.1638888888888895e-07]
Initial simulation status: False
7.742222222222222e-07 3.1638888888888895e-07 failed

Calling simulation with inputs: [1.5149444444444445e-06, 3.1638888888888895e-07]
Initial simulation status: False
1.5149444444444445e-06 3.1638888888888895e-07 failed

Calling simulation with inputs: [2.255666666666667e-06, 3.1638888888888895e-07]
Initial simulation status: False
2.255666666666667e-06 3.1638888888888895e-07 failed

Calling simulation with inputs: [2.9963888888888892e-06, 3.1638888888888895e-07]
Initial simulation status: False
2.9963888888888892e-06 3.1638888888888895e-07 failed

Calling simulation with inputs: [3.7371111111111116e-06, 3.1638888888888895e-07]
Initial simulation status: False
3.7371111111111116e-06 3.1638888888888895e-07 failed

Calling simulation with inputs: [4.477833333333333e-06, 3.1638888888888895e-07]
Initial simulation status: False
4.477833333333333e-06 3.1638888888888895e-07 failed

Calling simulation with inputs: [5.2185555555555555e-06, 3.1638888888888895e-07]
Initial simulation status: False
5.2185555555555555e-06 3.1638888888888895e-07 failed

Calling simulation with inputs: [5.959277777777778e-06, 3.1638888888888895e-07]
Initial simulation status: False
5.959277777777778e-06 3.1638888888888895e-07 failed

Calling simulation with inputs: [6.7e-06, 3.1638888888888895e-07]
Initial simulation status: False
6.7e-06 3.1638888888888895e-07 failed

Calling simulation with inputs: [3.35e-08, 3.8711111111111117e-07]
Initial simulation status: False
3.35e-08 3.8711111111111117e-07 failed

Calling simulation with inputs: [7.742222222222222e-07, 3.8711111111111117e-07]
Initial simulation status: False
7.742222222222222e-07 3.8711111111111117e-07 failed

Calling simulation with inputs: [1.5149444444444445e-06, 3.8711111111111117e-07]
Initial simulation status: False
1.5149444444444445e-06 3.8711111111111117e-07 failed

Calling simulation with inputs: [2.255666666666667e-06, 3.8711111111111117e-07]
Initial simulation status: False
2.255666666666667e-06 3.8711111111111117e-07 failed

Calling simulation with inputs: [2.9963888888888892e-06, 3.8711111111111117e-07]
Initial simulation status: False
2.9963888888888892e-06 3.8711111111111117e-07 failed

Calling simulation with inputs: [3.7371111111111116e-06, 3.8711111111111117e-07]
Initial simulation status: False
3.7371111111111116e-06 3.8711111111111117e-07 failed

Calling simulation with inputs: [4.477833333333333e-06, 3.8711111111111117e-07]
Initial simulation status: False
4.477833333333333e-06 3.8711111111111117e-07 failed

Calling simulation with inputs: [5.2185555555555555e-06, 3.8711111111111117e-07]
Initial simulation status: False
5.2185555555555555e-06 3.8711111111111117e-07 failed

Calling simulation with inputs: [5.959277777777778e-06, 3.8711111111111117e-07]
Initial simulation status: False
5.959277777777778e-06 3.8711111111111117e-07 failed

Calling simulation with inputs: [6.7e-06, 3.8711111111111117e-07]
Initial simulation status: False
6.7e-06 3.8711111111111117e-07 failed

Calling simulation with inputs: [3.35e-08, 4.578333333333334e-07]
Initial simulation status: False
3.35e-08 4.578333333333334e-07 failed

Calling simulation with inputs: [7.742222222222222e-07, 4.578333333333334e-07]
Initial simulation status: False
7.742222222222222e-07 4.578333333333334e-07 failed

Calling simulation with inputs: [1.5149444444444445e-06, 4.578333333333334e-07]
Initial simulation status: False
1.5149444444444445e-06 4.578333333333334e-07 failed

Calling simulation with inputs: [2.255666666666667e-06, 4.578333333333334e-07]
Initial simulation status: False
2.255666666666667e-06 4.578333333333334e-07 failed

Calling simulation with inputs: [2.9963888888888892e-06, 4.578333333333334e-07]
Initial simulation status: False
2.9963888888888892e-06 4.578333333333334e-07 failed

Calling simulation with inputs: [3.7371111111111116e-06, 4.578333333333334e-07]
Initial simulation status: False
3.7371111111111116e-06 4.578333333333334e-07 failed

Calling simulation with inputs: [4.477833333333333e-06, 4.578333333333334e-07]
Initial simulation status: False
4.477833333333333e-06 4.578333333333334e-07 failed

Calling simulation with inputs: [5.2185555555555555e-06, 4.578333333333334e-07]
Initial simulation status: False
5.2185555555555555e-06 4.578333333333334e-07 failed

Calling simulation with inputs: [5.959277777777778e-06, 4.578333333333334e-07]
Initial simulation status: False
5.959277777777778e-06 4.578333333333334e-07 failed

Calling simulation with inputs: [6.7e-06, 4.578333333333334e-07]
Initial simulation status: False
6.7e-06 4.578333333333334e-07 failed

Calling simulation with inputs: [3.35e-08, 5.285555555555556e-07]
Initial simulation status: False
3.35e-08 5.285555555555556e-07 failed

Calling simulation with inputs: [7.742222222222222e-07, 5.285555555555556e-07]
Initial simulation status: False
7.742222222222222e-07 5.285555555555556e-07 failed

Calling simulation with inputs: [1.5149444444444445e-06, 5.285555555555556e-07]
Initial simulation status: False
1.5149444444444445e-06 5.285555555555556e-07 failed

Calling simulation with inputs: [2.255666666666667e-06, 5.285555555555556e-07]
Initial simulation status: False
2.255666666666667e-06 5.285555555555556e-07 failed

Calling simulation with inputs: [2.9963888888888892e-06, 5.285555555555556e-07]
Initial simulation status: False
2.9963888888888892e-06 5.285555555555556e-07 failed

Calling simulation with inputs: [3.7371111111111116e-06, 5.285555555555556e-07]
Initial simulation status: False
3.7371111111111116e-06 5.285555555555556e-07 failed

Calling simulation with inputs: [4.477833333333333e-06, 5.285555555555556e-07]
Initial simulation status: False
4.477833333333333e-06 5.285555555555556e-07 failed

Calling simulation with inputs: [5.2185555555555555e-06, 5.285555555555556e-07]
Initial simulation status: False
5.2185555555555555e-06 5.285555555555556e-07 failed

Calling simulation with inputs: [5.959277777777778e-06, 5.285555555555556e-07]
Initial simulation status: False
5.959277777777778e-06 5.285555555555556e-07 failed

Calling simulation with inputs: [6.7e-06, 5.285555555555556e-07]
Initial simulation status: False
6.7e-06 5.285555555555556e-07 failed

Calling simulation with inputs: [3.35e-08, 5.992777777777778e-07]
Initial simulation status: False
3.35e-08 5.992777777777778e-07 failed

Calling simulation with inputs: [7.742222222222222e-07, 5.992777777777778e-07]
Initial simulation status: False
7.742222222222222e-07 5.992777777777778e-07 failed

Calling simulation with inputs: [1.5149444444444445e-06, 5.992777777777778e-07]
Initial simulation status: False
1.5149444444444445e-06 5.992777777777778e-07 failed

Calling simulation with inputs: [2.255666666666667e-06, 5.992777777777778e-07]
Initial simulation status: False
2.255666666666667e-06 5.992777777777778e-07 failed

Calling simulation with inputs: [2.9963888888888892e-06, 5.992777777777778e-07]
Initial simulation status: False
2.9963888888888892e-06 5.992777777777778e-07 failed

Calling simulation with inputs: [3.7371111111111116e-06, 5.992777777777778e-07]
Initial simulation status: False
3.7371111111111116e-06 5.992777777777778e-07 failed

Calling simulation with inputs: [4.477833333333333e-06, 5.992777777777778e-07]
Initial simulation status: False
4.477833333333333e-06 5.992777777777778e-07 failed

Calling simulation with inputs: [5.2185555555555555e-06, 5.992777777777778e-07]
Initial simulation status: False
5.2185555555555555e-06 5.992777777777778e-07 failed

Calling simulation with inputs: [5.959277777777778e-06, 5.992777777777778e-07]
Initial simulation status: False
5.959277777777778e-06 5.992777777777778e-07 failed

Calling simulation with inputs: [6.7e-06, 5.992777777777778e-07]
Initial simulation status: False
6.7e-06 5.992777777777778e-07 failed

Calling simulation with inputs: [3.35e-08, 6.7e-07]
Initial simulation status: False
3.35e-08 6.7e-07 failed

Calling simulation with inputs: [7.742222222222222e-07, 6.7e-07]
Initial simulation status: False
7.742222222222222e-07 6.7e-07 failed

Calling simulation with inputs: [1.5149444444444445e-06, 6.7e-07]
Initial simulation status: False
1.5149444444444445e-06 6.7e-07 failed

Calling simulation with inputs: [2.255666666666667e-06, 6.7e-07]
Initial simulation status: False
2.255666666666667e-06 6.7e-07 failed

Calling simulation with inputs: [2.9963888888888892e-06, 6.7e-07]
Initial simulation status: False
2.9963888888888892e-06 6.7e-07 failed

Calling simulation with inputs: [3.7371111111111116e-06, 6.7e-07]
Initial simulation status: False
3.7371111111111116e-06 6.7e-07 failed

Calling simulation with inputs: [4.477833333333333e-06, 6.7e-07]
Initial simulation status: False
4.477833333333333e-06 6.7e-07 failed

Calling simulation with inputs: [5.2185555555555555e-06, 6.7e-07]
Initial simulation status: False
5.2185555555555555e-06 6.7e-07 failed

Calling simulation with inputs: [5.959277777777778e-06, 6.7e-07]
Initial simulation status: False
5.959277777777778e-06 6.7e-07 failed

Calling simulation with inputs: [6.7e-06, 6.7e-07]
Initial simulation status: False
6.7e-06 6.7e-07 failed
../_images/d3def2673ffd3f81e4acef9fdd7dc1a9eddc3c09451f55ffb4dd354b69f7fb27.png

The AIS axes represent the CO2 permeance of each membrane module (u1 = membrane module 1 and u2 = membrane module 2).

The AOS axes show the outputs of the simulation (y1 = CO2 purity in mol% and y2 = CO2 recovery in %). The color gradient maps input cases to their respective outputs, and a proportional relationship can be observed between CO2 purity and recovery as the membrane properties vary. This showcases Opyrability’s capability to assess process outcomes via the manipulation of input variables.

Multimodel representation

This section covers the application of another feature of the Opyrability package, the multimodel representation. With it, it is possible to generate an AOS visualization using paired polytopes, which could assist in effective OI calculations.

Process model function for Multimodel case:

def Multi(u):

    y = np.zeros(2) #Prealocating outputs
     
    # Membrane properties case - First membrane module study

    # --------- Restarting simulation snapshot before changes -----------------------------
        
    snap.RevertSnapshot(simName,nameSnap_MR)

    #Parameters required for SetVariable method vm.SetVariableValue(<string> simulation name, <object> variable, <object> value, <object> unit, <object> apiOptions)(more on methods and interfaces is available in the AVEVA Scripting Interface documentation)
    vm.SetVariableValue(simName, "MDAC1.Nt", u[0], "", ).Result 
    vm.SetVariableValue(simName, "MDAC2.Nt", u[1], "", ).Result

    # --------- Checking solution status ----------------------------- 

    print(f"\nCalling simulation with inputs: {u}")
    try:
        status = sm.GetSimulationStatus(simName).Result #Retrieving solution status of the simulation. Argument [2] holds the boolean value that informs if the solver was capable to solve (True) or not (False) the simulation.
        print(f"Initial simulation status: {str(status[2])}")
    except Exception as e:
        print("Failed to get simulation status:", e) 

    if (status[2]):
        flag_conv = True
    else:
        flag_conv= False

    if flag_conv is True:
        
        # ------------------ PRODUCTIVITY VARIABLES -----------------------------------------

        Feed_flow = vm.GetVariableValue(simName, "Air_feed.F", "kmol/h").Result         
        Permeate = vm.GetVariableValue(simName, "Product.F", "kmol/h", ).Result            
        Purity =  vm.GetVariableValue(simName, "Product.z[CO2]", "mol frac", ).Result       

        # ---------------- AOS VARIABLES --------------------------------------------------
                
        # -------------------- Purity vs. Recovery case study ----------------------
        y[0] = Purity*100
        y[1] = 100*((Permeate*Purity) / (Feed_flow*0.000420))
        
    else:
            # --------- Restarting solver to try again -----------------------------
        
            snap.RevertSnapshot(simName,nameSnap_MR)

            # --------- Checking solution status again-----------------------------   
                
            status = sm.GetSimulationStatus(simName).Result

            print(u[0], u[1],"failed")
            if (status[2]):
                flag_conv = True
            else:
                flag_conv= False
            
            if flag_conv is True:
                            
                # ------------------- MEMBRANE PROPERTIES CASE -------------------------------
                
                #First membrane module study
                                
                vm.SetVariableValue(simName, "MDAC1.Nt", u[0], "", ).Result
                vm.SetVariableValue(simName, "MDAC2.Nt", u[1], "", ).Result
            
                       
                # ------------------ PRODUCTIVITY VARIABLES -----------------------------------------

                Feed_flow = vm.GetVariableValue(simName, "Air_feed.F", "kmol/h").Result         
                Permeate = vm.GetVariableValue(simName, "Product.F", "kmol/h", ).Result            
                Purity =  vm.GetVariableValue(simName, "Product.z[CO2]", "mol frac", ).Result                
   
                
                # ---------------- AOS VARIABLES --------------------------------------------------
                
                # -------------------- Purity vs. Recovery case study ----------------------
                y[0] = Purity*100
                y[1] = 100*((Permeate*Purity) / (Feed_flow*0.000420))              
                
            else:
                pass
            
            
    return y #Returning outputs for the Operability study

Defining Operability study used for multimodel representation

The current case study analyzes how the available membrane surface area (manipulated through the module’s number of fibers) affects the overall capture of CO2 in terms of CO2 purity and recovery.

Input (AIS)

Output (AOS)

Membrane module 1 number of fibers

CO2 purity [mol%]

Membrane module 2 number of fibers

CO2 recovery [%]

#---------------------- MULTIMODEL REPRESENTATION STUDY --------------------------------------------------

AIS_bounds =  np.array([[8e5, 1.3e6],[1.5e5, 3.5e5]]) #AIS bounds definition for the 2 inputs x 2 outputs case study

AIS_resolution =  [5,5] #AIS discretization definition 

AOS_reg = multimodel_rep(Multi, AIS_bounds, AIS_resolution) #Multimodel representation call
Calling simulation with inputs: [800000. 150000.]
Initial simulation status: True

Calling simulation with inputs: [800000.0, 150000.0]
Initial simulation status: True

Calling simulation with inputs: [925000.0, 150000.0]
Initial simulation status: True

Calling simulation with inputs: [1050000.0, 150000.0]
Initial simulation status: True

Calling simulation with inputs: [1175000.0, 150000.0]
Initial simulation status: True

Calling simulation with inputs: [1300000.0, 150000.0]
Initial simulation status: True

Calling simulation with inputs: [800000.0, 200000.0]
Initial simulation status: True

Calling simulation with inputs: [925000.0, 200000.0]
Initial simulation status: True

Calling simulation with inputs: [1050000.0, 200000.0]
Initial simulation status: True

Calling simulation with inputs: [1175000.0, 200000.0]
Initial simulation status: True

Calling simulation with inputs: [1300000.0, 200000.0]
Initial simulation status: True

Calling simulation with inputs: [800000.0, 250000.0]
Initial simulation status: True

Calling simulation with inputs: [925000.0, 250000.0]
Initial simulation status: True

Calling simulation with inputs: [1050000.0, 250000.0]
Initial simulation status: True

Calling simulation with inputs: [1175000.0, 250000.0]
Initial simulation status: True

Calling simulation with inputs: [1300000.0, 250000.0]
Initial simulation status: True

Calling simulation with inputs: [800000.0, 300000.0]
Initial simulation status: True

Calling simulation with inputs: [925000.0, 300000.0]
Initial simulation status: True

Calling simulation with inputs: [1050000.0, 300000.0]
Initial simulation status: True

Calling simulation with inputs: [1175000.0, 300000.0]
Initial simulation status: True

Calling simulation with inputs: [1300000.0, 300000.0]
Initial simulation status: True

Calling simulation with inputs: [800000.0, 350000.0]
Initial simulation status: True

Calling simulation with inputs: [925000.0, 350000.0]
Initial simulation status: True

Calling simulation with inputs: [1050000.0, 350000.0]
Initial simulation status: True

Calling simulation with inputs: [1175000.0, 350000.0]
Initial simulation status: True

Calling simulation with inputs: [1300000.0, 350000.0]
Initial simulation status: True
../_images/1c5797ea7450e62cd4ae653bc7ea378515ebfaed1138f934ff3867ba66e1c59c.png

Based on the region generated, the OI evaluation will provide a perspective on process’ operability within the DOS outlined for this case.

Desired Output Set (DOS)

CO2 purity [mol%] (y1)

3 - 7

CO2 recovery [%] (y2)

11 - 15

OI evaluation

DOS_bounds =  np.array([[3, 7], 
                            [11, 15]])
OI = OI_eval(AOS_reg, DOS_bounds)
../_images/218573051c93aebd586ee3c4060eb93412473505d7f5acac17035f041d8c6183.png

The OI calculation shows that within the DOS the process is 70.61% operable.